Generated code explanation¶
This page describes exactly what Python definitions the protocol buffer compiler generates for any given protocol definition. Also, this page is very similar to same page from original implementation, so I describe only differences from original implementation.
Compiler invocation¶
There is two significant differences:
- –python3_out instead of –python_out.
- There is no _pb2 suffix in generated file names.
Messages¶
Message can be loaded from serialized form two ways:
- By calling class-method create_from_bytes
- By creating instance and then calling instance method parse_from_bytes
And can be serialized by calling encode_to_bytes
Fields¶
Instead of original implementation, this one doesn’t generate any constants with field numbers.
Singular fields¶
All works very similar to original implementation:
message.foo = 123
print message.foo
There is some difference how you check fields presence:
assert not 'foo' in message
message.foo = 123
assert 'foo' in message
Also, currently there is no way for removing field (look at PB3-23)
Singular Message Fields¶
There is no difference with original implementation
message Foo {
optional Bar bar = 1;
}
message Bar {
optional int32 i = 1;
}
foo = Foo()
assert not 'bar' in foo
foo.bar.i = 1
assert 'bar' in foo
assert foo.bar.i == 1
Repeated Fields¶
I copied this section from original documentation, but commented some lines, that currently not implemented:
- .extend()
- I’m not sure about comparison with list, I’ll check later and fix this moment
- Currently there is no easy way for delete item from list. I’m working on it
message Foo {
repeated int32 nums = 1;
}
foo = Foo()
foo.nums.append(15) # Appends one value
#foo.nums.extend([32, 47]) # Appends an entire list
assert len(foo.nums) == 3
assert foo.nums[0] == 15
assert foo.nums[1] == 32
#assert foo.nums == [15, 32, 47]
foo.nums[1] = 56 # Reassigns a value
assert foo.nums[1] == 56
for i in foo.nums: # Loops and print
print i
#del foo.nums[:] # Clears list (works just like in a Python list)
Enumerations¶
In Python 3.4 default enum is used, for previous Python version this implementation will require backported implementation enum34.
Some example:
message Foo {
enum SomeEnum {
VALUE_A = 1;
VALUE_B = 5;
VALUE_C = 1234;
}
optional SomeEnum bar = 1;
}
After generating you will receive following code:
from enum import Enum
from protobuf3.message import Message
from protobuf3.fields import EnumField
class Foo(Message):
class SomeEnum(Enum):
VALUE_A = 1
VALUE_B = 5
VALUE_C = 1234
Foo.add_field('bar', EnumField(field_number=1, optional=True, enum_cls=Foo.SomeEnum))
And how this works:
foo = Foo()
foo.bar = Foo.SomeEnum.VALUE_A
assert foo.bar.value == 1
assert foo.bar == Foo.SomeEnum.VALUE_A
Oneof¶
Extensions¶
Messages with extension works very similar to messages without extensions. Look at this sample:
message Foo {
extensions 100 to 199;
}
extend Foo {
optional int32 bar = 123;
}
from protobuf3.fields import Int32Field
from protobuf3.message import Message
class Foo(Message):
pass
Foo.add_field('bar', Int32Field(field_number=123, optional=True))
This should work even if message and extension declared in different files