Index: third_party/protobuf/python/google/protobuf/internal/well_known_types.py |
diff --git a/third_party/protobuf/python/google/protobuf/internal/well_known_types.py b/third_party/protobuf/python/google/protobuf/internal/well_known_types.py |
index 7c5dffd0fc53d4728647c1e8551aa9d676782c8d..d631abeeaa5d8368903a5e334fe9450d4fb0e8f1 100644 |
--- a/third_party/protobuf/python/google/protobuf/internal/well_known_types.py |
+++ b/third_party/protobuf/python/google/protobuf/internal/well_known_types.py |
@@ -53,6 +53,7 @@ _NANOS_PER_MICROSECOND = 1000 |
_MILLIS_PER_SECOND = 1000 |
_MICROS_PER_SECOND = 1000000 |
_SECONDS_PER_DAY = 24 * 3600 |
+_DURATION_SECONDS_MAX = 315576000000 |
class Error(Exception): |
@@ -247,6 +248,7 @@ class Duration(object): |
represent the exact Duration value. For example: "1s", "1.010s", |
"1.000000100s", "-3.100s" |
""" |
+ _CheckDurationValid(self.seconds, self.nanos) |
if self.seconds < 0 or self.nanos < 0: |
result = '-' |
seconds = - self.seconds + int((0 - self.nanos) // 1e9) |
@@ -286,14 +288,17 @@ class Duration(object): |
try: |
pos = value.find('.') |
if pos == -1: |
- self.seconds = int(value[:-1]) |
- self.nanos = 0 |
+ seconds = int(value[:-1]) |
+ nanos = 0 |
else: |
- self.seconds = int(value[:pos]) |
+ seconds = int(value[:pos]) |
if value[0] == '-': |
- self.nanos = int(round(float('-0{0}'.format(value[pos: -1])) *1e9)) |
+ nanos = int(round(float('-0{0}'.format(value[pos: -1])) *1e9)) |
else: |
- self.nanos = int(round(float('0{0}'.format(value[pos: -1])) *1e9)) |
+ nanos = int(round(float('0{0}'.format(value[pos: -1])) *1e9)) |
+ _CheckDurationValid(seconds, nanos) |
+ self.seconds = seconds |
+ self.nanos = nanos |
except ValueError: |
raise ParseError( |
'Couldn\'t parse duration: {0}.'.format(value)) |
@@ -359,6 +364,17 @@ class Duration(object): |
self.nanos = nanos |
+def _CheckDurationValid(seconds, nanos): |
+ if seconds < -_DURATION_SECONDS_MAX or seconds > _DURATION_SECONDS_MAX: |
+ raise Error( |
+ 'Duration is not valid: Seconds {0} must be in range ' |
+ '[-315576000000, 315576000000].'.format(seconds)) |
+ if nanos <= -_NANOS_PER_SECOND or nanos >= _NANOS_PER_SECOND: |
+ raise Error( |
+ 'Duration is not valid: Nanos {0} must be in range ' |
+ '[-999999999, 999999999].'.format(nanos)) |
+ |
+ |
def _RoundTowardZero(value, divider): |
"""Truncates the remainder part after division.""" |
# For some languanges, the sign of the remainder is implementation |
@@ -379,13 +395,16 @@ class FieldMask(object): |
def ToJsonString(self): |
"""Converts FieldMask to string according to proto3 JSON spec.""" |
- return ','.join(self.paths) |
+ camelcase_paths = [] |
+ for path in self.paths: |
+ camelcase_paths.append(_SnakeCaseToCamelCase(path)) |
+ return ','.join(camelcase_paths) |
def FromJsonString(self, value): |
"""Converts string to FieldMask according to proto3 JSON spec.""" |
self.Clear() |
for path in value.split(','): |
- self.paths.append(path) |
+ self.paths.append(_CamelCaseToSnakeCase(path)) |
def IsValidForDescriptor(self, message_descriptor): |
"""Checks whether the FieldMask is valid for Message Descriptor.""" |
@@ -472,6 +491,48 @@ def _CheckFieldMaskMessage(message): |
message_descriptor.full_name)) |
+def _SnakeCaseToCamelCase(path_name): |
+ """Converts a path name from snake_case to camelCase.""" |
+ result = [] |
+ after_underscore = False |
+ for c in path_name: |
+ if c.isupper(): |
+ raise Error('Fail to print FieldMask to Json string: Path name ' |
+ '{0} must not contain uppercase letters.'.format(path_name)) |
+ if after_underscore: |
+ if c.islower(): |
+ result.append(c.upper()) |
+ after_underscore = False |
+ else: |
+ raise Error('Fail to print FieldMask to Json string: The ' |
+ 'character after a "_" must be a lowercase letter ' |
+ 'in path name {0}.'.format(path_name)) |
+ elif c == '_': |
+ after_underscore = True |
+ else: |
+ result += c |
+ |
+ if after_underscore: |
+ raise Error('Fail to print FieldMask to Json string: Trailing "_" ' |
+ 'in path name {0}.'.format(path_name)) |
+ return ''.join(result) |
+ |
+ |
+def _CamelCaseToSnakeCase(path_name): |
+ """Converts a field name from camelCase to snake_case.""" |
+ result = [] |
+ for c in path_name: |
+ if c == '_': |
+ raise ParseError('Fail to parse FieldMask: Path name ' |
+ '{0} must not contain "_"s.'.format(path_name)) |
+ if c.isupper(): |
+ result += '_' |
+ result += c.lower() |
+ else: |
+ result += c |
+ return ''.join(result) |
+ |
+ |
class _FieldMaskTree(object): |
"""Represents a FieldMask in a tree structure. |