proto-builder 1.5.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- proto_builder-1.5.2/PKG-INFO +402 -0
- proto_builder-1.5.2/README.md +397 -0
- proto_builder-1.5.2/pyproject.toml +9 -0
- proto_builder-1.5.2/setup.cfg +4 -0
- proto_builder-1.5.2/src/__init__.py +0 -0
- proto_builder-1.5.2/src/proto_builder/base_builder.py +231 -0
- proto_builder-1.5.2/src/proto_builder/message_builder.py +230 -0
- proto_builder-1.5.2/src/proto_builder/service_builder.py +126 -0
- proto_builder-1.5.2/src/proto_builder/tree_structure.py +355 -0
- proto_builder-1.5.2/src/proto_builder/utils.py +159 -0
- proto_builder-1.5.2/src/proto_builder.egg-info/PKG-INFO +402 -0
- proto_builder-1.5.2/src/proto_builder.egg-info/SOURCES.txt +12 -0
- proto_builder-1.5.2/src/proto_builder.egg-info/dependency_links.txt +1 -0
- proto_builder-1.5.2/src/proto_builder.egg-info/top_level.txt +2 -0
|
@@ -0,0 +1,402 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: proto-builder
|
|
3
|
+
Version: 1.5.2
|
|
4
|
+
Description-Content-Type: text/markdown
|
|
5
|
+
|
|
6
|
+
# Proto Builder
|
|
7
|
+
|
|
8
|
+
## 📦 Installation
|
|
9
|
+
|
|
10
|
+
Install the package with:
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
pip install proto-builder
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
A simple compiler that converts an abstract class to Protocol Buffers (`.proto`), built with Python.
|
|
17
|
+
|
|
18
|
+
It can also convert Python `dataclass` or Pydantic models to protobuf messages using a tree-based structure.
|
|
19
|
+
|
|
20
|
+
## 📚 Contents
|
|
21
|
+
|
|
22
|
+
### Getting Started
|
|
23
|
+
|
|
24
|
+
- [Overview](#overview)
|
|
25
|
+
- [Example Models](#example-models)
|
|
26
|
+
|
|
27
|
+
### Service Generation
|
|
28
|
+
|
|
29
|
+
- [Build a Protobuf Service](#build-a-protobuf-service)
|
|
30
|
+
- [Generated Service Output](#generated-service-output)
|
|
31
|
+
|
|
32
|
+
### Message Generation
|
|
33
|
+
|
|
34
|
+
- [Convert a Dataclass or Pydantic Model](#convert-a-dataclass-or-pydantic-model)
|
|
35
|
+
- [Generated Message Output](#generated-message-output)
|
|
36
|
+
|
|
37
|
+
### Configuration
|
|
38
|
+
|
|
39
|
+
- [Configuration Options](#configuration-options)
|
|
40
|
+
- [Override](#override)
|
|
41
|
+
- [Remove](#remove)
|
|
42
|
+
- [Optional](#optional)
|
|
43
|
+
- [Optional All](#optional-all)
|
|
44
|
+
- [Configuration Paths](#configuration-paths)
|
|
45
|
+
- [Configuration Example](#configuration-example)
|
|
46
|
+
- [Configured Output](#configured-output)
|
|
47
|
+
|
|
48
|
+
## Overview
|
|
49
|
+
|
|
50
|
+
A simple compiler that converts an abstract class to protobuf, built with Python.
|
|
51
|
+
|
|
52
|
+
It is also used to convert data classes or Pydantic classes to protobuf messages using a tree structure.
|
|
53
|
+
|
|
54
|
+
## Example Models
|
|
55
|
+
|
|
56
|
+
Suppose we have this abstract class along with data classes or Pydantic models (here we've used data classes).
|
|
57
|
+
|
|
58
|
+
```python
|
|
59
|
+
from abc import ABC, abstractmethod
|
|
60
|
+
from dataclasses import dataclass
|
|
61
|
+
from datetime import datetime
|
|
62
|
+
from enum import Enum
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
class Status(Enum):
|
|
66
|
+
ACTIVE = "active"
|
|
67
|
+
INACTIVE = "inactive"
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
@dataclass
|
|
71
|
+
class Location:
|
|
72
|
+
city: str
|
|
73
|
+
country: str
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
@dataclass
|
|
77
|
+
class Address:
|
|
78
|
+
street: str
|
|
79
|
+
postal_code: str
|
|
80
|
+
location: Location
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
@dataclass
|
|
84
|
+
class Employee:
|
|
85
|
+
id: int
|
|
86
|
+
name: str
|
|
87
|
+
status: Status
|
|
88
|
+
address: Address
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
@dataclass
|
|
92
|
+
class Department:
|
|
93
|
+
name: str
|
|
94
|
+
manager: Employee
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
@dataclass
|
|
98
|
+
class Company:
|
|
99
|
+
name: str
|
|
100
|
+
founded: datetime
|
|
101
|
+
department: Department
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
class CompanyService(ABC):
|
|
105
|
+
|
|
106
|
+
@abstractmethod
|
|
107
|
+
def get_company(self, company_id: int) -> Company:
|
|
108
|
+
pass
|
|
109
|
+
|
|
110
|
+
@abstractmethod
|
|
111
|
+
def get_employee(self, employee_id: int) -> Employee | None:
|
|
112
|
+
pass
|
|
113
|
+
|
|
114
|
+
@abstractmethod
|
|
115
|
+
def find(self, name: str) -> Company | Department | Employee | Status | None:
|
|
116
|
+
pass
|
|
117
|
+
|
|
118
|
+
@abstractmethod
|
|
119
|
+
def summary(self, employee_id: int) -> tuple[Employee | Status | None, str]:
|
|
120
|
+
pass
|
|
121
|
+
|
|
122
|
+
@abstractmethod
|
|
123
|
+
def update(
|
|
124
|
+
self,
|
|
125
|
+
company: Company,
|
|
126
|
+
employees: list[Employee],
|
|
127
|
+
metadata: dict[str, str],
|
|
128
|
+
tags: set[str],
|
|
129
|
+
) -> list[Department]:
|
|
130
|
+
pass
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## Build a Protobuf Service
|
|
134
|
+
|
|
135
|
+
This is how the protobuf service is generated from the abstract class.
|
|
136
|
+
|
|
137
|
+
```python
|
|
138
|
+
from proto_builder.utils import ProtoConfig
|
|
139
|
+
from proto_builder.service_builder import ServiceBuilder
|
|
140
|
+
|
|
141
|
+
config = ProtoConfig()
|
|
142
|
+
service_builder = ServiceBuilder(config)
|
|
143
|
+
|
|
144
|
+
proto = service_builder.build(CompanyService, "company_service")
|
|
145
|
+
|
|
146
|
+
print(proto)
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
## Generated Service Output
|
|
150
|
+
|
|
151
|
+
```protobuf
|
|
152
|
+
syntax = "proto3";
|
|
153
|
+
package company_service;
|
|
154
|
+
|
|
155
|
+
import "google/protobuf/timestamp.proto";
|
|
156
|
+
|
|
157
|
+
service CompanyService {
|
|
158
|
+
rpc get_company (GetCompanyRequest) returns (Company);
|
|
159
|
+
rpc get_employee (GetEmployeeRequest) returns (GetEmployeeResponse);
|
|
160
|
+
rpc find (FindRequest) returns (FindResponse);
|
|
161
|
+
rpc summary (SummaryRequest) returns (SummaryResponse);
|
|
162
|
+
rpc update (UpdateRequest) returns (UpdateResponse);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
enum Status {
|
|
166
|
+
ACTIVE = 0;
|
|
167
|
+
INACTIVE = 1;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
message Location {
|
|
171
|
+
string city = 1;
|
|
172
|
+
string country = 2;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
message Address {
|
|
176
|
+
string street = 1;
|
|
177
|
+
string postal_code = 2;
|
|
178
|
+
Location location = 3;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
message Employee {
|
|
182
|
+
int32 id = 1;
|
|
183
|
+
string name = 2;
|
|
184
|
+
Status status = 3;
|
|
185
|
+
Address address = 4;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
message Department {
|
|
189
|
+
string name = 1;
|
|
190
|
+
Employee manager = 2;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
message Company {
|
|
194
|
+
string name = 1;
|
|
195
|
+
google.protobuf.Timestamp founded = 2;
|
|
196
|
+
Department department = 3;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
message GetCompanyRequest {
|
|
200
|
+
int32 company_id = 1;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
message GetEmployeeRequest {
|
|
204
|
+
int32 employee_id = 1;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
message GetEmployeeResponse {
|
|
208
|
+
optional Employee employee = 1;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
message FindRequest {
|
|
212
|
+
string name = 1;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
message FindResponse {
|
|
216
|
+
oneof union_var {
|
|
217
|
+
Company company = 1;
|
|
218
|
+
Department department = 2;
|
|
219
|
+
Employee employee = 3;
|
|
220
|
+
Status status = 4;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
message SummaryRequest {
|
|
225
|
+
int32 employee_id = 1;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
message SummaryResponse {
|
|
229
|
+
oneof union_var {
|
|
230
|
+
Employee employee = 1;
|
|
231
|
+
Status status = 2;
|
|
232
|
+
}
|
|
233
|
+
string str_var = 3;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
message UpdateRequest {
|
|
237
|
+
Company company = 1;
|
|
238
|
+
repeated Employee employees = 2;
|
|
239
|
+
map<string, string> metadata = 3;
|
|
240
|
+
repeated string tags = 4;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
message UpdateResponse {
|
|
244
|
+
repeated Department department = 1;
|
|
245
|
+
}
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
## Convert a Dataclass or Pydantic Model
|
|
249
|
+
|
|
250
|
+
Converting a dataclass or Pydantic model to protobuf messages is done using this way.
|
|
251
|
+
|
|
252
|
+
```python
|
|
253
|
+
from proto_builder.utils import ProtoConfig
|
|
254
|
+
from proto_builder.message_builder import MessageBuilder
|
|
255
|
+
|
|
256
|
+
config = ProtoConfig()
|
|
257
|
+
message_builder = MessageBuilder(config)
|
|
258
|
+
|
|
259
|
+
proto = message_builder.build(Company)
|
|
260
|
+
|
|
261
|
+
print(proto)
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
## Generated Message Output
|
|
265
|
+
|
|
266
|
+
```protobuf
|
|
267
|
+
enum Status {
|
|
268
|
+
ACTIVE = 0;
|
|
269
|
+
INACTIVE = 1;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
message Location {
|
|
273
|
+
string city = 1;
|
|
274
|
+
string country = 2;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
message Address {
|
|
278
|
+
string street = 1;
|
|
279
|
+
string postal_code = 2;
|
|
280
|
+
Location location = 3;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
message Employee {
|
|
284
|
+
int32 id = 1;
|
|
285
|
+
string name = 2;
|
|
286
|
+
Status status = 3;
|
|
287
|
+
Address address = 4;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
message Department {
|
|
291
|
+
string name = 1;
|
|
292
|
+
Employee manager = 2;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
message Company {
|
|
296
|
+
string name = 1;
|
|
297
|
+
google.protobuf.Timestamp founded = 2;
|
|
298
|
+
Department department = 3;
|
|
299
|
+
}
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
## Configuration Options
|
|
303
|
+
|
|
304
|
+
The changes we can make via configuration:
|
|
305
|
+
|
|
306
|
+
```python
|
|
307
|
+
config = ProtoConfig(
|
|
308
|
+
override=[
|
|
309
|
+
...
|
|
310
|
+
],
|
|
311
|
+
remove=[
|
|
312
|
+
...
|
|
313
|
+
],
|
|
314
|
+
optional=[
|
|
315
|
+
...
|
|
316
|
+
],
|
|
317
|
+
optional_all=True or False,
|
|
318
|
+
)
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
### Override
|
|
322
|
+
|
|
323
|
+
Replace a type or a field's type with another type.
|
|
324
|
+
|
|
325
|
+
### Remove
|
|
326
|
+
|
|
327
|
+
Remove a type or a field's type.
|
|
328
|
+
|
|
329
|
+
### Optional
|
|
330
|
+
|
|
331
|
+
Make a field or its type optional (i.e., making its assignment optional).
|
|
332
|
+
|
|
333
|
+
### Optional All
|
|
334
|
+
|
|
335
|
+
`optional_all` makes the assignment of all fields or field types optional.
|
|
336
|
+
|
|
337
|
+
### Configuration Paths
|
|
338
|
+
|
|
339
|
+
The paths used in the config can be either relative or absolute.
|
|
340
|
+
|
|
341
|
+
### Configuration Example
|
|
342
|
+
|
|
343
|
+
```python
|
|
344
|
+
config = ProtoConfig(
|
|
345
|
+
override=[
|
|
346
|
+
{"Department.manager": list[Employee]},
|
|
347
|
+
# It can be:
|
|
348
|
+
# {"...Department.manager": list[Employee]},
|
|
349
|
+
# or
|
|
350
|
+
# {"...manager": list[Employee]},
|
|
351
|
+
|
|
352
|
+
{"str": int},
|
|
353
|
+
],
|
|
354
|
+
remove=[
|
|
355
|
+
"Employee.address",
|
|
356
|
+
# It can be:
|
|
357
|
+
# "...Employee.address",
|
|
358
|
+
# or
|
|
359
|
+
# "...address",
|
|
360
|
+
# or
|
|
361
|
+
# "...Address",
|
|
362
|
+
],
|
|
363
|
+
optional=[
|
|
364
|
+
"Company",
|
|
365
|
+
# It can be:
|
|
366
|
+
# "...Company",
|
|
367
|
+
|
|
368
|
+
"Employee.status",
|
|
369
|
+
# It can be:
|
|
370
|
+
# "...Employee.status",
|
|
371
|
+
# or
|
|
372
|
+
# "...status",
|
|
373
|
+
],
|
|
374
|
+
# optional_all=True,
|
|
375
|
+
)
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
## Configured Output
|
|
379
|
+
|
|
380
|
+
```protobuf
|
|
381
|
+
enum Status {
|
|
382
|
+
ACTIVE = 0;
|
|
383
|
+
INACTIVE = 1;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
message Employee {
|
|
387
|
+
int32 id = 1;
|
|
388
|
+
int32 name = 2;
|
|
389
|
+
optional Status status = 3;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
message Department {
|
|
393
|
+
int32 name = 1;
|
|
394
|
+
repeated Employee manager = 2;
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
message Company {
|
|
398
|
+
optional int32 name = 1;
|
|
399
|
+
optional google.protobuf.Timestamp founded = 2;
|
|
400
|
+
optional Department department = 3;
|
|
401
|
+
}
|
|
402
|
+
```
|