1fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# Protocol Buffers - Google's data interchange format 2fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# Copyright 2008 Google Inc. All rights reserved. 3afb4b72037e3f13db208590fc782c4bc8e27f862Jeff Davidson# https://developers.google.com/protocol-buffers/ 4fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# 5fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# Redistribution and use in source and binary forms, with or without 6fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# modification, are permitted provided that the following conditions are 7fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# met: 8fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# 9fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# * Redistributions of source code must retain the above copyright 10fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# notice, this list of conditions and the following disclaimer. 11fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# * Redistributions in binary form must reproduce the above 12fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# copyright notice, this list of conditions and the following disclaimer 13fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# in the documentation and/or other materials provided with the 14fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# distribution. 15fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# * Neither the name of Google Inc. nor the names of its 16fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# contributors may be used to endorse or promote products derived from 17fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# this software without specific prior written permission. 18fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# 19fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 31a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson#PY25 compatible for GAE. 32a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson# 33a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson# Copyright 2007 Google Inc. All Rights Reserved. 34a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson 35fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville"""Contains routines for printing protocol messages in text format.""" 36fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 37fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville__author__ = 'kenton@google.com (Kenton Varda)' 38fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 39fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleimport cStringIO 40fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleimport re 41fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 42fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillefrom google.protobuf.internal import type_checkers 43fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillefrom google.protobuf import descriptor 44a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidsonfrom google.protobuf import text_encoding 45a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson 46a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson__all__ = ['MessageToString', 'PrintMessage', 'PrintField', 47a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson 'PrintFieldValue', 'Merge'] 48fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 49fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 50a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson_INTEGER_CHECKERS = (type_checkers.Uint32ValueChecker(), 51a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson type_checkers.Int32ValueChecker(), 52a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson type_checkers.Uint64ValueChecker(), 53a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson type_checkers.Int64ValueChecker()) 54a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson_FLOAT_INFINITY = re.compile('-?inf(?:inity)?f?', re.IGNORECASE) 55a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson_FLOAT_NAN = re.compile('nanf?', re.IGNORECASE) 56a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson_FLOAT_TYPES = frozenset([descriptor.FieldDescriptor.CPPTYPE_FLOAT, 57a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson descriptor.FieldDescriptor.CPPTYPE_DOUBLE]) 58fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 59d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 60a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidsonclass Error(Exception): 61a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson """Top-level module error for text_format.""" 62d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 63a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson 64a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidsonclass ParseError(Error): 65fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville """Thrown in case of ASCII parsing error.""" 66fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 67fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 68a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidsondef MessageToString(message, as_utf8=False, as_one_line=False, 69a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson pointy_brackets=False, use_index_order=False, 70a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson float_format=None): 71a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson """Convert protobuf message to text format. 72a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson 73a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson Floating point values can be formatted compactly with 15 digits of 74a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson precision (which is the most that IEEE 754 "double" can guarantee) 75a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson using float_format='.15g'. 76a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson 77a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson Args: 78a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson message: The protocol buffers message. 79a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson as_utf8: Produce text output in UTF8 format. 80a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson as_one_line: Don't introduce newlines between fields. 81a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson pointy_brackets: If True, use angle brackets instead of curly braces for 82a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson nesting. 83a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson use_index_order: If True, print fields of a proto message using the order 84a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson defined in source code instead of the field number. By default, use the 85a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson field number order. 86a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson float_format: If set, use this to specify floating point number formatting 87a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson (per the "Format Specification Mini-Language"); otherwise, str() is used. 88a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson 89a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson Returns: 90a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson A string of the text formatted protocol buffer message. 91a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson """ 92fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville out = cStringIO.StringIO() 93a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson PrintMessage(message, out, as_utf8=as_utf8, as_one_line=as_one_line, 94a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson pointy_brackets=pointy_brackets, 95a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson use_index_order=use_index_order, 96a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson float_format=float_format) 97fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville result = out.getvalue() 98fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville out.close() 99a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson if as_one_line: 100a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson return result.rstrip() 101fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return result 102fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 103fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 104a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidsondef PrintMessage(message, out, indent=0, as_utf8=False, as_one_line=False, 105a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson pointy_brackets=False, use_index_order=False, 106a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson float_format=None): 107a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson fields = message.ListFields() 108a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson if use_index_order: 109a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson fields.sort(key=lambda x: x[0].index) 110a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson for field, value in fields: 111fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if field.label == descriptor.FieldDescriptor.LABEL_REPEATED: 112fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville for element in value: 113a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson PrintField(field, element, out, indent, as_utf8, as_one_line, 114a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson pointy_brackets=pointy_brackets, 115a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson float_format=float_format) 116fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville else: 117a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson PrintField(field, value, out, indent, as_utf8, as_one_line, 118a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson pointy_brackets=pointy_brackets, 119a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson float_format=float_format) 120fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 121fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 122a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidsondef PrintField(field, value, out, indent=0, as_utf8=False, as_one_line=False, 123a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson pointy_brackets=False, float_format=None): 124fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville """Print a single field name/value pair. For repeated fields, the value 125fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville should be a single element.""" 126fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 127a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson out.write(' ' * indent) 128fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if field.is_extension: 129fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville out.write('[') 130fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (field.containing_type.GetOptions().message_set_wire_format and 131fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville field.type == descriptor.FieldDescriptor.TYPE_MESSAGE and 132fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville field.message_type == field.extension_scope and 133fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville field.label == descriptor.FieldDescriptor.LABEL_OPTIONAL): 134fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville out.write(field.message_type.full_name) 135fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville else: 136fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville out.write(field.full_name) 137fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville out.write(']') 138fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville elif field.type == descriptor.FieldDescriptor.TYPE_GROUP: 139fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville # For groups, use the capitalized name. 140fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville out.write(field.message_type.name) 141fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville else: 142fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville out.write(field.name) 143fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 144fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if field.cpp_type != descriptor.FieldDescriptor.CPPTYPE_MESSAGE: 145fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville # The colon is optional in this case, but our cross-language golden files 146fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville # don't include it. 147fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville out.write(': ') 148fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 149a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson PrintFieldValue(field, value, out, indent, as_utf8, as_one_line, 150a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson pointy_brackets=pointy_brackets, 151a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson float_format=float_format) 152a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson if as_one_line: 153a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson out.write(' ') 154a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson else: 155a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson out.write('\n') 156fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 157fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 158a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidsondef PrintFieldValue(field, value, out, indent=0, as_utf8=False, 159a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson as_one_line=False, pointy_brackets=False, 160a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson float_format=None): 161fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville """Print a single field value (not including name). For repeated fields, 162fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville the value should be a single element.""" 163fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 164a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson if pointy_brackets: 165a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson openb = '<' 166a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson closeb = '>' 167a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson else: 168a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson openb = '{' 169a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson closeb = '}' 170a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson 171fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_MESSAGE: 172a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson if as_one_line: 173a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson out.write(' %s ' % openb) 174a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson PrintMessage(value, out, indent, as_utf8, as_one_line, 175a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson pointy_brackets=pointy_brackets, 176a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson float_format=float_format) 177a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson out.write(closeb) 178a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson else: 179a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson out.write(' %s\n' % openb) 180a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson PrintMessage(value, out, indent + 2, as_utf8, as_one_line, 181a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson pointy_brackets=pointy_brackets, 182a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson float_format=float_format) 183a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson out.write(' ' * indent + closeb) 184fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_ENUM: 185a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson enum_value = field.enum_type.values_by_number.get(value, None) 186a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson if enum_value is not None: 187a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson out.write(enum_value.name) 188a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson else: 189a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson out.write(str(value)) 190fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_STRING: 191fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville out.write('\"') 192a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson if isinstance(value, unicode): 193a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson out_value = value.encode('utf-8') 194a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson else: 195a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson out_value = value 196a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson if field.type == descriptor.FieldDescriptor.TYPE_BYTES: 197a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson # We need to escape non-UTF8 chars in TYPE_BYTES field. 198a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson out_as_utf8 = False 199a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson else: 200a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson out_as_utf8 = as_utf8 201a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson out.write(text_encoding.CEscape(out_value, out_as_utf8)) 202fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville out.write('\"') 203fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_BOOL: 204fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if value: 205a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson out.write('true') 206fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville else: 207a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson out.write('false') 208a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson elif field.cpp_type in _FLOAT_TYPES and float_format is not None: 209a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson out.write('{1:{0}}'.format(float_format, value)) 210fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville else: 211fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville out.write(str(value)) 212fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 213fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 214a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidsondef _ParseOrMerge(lines, message, allow_multiple_scalars): 215a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson """Converts an ASCII representation of a protocol message into a message. 216a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson 217a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson Args: 218a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson lines: Lines of a message's ASCII representation. 219a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson message: A protocol buffer message to merge into. 220a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson allow_multiple_scalars: Determines if repeated values for a non-repeated 221a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson field are permitted, e.g., the string "foo: 1 foo: 2" for a 222a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson required/optional field named "foo". 223a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson 224a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson Raises: 225a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson ParseError: On ASCII parsing problems. 226a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson """ 227a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson tokenizer = _Tokenizer(lines) 228a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson while not tokenizer.AtEnd(): 229a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson _MergeField(tokenizer, message, allow_multiple_scalars) 230a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson 231a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson 232a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidsondef Parse(text, message): 233a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson """Parses an ASCII representation of a protocol message into a message. 234a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson 235a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson Args: 236a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson text: Message ASCII representation. 237a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson message: A protocol buffer message to merge into. 238a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson 239a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson Returns: 240a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson The same message passed as argument. 241a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson 242a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson Raises: 243a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson ParseError: On ASCII parsing problems. 244a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson """ 245a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson if not isinstance(text, str): text = text.decode('utf-8') 246a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson return ParseLines(text.split('\n'), message) 247a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson 248a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson 249fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilledef Merge(text, message): 250a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson """Parses an ASCII representation of a protocol message into a message. 251a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson 252a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson Like Parse(), but allows repeated values for a non-repeated field, and uses 253a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson the last one. 254fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 255fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville Args: 256fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville text: Message ASCII representation. 257fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville message: A protocol buffer message to merge into. 258fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 259a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson Returns: 260a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson The same message passed as argument. 261a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson 262fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville Raises: 263fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville ParseError: On ASCII parsing problems. 264fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville """ 265a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson return MergeLines(text.split('\n'), message) 266a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson 267a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson 268a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidsondef ParseLines(lines, message): 269a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson """Parses an ASCII representation of a protocol message into a message. 270a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson 271a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson Args: 272a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson lines: An iterable of lines of a message's ASCII representation. 273a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson message: A protocol buffer message to merge into. 274a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson 275a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson Returns: 276a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson The same message passed as argument. 277a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson 278a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson Raises: 279a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson ParseError: On ASCII parsing problems. 280a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson """ 281a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson _ParseOrMerge(lines, message, False) 282a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson return message 283a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson 284a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson 285a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidsondef MergeLines(lines, message): 286a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson """Parses an ASCII representation of a protocol message into a message. 287a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson 288a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson Args: 289a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson lines: An iterable of lines of a message's ASCII representation. 290a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson message: A protocol buffer message to merge into. 291a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson 292a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson Returns: 293a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson The same message passed as argument. 294fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 295a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson Raises: 296a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson ParseError: On ASCII parsing problems. 297a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson """ 298a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson _ParseOrMerge(lines, message, True) 299a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson return message 300fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 301a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson 302a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidsondef _MergeField(tokenizer, message, allow_multiple_scalars): 303fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville """Merges a single protocol message field into a message. 304fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 305fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville Args: 306fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville tokenizer: A tokenizer to parse the field name and values. 307fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville message: A protocol message to record the data. 308a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson allow_multiple_scalars: Determines if repeated values for a non-repeated 309a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson field are permitted, e.g., the string "foo: 1 foo: 2" for a 310a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson required/optional field named "foo". 311fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 312fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville Raises: 313fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville ParseError: In case of ASCII parsing problems. 314fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville """ 315fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville message_descriptor = message.DESCRIPTOR 316fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if tokenizer.TryConsume('['): 317fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville name = [tokenizer.ConsumeIdentifier()] 318fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville while tokenizer.TryConsume('.'): 319fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville name.append(tokenizer.ConsumeIdentifier()) 320fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville name = '.'.join(name) 321fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 322d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if not message_descriptor.is_extendable: 323d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville raise tokenizer.ParseErrorPreviousToken( 324d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 'Message type "%s" does not have extensions.' % 325d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville message_descriptor.full_name) 326a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson # pylint: disable=protected-access 327fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville field = message.Extensions._FindExtensionByName(name) 328a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson # pylint: enable=protected-access 329fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if not field: 330fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville raise tokenizer.ParseErrorPreviousToken( 331fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 'Extension "%s" not registered.' % name) 332fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville elif message_descriptor != field.containing_type: 333fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville raise tokenizer.ParseErrorPreviousToken( 334fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 'Extension "%s" does not extend message type "%s".' % ( 335fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville name, message_descriptor.full_name)) 336fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville tokenizer.Consume(']') 337fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville else: 338fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville name = tokenizer.ConsumeIdentifier() 339fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville field = message_descriptor.fields_by_name.get(name, None) 340fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 341fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville # Group names are expected to be capitalized as they appear in the 342fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville # .proto file, which actually matches their type names, not their field 343fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville # names. 344fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if not field: 345fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville field = message_descriptor.fields_by_name.get(name.lower(), None) 346fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if field and field.type != descriptor.FieldDescriptor.TYPE_GROUP: 347fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville field = None 348fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 349fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (field and field.type == descriptor.FieldDescriptor.TYPE_GROUP and 350fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville field.message_type.name != name): 351fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville field = None 352fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 353fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if not field: 354fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville raise tokenizer.ParseErrorPreviousToken( 355fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 'Message type "%s" has no field named "%s".' % ( 356fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville message_descriptor.full_name, name)) 357fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 358fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_MESSAGE: 359fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville tokenizer.TryConsume(':') 360fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 361fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if tokenizer.TryConsume('<'): 362fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville end_token = '>' 363fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville else: 364fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville tokenizer.Consume('{') 365fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville end_token = '}' 366fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 367fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if field.label == descriptor.FieldDescriptor.LABEL_REPEATED: 368fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if field.is_extension: 369fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville sub_message = message.Extensions[field].add() 370fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville else: 371fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville sub_message = getattr(message, field.name).add() 372fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville else: 373fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if field.is_extension: 374fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville sub_message = message.Extensions[field] 375fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville else: 376fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville sub_message = getattr(message, field.name) 377a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson sub_message.SetInParent() 378fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 379fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville while not tokenizer.TryConsume(end_token): 380fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if tokenizer.AtEnd(): 381fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville raise tokenizer.ParseErrorPreviousToken('Expected "%s".' % (end_token)) 382a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson _MergeField(tokenizer, sub_message, allow_multiple_scalars) 383fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville else: 384a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson _MergeScalarField(tokenizer, message, field, allow_multiple_scalars) 385a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson 386a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson # For historical reasons, fields may optionally be separated by commas or 387a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson # semicolons. 388a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson if not tokenizer.TryConsume(','): 389a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson tokenizer.TryConsume(';') 390fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 391fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 392a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidsondef _MergeScalarField(tokenizer, message, field, allow_multiple_scalars): 393fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville """Merges a single protocol message scalar field into a message. 394fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 395fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville Args: 396fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville tokenizer: A tokenizer to parse the field value. 397fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville message: A protocol message to record the data. 398fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville field: The descriptor of the field to be merged. 399a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson allow_multiple_scalars: Determines if repeated values for a non-repeated 400a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson field are permitted, e.g., the string "foo: 1 foo: 2" for a 401a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson required/optional field named "foo". 402fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 403fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville Raises: 404fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville ParseError: In case of ASCII parsing problems. 405fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville RuntimeError: On runtime errors. 406fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville """ 407fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville tokenizer.Consume(':') 408fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville value = None 409fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 410fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if field.type in (descriptor.FieldDescriptor.TYPE_INT32, 411fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville descriptor.FieldDescriptor.TYPE_SINT32, 412fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville descriptor.FieldDescriptor.TYPE_SFIXED32): 413fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville value = tokenizer.ConsumeInt32() 414fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville elif field.type in (descriptor.FieldDescriptor.TYPE_INT64, 415fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville descriptor.FieldDescriptor.TYPE_SINT64, 416fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville descriptor.FieldDescriptor.TYPE_SFIXED64): 417fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville value = tokenizer.ConsumeInt64() 418fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville elif field.type in (descriptor.FieldDescriptor.TYPE_UINT32, 419fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville descriptor.FieldDescriptor.TYPE_FIXED32): 420fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville value = tokenizer.ConsumeUint32() 421fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville elif field.type in (descriptor.FieldDescriptor.TYPE_UINT64, 422fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville descriptor.FieldDescriptor.TYPE_FIXED64): 423fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville value = tokenizer.ConsumeUint64() 424fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville elif field.type in (descriptor.FieldDescriptor.TYPE_FLOAT, 425fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville descriptor.FieldDescriptor.TYPE_DOUBLE): 426fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville value = tokenizer.ConsumeFloat() 427fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville elif field.type == descriptor.FieldDescriptor.TYPE_BOOL: 428fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville value = tokenizer.ConsumeBool() 429fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville elif field.type == descriptor.FieldDescriptor.TYPE_STRING: 430fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville value = tokenizer.ConsumeString() 431fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville elif field.type == descriptor.FieldDescriptor.TYPE_BYTES: 432fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville value = tokenizer.ConsumeByteString() 433fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville elif field.type == descriptor.FieldDescriptor.TYPE_ENUM: 434a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson value = tokenizer.ConsumeEnum(field) 435fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville else: 436fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville raise RuntimeError('Unknown field type %d' % field.type) 437fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 438fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if field.label == descriptor.FieldDescriptor.LABEL_REPEATED: 439fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if field.is_extension: 440fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville message.Extensions[field].append(value) 441fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville else: 442fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville getattr(message, field.name).append(value) 443fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville else: 444fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if field.is_extension: 445a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson if not allow_multiple_scalars and message.HasExtension(field): 446a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson raise tokenizer.ParseErrorPreviousToken( 447a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson 'Message type "%s" should not have multiple "%s" extensions.' % 448a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson (message.DESCRIPTOR.full_name, field.full_name)) 449a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson else: 450a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson message.Extensions[field] = value 451fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville else: 452a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson if not allow_multiple_scalars and message.HasField(field.name): 453a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson raise tokenizer.ParseErrorPreviousToken( 454a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson 'Message type "%s" should not have multiple "%s" fields.' % 455a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson (message.DESCRIPTOR.full_name, field.name)) 456a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson else: 457a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson setattr(message, field.name, value) 458fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 459fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 460fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleclass _Tokenizer(object): 461fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville """Protocol buffer ASCII representation tokenizer. 462fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 463fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville This class handles the lower level string parsing by splitting it into 464fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville meaningful tokens. 465fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 466fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville It was directly ported from the Java protocol buffer API. 467fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville """ 468fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 469fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville _WHITESPACE = re.compile('(\\s|(#.*$))+', re.MULTILINE) 470fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville _TOKEN = re.compile( 471fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville '[a-zA-Z_][0-9a-zA-Z_+-]*|' # an identifier 472fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville '[0-9+-][0-9a-zA-Z_.+-]*|' # a number 473fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville '\"([^\"\n\\\\]|\\\\.)*(\"|\\\\?$)|' # a double-quoted string 474d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville '\'([^\'\n\\\\]|\\\\.)*(\'|\\\\?$)') # a single-quoted string 475a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson _IDENTIFIER = re.compile(r'\w+') 476fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 477a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson def __init__(self, lines): 478fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville self._position = 0 479fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville self._line = -1 480fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville self._column = 0 481fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville self._token_start = None 482fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville self.token = '' 483a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson self._lines = iter(lines) 484fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville self._current_line = '' 485fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville self._previous_line = 0 486fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville self._previous_column = 0 487a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson self._more_lines = True 488fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville self._SkipWhitespace() 489fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville self.NextToken() 490fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 491fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville def AtEnd(self): 492fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville """Checks the end of the text was reached. 493fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 494fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville Returns: 495fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville True iff the end was reached. 496fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville """ 497a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson return not self.token 498fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 499fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville def _PopLine(self): 500a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson while len(self._current_line) <= self._column: 501a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson try: 502a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson self._current_line = self._lines.next() 503a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson except StopIteration: 504fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville self._current_line = '' 505a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson self._more_lines = False 506fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return 507a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson else: 508a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson self._line += 1 509a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson self._column = 0 510fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 511fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville def _SkipWhitespace(self): 512fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville while True: 513fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville self._PopLine() 514a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson match = self._WHITESPACE.match(self._current_line, self._column) 515fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if not match: 516fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville break 517fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville length = len(match.group(0)) 518fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville self._column += length 519fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 520fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville def TryConsume(self, token): 521fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville """Tries to consume a given piece of text. 522fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 523fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville Args: 524fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville token: Text to consume. 525fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 526fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville Returns: 527fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville True iff the text was consumed. 528fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville """ 529fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if self.token == token: 530fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville self.NextToken() 531fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return True 532fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return False 533fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 534fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville def Consume(self, token): 535fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville """Consumes a piece of text. 536fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 537fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville Args: 538fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville token: Text to consume. 539fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 540fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville Raises: 541fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville ParseError: If the text couldn't be consumed. 542fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville """ 543fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if not self.TryConsume(token): 544fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville raise self._ParseError('Expected "%s".' % token) 545fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 546fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville def ConsumeIdentifier(self): 547fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville """Consumes protocol message field identifier. 548fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 549fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville Returns: 550fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville Identifier string. 551fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 552fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville Raises: 553fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville ParseError: If an identifier couldn't be consumed. 554fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville """ 555fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville result = self.token 556a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson if not self._IDENTIFIER.match(result): 557fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville raise self._ParseError('Expected identifier.') 558fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville self.NextToken() 559fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return result 560fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 561fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville def ConsumeInt32(self): 562fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville """Consumes a signed 32bit integer number. 563fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 564fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville Returns: 565fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville The integer parsed. 566fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 567fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville Raises: 568fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville ParseError: If a signed 32bit integer couldn't be consumed. 569fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville """ 570fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville try: 571a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson result = ParseInteger(self.token, is_signed=True, is_long=False) 572fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville except ValueError, e: 573a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson raise self._ParseError(str(e)) 574fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville self.NextToken() 575fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return result 576fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 577fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville def ConsumeUint32(self): 578fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville """Consumes an unsigned 32bit integer number. 579fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 580fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville Returns: 581fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville The integer parsed. 582fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 583fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville Raises: 584fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville ParseError: If an unsigned 32bit integer couldn't be consumed. 585fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville """ 586fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville try: 587a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson result = ParseInteger(self.token, is_signed=False, is_long=False) 588fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville except ValueError, e: 589a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson raise self._ParseError(str(e)) 590fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville self.NextToken() 591fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return result 592fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 593fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville def ConsumeInt64(self): 594fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville """Consumes a signed 64bit integer number. 595fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 596fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville Returns: 597fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville The integer parsed. 598fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 599fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville Raises: 600fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville ParseError: If a signed 64bit integer couldn't be consumed. 601fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville """ 602fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville try: 603a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson result = ParseInteger(self.token, is_signed=True, is_long=True) 604fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville except ValueError, e: 605a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson raise self._ParseError(str(e)) 606fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville self.NextToken() 607fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return result 608fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 609fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville def ConsumeUint64(self): 610fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville """Consumes an unsigned 64bit integer number. 611fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 612fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville Returns: 613fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville The integer parsed. 614fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 615fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville Raises: 616fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville ParseError: If an unsigned 64bit integer couldn't be consumed. 617fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville """ 618fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville try: 619a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson result = ParseInteger(self.token, is_signed=False, is_long=True) 620fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville except ValueError, e: 621a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson raise self._ParseError(str(e)) 622fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville self.NextToken() 623fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return result 624fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 625fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville def ConsumeFloat(self): 626fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville """Consumes an floating point number. 627fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 628fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville Returns: 629fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville The number parsed. 630fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 631fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville Raises: 632fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville ParseError: If a floating point number couldn't be consumed. 633fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville """ 634fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville try: 635a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson result = ParseFloat(self.token) 636fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville except ValueError, e: 637a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson raise self._ParseError(str(e)) 638fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville self.NextToken() 639fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return result 640fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 641fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville def ConsumeBool(self): 642fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville """Consumes a boolean value. 643fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 644fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville Returns: 645fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville The bool parsed. 646fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 647fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville Raises: 648fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville ParseError: If a boolean value couldn't be consumed. 649fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville """ 650a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson try: 651a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson result = ParseBool(self.token) 652a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson except ValueError, e: 653a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson raise self._ParseError(str(e)) 654a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson self.NextToken() 655a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson return result 656fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 657fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville def ConsumeString(self): 658fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville """Consumes a string value. 659fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 660fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville Returns: 661fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville The string parsed. 662fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 663fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville Raises: 664fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville ParseError: If a string value couldn't be consumed. 665fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville """ 666a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson the_bytes = self.ConsumeByteString() 667a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson try: 668a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson return unicode(the_bytes, 'utf-8') 669a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson except UnicodeDecodeError, e: 670a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson raise self._StringParseError(e) 671fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 672fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville def ConsumeByteString(self): 673fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville """Consumes a byte array value. 674fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 675fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville Returns: 676fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville The array parsed (as a string). 677fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 678fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville Raises: 679fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville ParseError: If a byte array value couldn't be consumed. 680fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville """ 681a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson the_list = [self._ConsumeSingleByteString()] 682a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson while self.token and self.token[0] in ('\'', '"'): 683a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson the_list.append(self._ConsumeSingleByteString()) 684a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson return ''.encode('latin1').join(the_list) ##PY25 685a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson##!PY25 return b''.join(the_list) 686d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 687d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville def _ConsumeSingleByteString(self): 688d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville """Consume one token of a string literal. 689d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 690d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville String literals (whether bytes or text) can come in multiple adjacent 691d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville tokens which are automatically concatenated, like in C or Python. This 692d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville method only consumes one token. 693d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville """ 694fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville text = self.token 695fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if len(text) < 1 or text[0] not in ('\'', '"'): 696a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson raise self._ParseError('Expected string.') 697fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 698fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if len(text) < 2 or text[-1] != text[0]: 699fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville raise self._ParseError('String missing ending quote.') 700fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 701fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville try: 702a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson result = text_encoding.CUnescape(text[1:-1]) 703fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville except ValueError, e: 704fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville raise self._ParseError(str(e)) 705fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville self.NextToken() 706fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return result 707fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 708a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson def ConsumeEnum(self, field): 709a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson try: 710a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson result = ParseEnum(field, self.token) 711a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson except ValueError, e: 712a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson raise self._ParseError(str(e)) 713a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson self.NextToken() 714fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return result 715fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 716fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville def ParseErrorPreviousToken(self, message): 717fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville """Creates and *returns* a ParseError for the previously read token. 718fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 719fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville Args: 720fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville message: A message to set for the exception. 721fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 722fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville Returns: 723fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville A ParseError instance. 724fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville """ 725fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return ParseError('%d:%d : %s' % ( 726fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville self._previous_line + 1, self._previous_column + 1, message)) 727fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 728fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville def _ParseError(self, message): 729fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville """Creates and *returns* a ParseError for the current token.""" 730fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return ParseError('%d:%d : %s' % ( 731fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville self._line + 1, self._column + 1, message)) 732fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 733a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson def _StringParseError(self, e): 734a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson return self._ParseError('Couldn\'t parse string: ' + str(e)) 735fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 736fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville def NextToken(self): 737fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville """Reads the next meaningful token.""" 738fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville self._previous_line = self._line 739fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville self._previous_column = self._column 740a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson 741fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville self._column += len(self.token) 742a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson self._SkipWhitespace() 743fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 744a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson if not self._more_lines: 745a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson self.token = '' 746a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson return 747fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 748a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson match = self._TOKEN.match(self._current_line, self._column) 749fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if match: 750fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville token = match.group(0) 751fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville self.token = token 752fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville else: 753a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson self.token = self._current_line[self._column] 754a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson 755a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson 756a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidsondef ParseInteger(text, is_signed=False, is_long=False): 757a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson """Parses an integer. 758a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson 759a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson Args: 760a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson text: The text to parse. 761a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson is_signed: True if a signed integer must be parsed. 762a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson is_long: True if a long integer must be parsed. 763a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson 764a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson Returns: 765a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson The integer value. 766a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson 767a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson Raises: 768a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson ValueError: Thrown Iff the text is not a valid integer. 769a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson """ 770a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson # Do the actual parsing. Exception handling is propagated to caller. 771a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson try: 772a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson # We force 32-bit values to int and 64-bit values to long to make 773a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson # alternate implementations where the distinction is more significant 774a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson # (e.g. the C++ implementation) simpler. 775a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson if is_long: 776a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson result = long(text, 0) 777a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson else: 778a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson result = int(text, 0) 779a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson except ValueError: 780a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson raise ValueError('Couldn\'t parse integer: %s' % text) 781a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson 782a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson # Check if the integer is sane. Exceptions handled by callers. 783a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson checker = _INTEGER_CHECKERS[2 * int(is_long) + int(is_signed)] 784a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson checker.CheckValue(result) 785a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson return result 786a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson 787a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson 788a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidsondef ParseFloat(text): 789a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson """Parse a floating point number. 790a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson 791a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson Args: 792a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson text: Text to parse. 793fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 794a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson Returns: 795a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson The number parsed. 796fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 797a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson Raises: 798a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson ValueError: If a floating point number couldn't be parsed. 799a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson """ 800a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson try: 801a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson # Assume Python compatible syntax. 802a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson return float(text) 803a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson except ValueError: 804a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson # Check alternative spellings. 805a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson if _FLOAT_INFINITY.match(text): 806a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson if text[0] == '-': 807a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson return float('-inf') 808a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson else: 809a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson return float('inf') 810a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson elif _FLOAT_NAN.match(text): 811a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson return float('nan') 812a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson else: 813a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson # assume '1.0f' format 814a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson try: 815a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson return float(text.rstrip('f')) 816a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson except ValueError: 817a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson raise ValueError('Couldn\'t parse float: %s' % text) 818a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson 819a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson 820a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidsondef ParseBool(text): 821a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson """Parse a boolean value. 822a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson 823a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson Args: 824a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson text: Text to parse. 825a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson 826a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson Returns: 827a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson Boolean values parsed 828fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 829a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson Raises: 830a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson ValueError: If text is not a valid boolean. 831a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson """ 832a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson if text in ('true', 't', '1'): 833a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson return True 834a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson elif text in ('false', 'f', '0'): 835a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson return False 836a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson else: 837a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson raise ValueError('Expected "true" or "false".') 838fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 839fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 840a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidsondef ParseEnum(field, value): 841a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson """Parse an enum value. 842fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 843a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson The value can be specified by a number (the enum value), or by 844a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson a string literal (the enum name). 845fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 846a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson Args: 847a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson field: Enum field descriptor. 848a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson value: String value. 849fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 850a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson Returns: 851a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson Enum value number. 852a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson 853a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson Raises: 854a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson ValueError: If the enum value could not be parsed. 855a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson """ 856a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson enum_descriptor = field.enum_type 857a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson try: 858a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson number = int(value, 0) 859a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson except ValueError: 860a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson # Identifier. 861a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson enum_value = enum_descriptor.values_by_name.get(value, None) 862a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson if enum_value is None: 863a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson raise ValueError( 864a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson 'Enum type "%s" has no value named %s.' % ( 865a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson enum_descriptor.full_name, value)) 866a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson else: 867a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson # Numeric value. 868a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson enum_value = enum_descriptor.values_by_number.get(number, None) 869a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson if enum_value is None: 870a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson raise ValueError( 871a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson 'Enum type "%s" has no value with number %d.' % ( 872a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson enum_descriptor.full_name, number)) 873a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson return enum_value.number 874