-
Notifications
You must be signed in to change notification settings - Fork 15.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Nextgen Proto Pythonic API: Timestamp/Duration assignment, creation a…
…nd calculation Timestamp and Duration are now have more support with datetime and timedelta: - Allows assign python datetime to protobuf DateTime field in addition to current FromDatetime/ToDatetime (Note: will throw exceptions for the differences in supported ranges) - Allows assign python timedelta to protobuf Duration field in addition to current FromTimedelta/ToTimedelta - Calculation between Timestamp, Duration, datetime and timedelta will also be supported. example usage: from datetime import datetime, timedelta from event_pb2 import Event e = Event(start_time=datetime(year=2112, month=2, day=3), duration=timedelta(hours=10)) duration = timedelta(hours=10)) end_time = e.start_time + timedelta(hours=4) e.duration = end_time - e.start_time PiperOrigin-RevId: 640639168
- Loading branch information
1 parent
a450c9c
commit b690e72
Showing
7 changed files
with
445 additions
and
31 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -27,6 +27,7 @@ | |
|
||
__author__ = '[email protected] (Will Robinson)' | ||
|
||
import datetime | ||
from io import BytesIO | ||
import struct | ||
import sys | ||
|
@@ -536,13 +537,30 @@ def init(self, **kwargs): | |
self._fields[field] = copy | ||
elif field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: | ||
copy = field._default_constructor(self) | ||
new_val = field_value | ||
if isinstance(field_value, dict): | ||
new_val = None | ||
if isinstance(field_value, message_mod.Message): | ||
new_val = field_value | ||
elif isinstance(field_value, dict): | ||
new_val = field.message_type._concrete_class(**field_value) | ||
try: | ||
copy.MergeFrom(new_val) | ||
except TypeError: | ||
_ReraiseTypeErrorWithFieldName(message_descriptor.name, field_name) | ||
elif field.message_type.full_name == 'google.protobuf.Timestamp': | ||
copy.FromDatetime(field_value) | ||
elif field.message_type.full_name == 'google.protobuf.Duration': | ||
copy.FromTimedelta(field_value) | ||
else: | ||
raise TypeError( | ||
'Message field {0}.{1} must be initialized with a ' | ||
'dict or instance of same class, got {2}.'.format( | ||
message_descriptor.name, | ||
field_name, | ||
type(field_value).__name__, | ||
) | ||
) | ||
|
||
if new_val: | ||
try: | ||
copy.MergeFrom(new_val) | ||
except TypeError: | ||
_ReraiseTypeErrorWithFieldName(message_descriptor.name, field_name) | ||
self._fields[field] = copy | ||
else: | ||
if field.cpp_type == _FieldDescriptor.CPPTYPE_ENUM: | ||
|
@@ -753,8 +771,17 @@ def getter(self): | |
# We define a setter just so we can throw an exception with a more | ||
# helpful error message. | ||
def setter(self, new_value): | ||
raise AttributeError('Assignment not allowed to composite field ' | ||
'"%s" in protocol message object.' % proto_field_name) | ||
if field.message_type.full_name == 'google.protobuf.Timestamp': | ||
getter(self) | ||
self._fields[field].FromDatetime(new_value) | ||
elif field.message_type.full_name == 'google.protobuf.Duration': | ||
getter(self) | ||
self._fields[field].FromTimedelta(new_value) | ||
else: | ||
raise AttributeError( | ||
'Assignment not allowed to composite field ' | ||
'"%s" in protocol message object.' % proto_field_name | ||
) | ||
|
||
# Add a property to encapsulate the getter. | ||
doc = 'Magic attribute generated for "%s" proto field.' % proto_field_name | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.