28
28
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
29
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
#PY25 compatible for GAE.
33
# Copyright 2008 Google Inc. All Rights Reserved.
31
35
"""Provides type checking routines.
33
37
This module defines type checking utilities in the forms of dictionaries:
53
60
_FieldDescriptor = descriptor.FieldDescriptor
56
def GetTypeChecker(cpp_type, field_type):
63
def GetTypeChecker(field):
57
64
"""Returns a type checker for a message field of the specified types.
60
cpp_type: C++ type of the field (see descriptor.py).
61
field_type: Protocol message field type (see descriptor.py).
67
field: FieldDescriptor object for this field.
64
70
An instance of TypeChecker which can be used to verify the types
65
71
of values assigned to a field of the specified type.
67
if (cpp_type == _FieldDescriptor.CPPTYPE_STRING and
68
field_type == _FieldDescriptor.TYPE_STRING):
73
if (field.cpp_type == _FieldDescriptor.CPPTYPE_STRING and
74
field.type == _FieldDescriptor.TYPE_STRING):
69
75
return UnicodeValueChecker()
70
return _VALUE_CHECKERS[cpp_type]
76
if field.cpp_type == _FieldDescriptor.CPPTYPE_ENUM:
77
return EnumValueChecker(field.enum_type)
78
return _VALUE_CHECKERS[field.cpp_type]
73
81
# None of the typecheckers below make any attempt to guard against people
85
93
self._acceptable_types = acceptable_types
87
95
def CheckValue(self, proposed_value):
96
"""Type check the provided value and return it.
98
The returned value might have been normalized to another type.
88
100
if not isinstance(proposed_value, self._acceptable_types):
89
101
message = ('%.1024r has type %s, but expected one of: %s' %
90
102
(proposed_value, type(proposed_value), self._acceptable_types))
91
103
raise TypeError(message)
104
return proposed_value
94
107
# IntValueChecker and its subclasses perform integer type-checks
104
117
raise TypeError(message)
105
118
if not self._MIN <= proposed_value <= self._MAX:
106
119
raise ValueError('Value out of range: %d' % proposed_value)
120
# We force 32-bit values to int and 64-bit values to long to make
121
# alternate implementations where the distinction is more significant
122
# (e.g. the C++ implementation) simpler.
123
proposed_value = self._TYPE(proposed_value)
124
return proposed_value
127
class EnumValueChecker(object):
129
"""Checker used for enum fields. Performs type-check and range check."""
131
def __init__(self, enum_type):
132
self._enum_type = enum_type
134
def CheckValue(self, proposed_value):
135
if not isinstance(proposed_value, (int, long)):
136
message = ('%.1024r has type %s, but expected one of: %s' %
137
(proposed_value, type(proposed_value), (int, long)))
138
raise TypeError(message)
139
if proposed_value not in self._enum_type.values_by_number:
140
raise ValueError('Unknown enum value: %d' % proposed_value)
141
return proposed_value
109
144
class UnicodeValueChecker(object):
111
"""Checker used for string fields."""
146
"""Checker used for string fields.
148
Always returns a unicode value, even if the input is of type str.
113
151
def CheckValue(self, proposed_value):
114
if not isinstance(proposed_value, (str, unicode)):
152
if not isinstance(proposed_value, (bytes, unicode)):
115
153
message = ('%.1024r has type %s, but expected one of: %s' %
116
(proposed_value, type(proposed_value), (str, unicode)))
154
(proposed_value, type(proposed_value), (bytes, unicode)))
117
155
raise TypeError(message)
119
# If the value is of type 'str' make sure that it is in 7-bit ASCII
157
# If the value is of type 'bytes' make sure that it is in 7-bit ASCII
121
if isinstance(proposed_value, str):
159
if isinstance(proposed_value, bytes):
123
unicode(proposed_value, 'ascii')
161
proposed_value = proposed_value.decode('ascii')
124
162
except UnicodeDecodeError:
125
raise ValueError('%.1024r has type str, but isn\'t in 7-bit ASCII '
163
raise ValueError('%.1024r has type bytes, but isn\'t in 7-bit ASCII '
126
164
'encoding. Non-ASCII strings must be converted to '
127
165
'unicode objects before being added.' %
128
166
(proposed_value))
167
return proposed_value
131
170
class Int32ValueChecker(IntValueChecker):
161
204
_FieldDescriptor.CPPTYPE_FLOAT: TypeChecker(
162
205
float, int, long),
163
206
_FieldDescriptor.CPPTYPE_BOOL: TypeChecker(bool, int),
164
_FieldDescriptor.CPPTYPE_ENUM: Int32ValueChecker(),
165
_FieldDescriptor.CPPTYPE_STRING: TypeChecker(str),
207
_FieldDescriptor.CPPTYPE_STRING: TypeChecker(bytes),