or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

enum-system.mdfield-system.mdindex.mdmarshal-system.mdmessage-system.mdmodule-system.md

field-system.mddocs/

0

# Field System

1

2

The Field system provides the building blocks for defining message structure in proto-plus. Fields define the data members of protocol buffer messages, handling type validation, serialization, and providing the mapping between Python attributes and protocol buffer fields.

3

4

## Capabilities

5

6

### Basic Field Definition

7

8

Define individual fields within protocol buffer messages using the Field class.

9

10

```python { .api }

11

class Field:

12

"""

13

A representation of a type of field in protocol buffers.

14

15

Args:

16

proto_type: The protocol buffer type (ProtoType enum value or message/enum class)

17

number (int): The field number in the protocol buffer definition

18

message: Message class for MESSAGE type fields

19

enum: Enum class for ENUM type fields

20

oneof (str): Name of oneof group this field belongs to

21

json_name (str): Custom JSON field name

22

optional (bool): Whether this is an optional field (proto3)

23

"""

24

def __init__(self, proto_type, *, number: int, message=None, enum=None,

25

oneof: str = None, json_name: str = None, optional: bool = False): ...

26

27

@property

28

def name(self) -> str:

29

"""Return the name of the field."""

30

31

@property

32

def package(self) -> str:

33

"""Return the package of the field."""

34

35

@property

36

def pb_type(self):

37

"""Return the composite type of the field, or the primitive type if a primitive."""

38

39

@property

40

def descriptor(self):

41

"""Return the descriptor for the field."""

42

```

43

44

Example usage:

45

46

```python

47

class Product(proto.Message):

48

# Primitive fields

49

name = proto.Field(proto.STRING, number=1)

50

price = proto.Field(proto.FLOAT, number=2)

51

in_stock = proto.Field(proto.BOOL, number=3)

52

53

# Optional field

54

description = proto.Field(proto.STRING, number=4, optional=True)

55

56

# Custom JSON name

57

product_id = proto.Field(proto.STRING, number=5, json_name="productId")

58

59

# Message field

60

category = proto.Field(Category, number=6)

61

62

# Enum field

63

status = proto.Field(ProductStatus, number=7)

64

```

65

66

### Repeated Fields

67

68

Define fields that can contain multiple values using RepeatedField.

69

70

```python { .api }

71

class RepeatedField(Field):

72

"""

73

A representation of a repeated field in protocol buffers.

74

75

Inherits all parameters from Field. The resulting field will contain

76

a sequence of values of the specified type.

77

"""

78

```

79

80

Example usage:

81

82

```python

83

class Order(proto.Message):

84

# Repeated primitive fields

85

item_ids = proto.RepeatedField(proto.STRING, number=1)

86

quantities = proto.RepeatedField(proto.INT32, number=2)

87

88

# Repeated message fields

89

line_items = proto.RepeatedField(LineItem, number=3)

90

91

# Repeated enum fields

92

statuses = proto.RepeatedField(OrderStatus, number=4)

93

94

# Usage

95

order = Order(

96

item_ids=["item1", "item2", "item3"],

97

quantities=[1, 2, 1],

98

line_items=[

99

LineItem(name="Widget", price=10.0),

100

LineItem(name="Gadget", price=25.0)

101

]

102

)

103

104

# Access like Python lists

105

print(len(order.item_ids)) # 3

106

order.item_ids.append("item4")

107

for item_id in order.item_ids:

108

print(item_id)

109

```

110

111

### Map Fields

112

113

Define key-value mapping fields using MapField.

114

115

```python { .api }

116

class MapField(Field):

117

"""

118

A representation of a map field in protocol buffers.

119

120

Args:

121

key_type: The protocol buffer type for map keys

122

value_type: The protocol buffer type for map values

123

number (int): The field number in the protocol buffer definition

124

message: Message class for MESSAGE type values

125

enum: Enum class for ENUM type values

126

"""

127

def __init__(self, key_type, value_type, *, number: int, message=None, enum=None): ...

128

```

129

130

Example usage:

131

132

