|
|
@ -48,7 +48,6 @@ __author__ = 'robinson@google.com (Will Robinson)' |
|
|
|
import ctypes |
|
|
|
import ctypes |
|
|
|
import numbers |
|
|
|
import numbers |
|
|
|
|
|
|
|
|
|
|
|
from google.protobuf.internal import api_implementation |
|
|
|
|
|
|
|
from google.protobuf.internal import decoder |
|
|
|
from google.protobuf.internal import decoder |
|
|
|
from google.protobuf.internal import encoder |
|
|
|
from google.protobuf.internal import encoder |
|
|
|
from google.protobuf.internal import wire_format |
|
|
|
from google.protobuf.internal import wire_format |
|
|
@ -77,7 +76,8 @@ def ToShortestFloat(original): |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def SupportsOpenEnums(field_descriptor): |
|
|
|
def SupportsOpenEnums(field_descriptor): |
|
|
|
return field_descriptor.containing_type.syntax == "proto3" |
|
|
|
return field_descriptor.containing_type.syntax == 'proto3' |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def GetTypeChecker(field): |
|
|
|
def GetTypeChecker(field): |
|
|
|
"""Returns a type checker for a message field of the specified types. |
|
|
|
"""Returns a type checker for a message field of the specified types. |
|
|
@ -105,7 +105,6 @@ def GetTypeChecker(field): |
|
|
|
# subclassing builtin types and doing weird things. We're not trying to |
|
|
|
# subclassing builtin types and doing weird things. We're not trying to |
|
|
|
# protect against malicious clients here, just people accidentally shooting |
|
|
|
# protect against malicious clients here, just people accidentally shooting |
|
|
|
# themselves in the foot in obvious ways. |
|
|
|
# themselves in the foot in obvious ways. |
|
|
|
|
|
|
|
|
|
|
|
class TypeChecker(object): |
|
|
|
class TypeChecker(object): |
|
|
|
|
|
|
|
|
|
|
|
"""Type checker used to catch type errors as early as possible |
|
|
|
"""Type checker used to catch type errors as early as possible |
|
|
@ -124,11 +123,6 @@ class TypeChecker(object): |
|
|
|
message = ('%.1024r has type %s, but expected one of: %s' % |
|
|
|
message = ('%.1024r has type %s, but expected one of: %s' % |
|
|
|
(proposed_value, type(proposed_value), self._acceptable_types)) |
|
|
|
(proposed_value, type(proposed_value), self._acceptable_types)) |
|
|
|
raise TypeError(message) |
|
|
|
raise TypeError(message) |
|
|
|
# Some field types(float, double and bool) accept other types, must |
|
|
|
|
|
|
|
# convert to the correct type in such cases. |
|
|
|
|
|
|
|
if self._acceptable_types: |
|
|
|
|
|
|
|
if self._acceptable_types[0] in (bool, float): |
|
|
|
|
|
|
|
return self._acceptable_types[0](proposed_value) |
|
|
|
|
|
|
|
return proposed_value |
|
|
|
return proposed_value |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -142,6 +136,22 @@ class TypeCheckerWithDefault(TypeChecker): |
|
|
|
return self._default_value |
|
|
|
return self._default_value |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class BoolValueChecker(object): |
|
|
|
|
|
|
|
"""Type checker used for bool fields.""" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def CheckValue(self, proposed_value): |
|
|
|
|
|
|
|
if not hasattr(proposed_value, '__index__') or ( |
|
|
|
|
|
|
|
type(proposed_value).__module__ == 'numpy' and |
|
|
|
|
|
|
|
type(proposed_value).__name__ == 'ndarray'): |
|
|
|
|
|
|
|
message = ('%.1024r has type %s, but expected one of: %s' % |
|
|
|
|
|
|
|
(proposed_value, type(proposed_value), (bool, int))) |
|
|
|
|
|
|
|
raise TypeError(message) |
|
|
|
|
|
|
|
return bool(proposed_value) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def DefaultValue(self): |
|
|
|
|
|
|
|
return False |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# IntValueChecker and its subclasses perform integer type-checks |
|
|
|
# IntValueChecker and its subclasses perform integer type-checks |
|
|
|
# and bounds-checks. |
|
|
|
# and bounds-checks. |
|
|
|
class IntValueChecker(object): |
|
|
|
class IntValueChecker(object): |
|
|
@ -149,10 +159,13 @@ class IntValueChecker(object): |
|
|
|
"""Checker used for integer fields. Performs type-check and range check.""" |
|
|
|
"""Checker used for integer fields. Performs type-check and range check.""" |
|
|
|
|
|
|
|
|
|
|
|
def CheckValue(self, proposed_value): |
|
|
|
def CheckValue(self, proposed_value): |
|
|
|
if not isinstance(proposed_value, numbers.Integral): |
|
|
|
if not hasattr(proposed_value, '__index__') or ( |
|
|
|
|
|
|
|
type(proposed_value).__module__ == 'numpy' and |
|
|
|
|
|
|
|
type(proposed_value).__name__ == 'ndarray'): |
|
|
|
message = ('%.1024r has type %s, but expected one of: %s' % |
|
|
|
message = ('%.1024r has type %s, but expected one of: %s' % |
|
|
|
(proposed_value, type(proposed_value), (int,))) |
|
|
|
(proposed_value, type(proposed_value), (int,))) |
|
|
|
raise TypeError(message) |
|
|
|
raise TypeError(message) |
|
|
|
|
|
|
|
|
|
|
|
if not self._MIN <= int(proposed_value) <= self._MAX: |
|
|
|
if not self._MIN <= int(proposed_value) <= self._MAX: |
|
|
|
raise ValueError('Value out of range: %d' % proposed_value) |
|
|
|
raise ValueError('Value out of range: %d' % proposed_value) |
|
|
|
# We force all values to int to make alternate implementations where the |
|
|
|
# We force all values to int to make alternate implementations where the |
|
|
@ -249,20 +262,38 @@ _INF = float('inf') |
|
|
|
_NEG_INF = float('-inf') |
|
|
|
_NEG_INF = float('-inf') |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class FloatValueChecker(object): |
|
|
|
class DoubleValueChecker(object): |
|
|
|
|
|
|
|
"""Checker used for double fields. |
|
|
|
|
|
|
|
|
|
|
|
"""Checker used for float fields. Performs type-check and range check. |
|
|
|
Performs type-check and range check. |
|
|
|
|
|
|
|
|
|
|
|
Values exceeding a 32-bit float will be converted to inf/-inf. |
|
|
|
|
|
|
|
""" |
|
|
|
""" |
|
|
|
|
|
|
|
|
|
|
|
def CheckValue(self, proposed_value): |
|
|
|
def CheckValue(self, proposed_value): |
|
|
|
"""Check and convert proposed_value to float.""" |
|
|
|
"""Check and convert proposed_value to float.""" |
|
|
|
if not isinstance(proposed_value, numbers.Real): |
|
|
|
if (not hasattr(proposed_value, '__float__') and |
|
|
|
message = ('%.1024r has type %s, but expected one of: numbers.Real' % |
|
|
|
not hasattr(proposed_value, '__index__')) or ( |
|
|
|
|
|
|
|
type(proposed_value).__module__ == 'numpy' and |
|
|
|
|
|
|
|
type(proposed_value).__name__ == 'ndarray'): |
|
|
|
|
|
|
|
message = ('%.1024r has type %s, but expected one of: int, float' % |
|
|
|
(proposed_value, type(proposed_value))) |
|
|
|
(proposed_value, type(proposed_value))) |
|
|
|
raise TypeError(message) |
|
|
|
raise TypeError(message) |
|
|
|
converted_value = float(proposed_value) |
|
|
|
return float(proposed_value) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def DefaultValue(self): |
|
|
|
|
|
|
|
return 0.0 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class FloatValueChecker(DoubleValueChecker): |
|
|
|
|
|
|
|
"""Checker used for float fields. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Performs type-check and range check. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Values exceeding a 32-bit float will be converted to inf/-inf. |
|
|
|
|
|
|
|
""" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def CheckValue(self, proposed_value): |
|
|
|
|
|
|
|
"""Check and convert proposed_value to float.""" |
|
|
|
|
|
|
|
converted_value = super().CheckValue(proposed_value) |
|
|
|
# This inf rounding matches the C++ proto SafeDoubleToFloat logic. |
|
|
|
# This inf rounding matches the C++ proto SafeDoubleToFloat logic. |
|
|
|
if converted_value > _FLOAT_MAX: |
|
|
|
if converted_value > _FLOAT_MAX: |
|
|
|
return _INF |
|
|
|
return _INF |
|
|
@ -271,23 +302,17 @@ class FloatValueChecker(object): |
|
|
|
|
|
|
|
|
|
|
|
return TruncateToFourByteFloat(converted_value) |
|
|
|
return TruncateToFourByteFloat(converted_value) |
|
|
|
|
|
|
|
|
|
|
|
def DefaultValue(self): |
|
|
|
|
|
|
|
return 0.0 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Type-checkers for all scalar CPPTYPEs. |
|
|
|
# Type-checkers for all scalar CPPTYPEs. |
|
|
|
_VALUE_CHECKERS = { |
|
|
|
_VALUE_CHECKERS = { |
|
|
|
_FieldDescriptor.CPPTYPE_INT32: Int32ValueChecker(), |
|
|
|
_FieldDescriptor.CPPTYPE_INT32: Int32ValueChecker(), |
|
|
|
_FieldDescriptor.CPPTYPE_INT64: Int64ValueChecker(), |
|
|
|
_FieldDescriptor.CPPTYPE_INT64: Int64ValueChecker(), |
|
|
|
_FieldDescriptor.CPPTYPE_UINT32: Uint32ValueChecker(), |
|
|
|
_FieldDescriptor.CPPTYPE_UINT32: Uint32ValueChecker(), |
|
|
|
_FieldDescriptor.CPPTYPE_UINT64: Uint64ValueChecker(), |
|
|
|
_FieldDescriptor.CPPTYPE_UINT64: Uint64ValueChecker(), |
|
|
|
_FieldDescriptor.CPPTYPE_DOUBLE: TypeCheckerWithDefault( |
|
|
|
_FieldDescriptor.CPPTYPE_DOUBLE: DoubleValueChecker(), |
|
|
|
0.0, float, numbers.Real), |
|
|
|
|
|
|
|
_FieldDescriptor.CPPTYPE_FLOAT: FloatValueChecker(), |
|
|
|
_FieldDescriptor.CPPTYPE_FLOAT: FloatValueChecker(), |
|
|
|
_FieldDescriptor.CPPTYPE_BOOL: TypeCheckerWithDefault( |
|
|
|
_FieldDescriptor.CPPTYPE_BOOL: BoolValueChecker(), |
|
|
|
False, bool, numbers.Integral), |
|
|
|
|
|
|
|
_FieldDescriptor.CPPTYPE_STRING: TypeCheckerWithDefault(b'', bytes), |
|
|
|
_FieldDescriptor.CPPTYPE_STRING: TypeCheckerWithDefault(b'', bytes), |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Map from field type to a function F, such that F(field_num, value) |
|
|
|
# Map from field type to a function F, such that F(field_num, value) |
|
|
|