Full exampleΒΆ
Warning
This is incomplete and will be extended to include validation and other, more complex patterns.
Note
Finished example can be found at github.
Given following protobuf definition and student_pb2.py
Python module:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | syntax = "proto3";
import "google/protobuf/wrappers.proto";
package overview_example;
enum Grade {
UNKNOWN = 0;
// others...
B = 5;
A = 6;
}
message Student {
message CourseGrade {
string course_id = 1;
Grade grade = 2;
}
uint32 id = 1;
google.protobuf.StringValue name = 2;
repeated CourseGrade grades = 3;
}
|
We can declare following Model
classes, which reflect the structure of above message:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | from schematics import types
from schematics_proto3 import Model
from schematics_proto3 import types as pbtypes
from schematics_proto3.enum import ProtobufEnum
import student_pb2 as pb2 # noqa
class Grade(ProtobufEnum, protobuf_enum=pb2.Grade):
pass
class CourseGrade(Model, protobuf_message=pb2.Student.CourseGrade):
course_id = types.StringType()
grade = pbtypes.EnumType(
Grade,
unset_variant=pb2.Grade.UNKNOWN,
)
class StudentModel(Model, protobuf_message=pb2.Student):
id = types.IntType()
name = pbtypes.StringWrapperType()
grades = pbtypes.RepeatedType(
pbtypes.MessageType(CourseGrade),
)
|
And now, we can instantiate StudentModel
class directly from Protobuf message:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | # Build a student message, normally that comes through the wire
msg = pb2.Student()
msg.id = 42
msg.name.value = 'Jon Doe'
msg.grades.extend([
pb2.Student.CourseGrade(course_id='maths', grade=pb2.Grade.A),
pb2.Student.CourseGrade(course_id='physics', grade=pb2.Grade.A),
])
# Create StudentModel instance, loading protobuf message
model = StudentModel.load_protobuf(msg)
model.validate()
# Inspect instance attributes
print('Student ID:', model.id)
# Student ID: 42
print('Student name:', model.name)
# Student name: Jon Doe
for grade in model.grades:
print(f'`{grade.course_id}` grade:', grade.grade)
# `maths` grade: A
# `physics` grade: A
# Export instance to dict
print(model.to_native())
# {'id': 42, 'name': 'Jon Doe', 'grades': [{'course_id': 'maths', 'grade': 'A'}, {'course_id': 'physics', 'grade': 'A'}]}
|