```python

133

class Configuration(proto.Message):

134

# String to string map

135

settings = proto.MapField(proto.STRING, proto.STRING, number=1)

136

137

# String to integer map

138

limits = proto.MapField(proto.STRING, proto.INT32, number=2)

139

140

# String to message map

141

services = proto.MapField(proto.STRING, ServiceConfig, number=3)

142

143

# String to enum map

144

permissions = proto.MapField(proto.STRING, PermissionLevel, number=4)

145

146

# Usage

147

config = Configuration(

148

settings={

149

"debug": "true",

150

"log_level": "info"

151

},

152

limits={

153

"max_connections": 100,

154

"timeout_seconds": 30

155

}

156

)

157

158

# Access like Python dictionaries

159

print(config.settings["debug"]) # "true"

160

config.settings["new_setting"] = "value"

161

for key, value in config.limits.items():

162

print(f"{key}: {value}")

163

```

164

165

## Field Types and Protocol Buffer Integration

166

167

### Primitive Types

168

169

All protocol buffer primitive types are supported:

170

171

```python

172

# Numeric types

173

age = proto.Field(proto.INT32, number=1)

174

balance = proto.Field(proto.FLOAT, number=2)

175

precise_value = proto.Field(proto.DOUBLE, number=3)

176

user_id = proto.Field(proto.UINT64, number=4)

177

178

# String and bytes

179

name = proto.Field(proto.STRING, number=5)

180

data = proto.Field(proto.BYTES, number=6)

181

182

# Boolean

183

is_active = proto.Field(proto.BOOL, number=7)

184

```

185

186

### Message Types

187

188

Reference other proto-plus messages:

189

190

```python

191

class Address(proto.Message):

192

street = proto.Field(proto.STRING, number=1)

193

city = proto.Field(proto.STRING, number=2)

194

195

class Person(proto.Message):

196

name = proto.Field(proto.STRING, number=1)

197

# Message field - reference another message type

198

address = proto.Field(Address, number=2)

199

```

200

201

### Enum Types

202

203

Reference proto-plus enums:

204

205

```python

206

class Priority(proto.Enum):

207

LOW = 1

208

MEDIUM = 2

209

HIGH = 3

210

211

class Task(proto.Message):

212

title = proto.Field(proto.STRING, number=1)

213

# Enum field - reference an enum type

214

priority = proto.Field(Priority, number=2)

215

```

216

217

### Oneof Fields

218

219

Group fields into oneof constructs where only one field can be set:

220

221

```python

222

class Contact(proto.Message):

223

name = proto.Field(proto.STRING, number=1)

224

225

# Oneof group - only one of these can be set

226

email = proto.Field(proto.STRING, number=2, oneof="contact_method")

227

phone = proto.Field(proto.STRING, number=3, oneof="contact_method")

228

address = proto.Field(Address, number=4, oneof="contact_method")

229

230

# Usage

231

contact = Contact(name="John", email="john@example.com")

232

# contact.phone would be unset since email is set in the same oneof

233

```

234

235

### Optional Fields

236

237

Mark fields as optional in proto3:

238

239

```python

240

class User(proto.Message):

241

# Required fields (will have default values if not set)

242

username = proto.Field(proto.STRING, number=1)

243

244

# Optional field (can distinguish between unset and default value)

245

middle_name = proto.Field(proto.STRING, number=2, optional=True)

246

age = proto.Field(proto.INT32, number=3, optional=True)

247

248

# Usage

249

user = User(username="alice")

250

print("middle_name" in user) # False - not set

251

print("username" in user) # True - set

252

253

user.middle_name = ""

254

print("middle_name" in user) # True - set to empty string

255

```

256

257

## Advanced Field Features

258

259

### JSON Field Names

260

261

Customize JSON serialization field names:

262

263

```python

264

class Product(proto.Message):

265

internal_id = proto.Field(proto.STRING, number=1, json_name="productId")

266

display_name = proto.Field(proto.STRING, number=2, json_name="displayName")

267

268

# JSON will use "productId" and "displayName" instead of "internal_id" and "display_name"

269

```

270

271

### Field Validation and Conversion

272

273

Fields automatically handle type validation and conversion:

274

275

```python

276

class Stats(proto.Message):

277

count = proto.Field(proto.INT32, number=1)

278

279

# Automatic conversion

280

stats = Stats(count="123") # String converted to int

281

print(stats.count) # 123 (integer)

282

283

# Type validation

284

try:

285

stats = Stats(count="invalid") # Raises error

286

except ValueError:

287

print("Invalid value")

288

```