Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
text_format.py1835 linesDownload Raw Back to protobuf
1# Protocol Buffers - Google's data interchange format2# Copyright 2008 Google Inc.  All rights reserved.3#4# Use of this source code is governed by a BSD-style5# license that can be found in the LICENSE file or at6# https://developers.google.com/open-source/licenses/bsd7 8"""Contains routines for printing protocol messages in text format.9 10Simple usage example::11 12  # Create a proto object and serialize it to a text proto string.13  message = my_proto_pb2.MyMessage(foo='bar')14  text_proto = text_format.MessageToString(message)15 16  # Parse a text proto string.17  message = text_format.Parse(text_proto, my_proto_pb2.MyMessage())18"""19 20__author__ = 'kenton@google.com (Kenton Varda)'21 22# TODO Import thread contention leads to test failures.23import encodings.raw_unicode_escape  # pylint: disable=unused-import24import encodings.unicode_escape  # pylint: disable=unused-import25import io26import math27import re28 29from google.protobuf.internal import decoder30from google.protobuf.internal import type_checkers31from google.protobuf import descriptor32from google.protobuf import text_encoding33from google.protobuf import unknown_fields34 35# pylint: disable=g-import-not-at-top36__all__ = ['MessageToString', 'Parse', 'PrintMessage', 'PrintField',37           'PrintFieldValue', 'Merge', 'MessageToBytes']38 39_INTEGER_CHECKERS = (type_checkers.Uint32ValueChecker(),40                     type_checkers.Int32ValueChecker(),41                     type_checkers.Uint64ValueChecker(),42                     type_checkers.Int64ValueChecker())43_FLOAT_INFINITY = re.compile('-?inf(?:inity)?f?$', re.IGNORECASE)44_FLOAT_NAN = re.compile('nanf?$', re.IGNORECASE)45_QUOTES = frozenset(("'", '"'))46_ANY_FULL_TYPE_NAME = 'google.protobuf.Any'47_DEBUG_STRING_SILENT_MARKER = '\t '48 49 50class Error(Exception):51  """Top-level module error for text_format."""52 53 54class ParseError(Error):55  """Thrown in case of text parsing or tokenizing error."""56 57  def __init__(self, message=None, line=None, column=None):58    if message is not None and line is not None:59      loc = str(line)60      if column is not None:61        loc += ':{0}'.format(column)62      message = '{0} : {1}'.format(loc, message)63    if message is not None:64      super(ParseError, self).__init__(message)65    else:66      super(ParseError, self).__init__()67    self._line = line68    self._column = column69 70  def GetLine(self):71    return self._line72 73  def GetColumn(self):74    return self._column75 76 77class TextWriter(object):78 79  def __init__(self, as_utf8):80    self._writer = io.StringIO()81 82  def write(self, val):83    return self._writer.write(val)84 85  def close(self):86    return self._writer.close()87 88  def getvalue(self):89    return self._writer.getvalue()90 91 92def MessageToString(93    message,94    as_utf8=False,95    as_one_line=False,96    use_short_repeated_primitives=False,97    pointy_brackets=False,98    use_index_order=False,99    float_format=None,100    double_format=None,101    use_field_number=False,102    descriptor_pool=None,103    indent=0,104    message_formatter=None,105    print_unknown_fields=False,106    force_colon=False) -> str:107  """Convert protobuf message to text format.108 109  Double values can be formatted compactly with 15 digits of110  precision (which is the most that IEEE 754 "double" can guarantee)111  using double_format='.15g'. To ensure that converting to text and back to a112  proto will result in an identical value, double_format='.17g' should be used.113 114  Args:115    message: The protocol buffers message.116    as_utf8: Return unescaped Unicode for non-ASCII characters.117    as_one_line: Don't introduce newlines between fields.118    use_short_repeated_primitives: Use short repeated format for primitives.119    pointy_brackets: If True, use angle brackets instead of curly braces for120      nesting.121    use_index_order: If True, fields of a proto message will be printed using122      the order defined in source code instead of the field number, extensions123      will be printed at the end of the message and their relative order is124      determined by the extension number. By default, use the field number125      order.126    float_format (str): If set, use this to specify float field formatting127      (per the "Format Specification Mini-Language"); otherwise, shortest float128      that has same value in wire will be printed. Also affect double field129      if double_format is not set but float_format is set.130    double_format (str): If set, use this to specify double field formatting131      (per the "Format Specification Mini-Language"); if it is not set but132      float_format is set, use float_format. Otherwise, use ``str()``133    use_field_number: If True, print field numbers instead of names.134    descriptor_pool (DescriptorPool): Descriptor pool used to resolve Any types.135    indent (int): The initial indent level, in terms of spaces, for pretty136      print.137    message_formatter (function(message, indent, as_one_line) -> unicode|None):138      Custom formatter for selected sub-messages (usually based on message139      type). Use to pretty print parts of the protobuf for easier diffing.140    print_unknown_fields: If True, unknown fields will be printed.141    force_colon: If set, a colon will be added after the field name even if the142      field is a proto message.143 144  Returns:145    str: A string of the text formatted protocol buffer message.146  """147  out = TextWriter(as_utf8)148  printer = _Printer(149      out,150      indent,151      as_utf8,152      as_one_line,153      use_short_repeated_primitives,154      pointy_brackets,155      use_index_order,156      float_format,157      double_format,158      use_field_number,159      descriptor_pool,160      message_formatter,161      print_unknown_fields=print_unknown_fields,162      force_colon=force_colon)163  printer.PrintMessage(message)164  result = out.getvalue()165  out.close()166  if as_one_line:167    return result.rstrip()168  return result169 170 171def MessageToBytes(message, **kwargs) -> bytes:172  """Convert protobuf message to encoded text format.  See MessageToString."""173  text = MessageToString(message, **kwargs)174  if isinstance(text, bytes):175    return text176  codec = 'utf-8' if kwargs.get('as_utf8') else 'ascii'177  return text.encode(codec)178 179 180def _IsMapEntry(field):181  return (field.type == descriptor.FieldDescriptor.TYPE_MESSAGE and182          field.message_type.has_options and183          field.message_type.GetOptions().map_entry)184 185 186def PrintMessage(message,187                 out,188                 indent=0,189                 as_utf8=False,190                 as_one_line=False,191                 use_short_repeated_primitives=False,192                 pointy_brackets=False,193                 use_index_order=False,194                 float_format=None,195                 double_format=None,196                 use_field_number=False,197                 descriptor_pool=None,198                 message_formatter=None,199                 print_unknown_fields=False,200                 force_colon=False):201  """Convert the message to text format and write it to the out stream.202 203  Args:204    message: The Message object to convert to text format.205    out: A file handle to write the message to.206    indent: The initial indent level for pretty print.207    as_utf8: Return unescaped Unicode for non-ASCII characters.208    as_one_line: Don't introduce newlines between fields.209    use_short_repeated_primitives: Use short repeated format for primitives.210    pointy_brackets: If True, use angle brackets instead of curly braces for211      nesting.212    use_index_order: If True, print fields of a proto message using the order213      defined in source code instead of the field number. By default, use the214      field number order.215    float_format: If set, use this to specify float field formatting216      (per the "Format Specification Mini-Language"); otherwise, shortest217      float that has same value in wire will be printed. Also affect double218      field if double_format is not set but float_format is set.219    double_format: If set, use this to specify double field formatting220      (per the "Format Specification Mini-Language"); if it is not set but221      float_format is set, use float_format. Otherwise, str() is used.222    use_field_number: If True, print field numbers instead of names.223    descriptor_pool: A DescriptorPool used to resolve Any types.224    message_formatter: A function(message, indent, as_one_line): unicode|None225      to custom format selected sub-messages (usually based on message type).226      Use to pretty print parts of the protobuf for easier diffing.227    print_unknown_fields: If True, unknown fields will be printed.228    force_colon: If set, a colon will be added after the field name even if229      the field is a proto message.230  """231  printer = _Printer(232      out=out, indent=indent, as_utf8=as_utf8,233      as_one_line=as_one_line,234      use_short_repeated_primitives=use_short_repeated_primitives,235      pointy_brackets=pointy_brackets,236      use_index_order=use_index_order,237      float_format=float_format,238      double_format=double_format,239      use_field_number=use_field_number,240      descriptor_pool=descriptor_pool,241      message_formatter=message_formatter,242      print_unknown_fields=print_unknown_fields,243      force_colon=force_colon)244  printer.PrintMessage(message)245 246 247def PrintField(field,248               value,249               out,250               indent=0,251               as_utf8=False,252               as_one_line=False,253               use_short_repeated_primitives=False,254               pointy_brackets=False,255               use_index_order=False,256               float_format=None,257               double_format=None,258               message_formatter=None,259               print_unknown_fields=False,260               force_colon=False):261  """Print a single field name/value pair."""262  printer = _Printer(out, indent, as_utf8, as_one_line,263                     use_short_repeated_primitives, pointy_brackets,264                     use_index_order, float_format, double_format,265                     message_formatter=message_formatter,266                     print_unknown_fields=print_unknown_fields,267                     force_colon=force_colon)268  printer.PrintField(field, value)269 270 271def PrintFieldValue(field,272                    value,273                    out,274                    indent=0,275                    as_utf8=False,276                    as_one_line=False,277                    use_short_repeated_primitives=False,278                    pointy_brackets=False,279                    use_index_order=False,280                    float_format=None,281                    double_format=None,282                    message_formatter=None,283                    print_unknown_fields=False,284                    force_colon=False):285  """Print a single field value (not including name)."""286  printer = _Printer(out, indent, as_utf8, as_one_line,287                     use_short_repeated_primitives, pointy_brackets,288                     use_index_order, float_format, double_format,289                     message_formatter=message_formatter,290                     print_unknown_fields=print_unknown_fields,291                     force_colon=force_colon)292  printer.PrintFieldValue(field, value)293 294 295def _BuildMessageFromTypeName(type_name, descriptor_pool):296  """Returns a protobuf message instance.297 298  Args:299    type_name: Fully-qualified protobuf  message type name string.300    descriptor_pool: DescriptorPool instance.301 302  Returns:303    A Message instance of type matching type_name, or None if the a Descriptor304    wasn't found matching type_name.305  """306  # pylint: disable=g-import-not-at-top307  if descriptor_pool is None:308    from google.protobuf import descriptor_pool as pool_mod309    descriptor_pool = pool_mod.Default()310  from google.protobuf import message_factory311  try:312    message_descriptor = descriptor_pool.FindMessageTypeByName(type_name)313  except KeyError:314    return None315  message_type = message_factory.GetMessageClass(message_descriptor)316  return message_type()317 318 319# These values must match WireType enum in //google/protobuf/wire_format.h.320WIRETYPE_LENGTH_DELIMITED = 2321WIRETYPE_START_GROUP = 3322 323 324class _Printer(object):325  """Text format printer for protocol message."""326 327  def __init__(328      self,329      out,330      indent=0,331      as_utf8=False,332      as_one_line=False,333      use_short_repeated_primitives=False,334      pointy_brackets=False,335      use_index_order=False,336      float_format=None,337      double_format=None,338      use_field_number=False,339      descriptor_pool=None,340      message_formatter=None,341      print_unknown_fields=False,342      force_colon=False):343    """Initialize the Printer.344 345    Double values can be formatted compactly with 15 digits of precision346    (which is the most that IEEE 754 "double" can guarantee) using347    double_format='.15g'. To ensure that converting to text and back to a proto348    will result in an identical value, double_format='.17g' should be used.349 350    Args:351      out: To record the text format result.352      indent: The initial indent level for pretty print.353      as_utf8: Return unescaped Unicode for non-ASCII characters.354      as_one_line: Don't introduce newlines between fields.355      use_short_repeated_primitives: Use short repeated format for primitives.356      pointy_brackets: If True, use angle brackets instead of curly braces for357        nesting.358      use_index_order: If True, print fields of a proto message using the order359        defined in source code instead of the field number. By default, use the360        field number order.361      float_format: If set, use this to specify float field formatting362        (per the "Format Specification Mini-Language"); otherwise, shortest363        float that has same value in wire will be printed. Also affect double364        field if double_format is not set but float_format is set.365      double_format: If set, use this to specify double field formatting366        (per the "Format Specification Mini-Language"); if it is not set but367        float_format is set, use float_format. Otherwise, str() is used.368      use_field_number: If True, print field numbers instead of names.369      descriptor_pool: A DescriptorPool used to resolve Any types.370      message_formatter: A function(message, indent, as_one_line): unicode|None371        to custom format selected sub-messages (usually based on message type).372        Use to pretty print parts of the protobuf for easier diffing.373      print_unknown_fields: If True, unknown fields will be printed.374      force_colon: If set, a colon will be added after the field name even if375        the field is a proto message.376    """377    self.out = out378    self.indent = indent379    self.as_utf8 = as_utf8380    self.as_one_line = as_one_line381    self.use_short_repeated_primitives = use_short_repeated_primitives382    self.pointy_brackets = pointy_brackets383    self.use_index_order = use_index_order384    self.float_format = float_format385    if double_format is not None:386      self.double_format = double_format387    else:388      self.double_format = float_format389    self.use_field_number = use_field_number390    self.descriptor_pool = descriptor_pool391    self.message_formatter = message_formatter392    self.print_unknown_fields = print_unknown_fields393    self.force_colon = force_colon394 395  def _TryPrintAsAnyMessage(self, message):396    """Serializes if message is a google.protobuf.Any field."""397    if '/' not in message.type_url:398      return False399    packed_message = _BuildMessageFromTypeName(message.TypeName(),400                                               self.descriptor_pool)401    if packed_message:402      packed_message.MergeFromString(message.value)403      colon = ':' if self.force_colon else ''404      self.out.write('%s[%s]%s ' % (self.indent * ' ', message.type_url, colon))405      self._PrintMessageFieldValue(packed_message)406      self.out.write(' ' if self.as_one_line else '\n')407      return True408    else:409      return False410 411  def _TryCustomFormatMessage(self, message):412    formatted = self.message_formatter(message, self.indent, self.as_one_line)413    if formatted is None:414      return False415 416    out = self.out417    out.write(' ' * self.indent)418    out.write(formatted)419    out.write(' ' if self.as_one_line else '\n')420    return True421 422  def PrintMessage(self, message):423    """Convert protobuf message to text format.424 425    Args:426      message: The protocol buffers message.427    """428    if self.message_formatter and self._TryCustomFormatMessage(message):429      return430    if (message.DESCRIPTOR.full_name == _ANY_FULL_TYPE_NAME and431        self._TryPrintAsAnyMessage(message)):432      return433    fields = message.ListFields()434    if self.use_index_order:435      fields.sort(436          key=lambda x: x[0].number if x[0].is_extension else x[0].index)437    for field, value in fields:438      if _IsMapEntry(field):439        for key in sorted(value):440          # This is slow for maps with submessage entries because it copies the441          # entire tree.  Unfortunately this would take significant refactoring442          # of this file to work around.443          #444          # TODO: refactor and optimize if this becomes an issue.445          entry_submsg = value.GetEntryClass()(key=key, value=value[key])446          self.PrintField(field, entry_submsg)447      elif field.label == descriptor.FieldDescriptor.LABEL_REPEATED:448        if (self.use_short_repeated_primitives449            and field.cpp_type != descriptor.FieldDescriptor.CPPTYPE_MESSAGE450            and field.cpp_type != descriptor.FieldDescriptor.CPPTYPE_STRING):451          self._PrintShortRepeatedPrimitivesValue(field, value)452        else:453          for element in value:454            self.PrintField(field, element)455      else:456        self.PrintField(field, value)457 458    if self.print_unknown_fields:459      self._PrintUnknownFields(unknown_fields.UnknownFieldSet(message))460 461  def _PrintUnknownFields(self, unknown_field_set):462    """Print unknown fields."""463    out = self.out464    for field in unknown_field_set:465      out.write(' ' * self.indent)466      out.write(str(field.field_number))467      if field.wire_type == WIRETYPE_START_GROUP:468        if self.as_one_line:469          out.write(' { ')470        else:471          out.write(' {\n')472          self.indent += 2473 474        self._PrintUnknownFields(field.data)475 476        if self.as_one_line:477          out.write('} ')478        else:479          self.indent -= 2480          out.write(' ' * self.indent + '}\n')481      elif field.wire_type == WIRETYPE_LENGTH_DELIMITED:482        try:483          # If this field is parseable as a Message, it is probably484          # an embedded message.485          # pylint: disable=protected-access486          (embedded_unknown_message, pos) = decoder._DecodeUnknownFieldSet(487              memoryview(field.data), 0, len(field.data))488        except Exception:    # pylint: disable=broad-except489          pos = 0490 491        if pos == len(field.data):492          if self.as_one_line:493            out.write(' { ')494          else:495            out.write(' {\n')496            self.indent += 2497 498          self._PrintUnknownFields(embedded_unknown_message)499 500          if self.as_one_line:501            out.write('} ')502          else:503            self.indent -= 2504            out.write(' ' * self.indent + '}\n')505        else:506          # A string or bytes field. self.as_utf8 may not work.507          out.write(': \"')508          out.write(text_encoding.CEscape(field.data, False))509          out.write('\" ' if self.as_one_line else '\"\n')510      else:511        # varint, fixed32, fixed64512        out.write(': ')513        out.write(str(field.data))514        out.write(' ' if self.as_one_line else '\n')515 516  def _PrintFieldName(self, field):517    """Print field name."""518    out = self.out519    out.write(' ' * self.indent)520    if self.use_field_number:521      out.write(str(field.number))522    else:523      if field.is_extension:524        out.write('[')525        if (field.containing_type.GetOptions().message_set_wire_format and526            field.type == descriptor.FieldDescriptor.TYPE_MESSAGE and527            field.label == descriptor.FieldDescriptor.LABEL_OPTIONAL):528          out.write(field.message_type.full_name)529        else:530          out.write(field.full_name)531        out.write(']')532      elif field.type == descriptor.FieldDescriptor.TYPE_GROUP:533        # For groups, use the capitalized name.534        out.write(field.message_type.name)535      else:536        out.write(field.name)537 538    if (self.force_colon or539        field.cpp_type != descriptor.FieldDescriptor.CPPTYPE_MESSAGE):540      # The colon is optional in this case, but our cross-language golden files541      # don't include it. Here, the colon is only included if force_colon is542      # set to True543      out.write(':')544 545  def PrintField(self, field, value):546    """Print a single field name/value pair."""547    self._PrintFieldName(field)548    self.out.write(' ')549    self.PrintFieldValue(field, value)550    self.out.write(' ' if self.as_one_line else '\n')551 552  def _PrintShortRepeatedPrimitivesValue(self, field, value):553    """"Prints short repeated primitives value."""554    # Note: this is called only when value has at least one element.555    self._PrintFieldName(field)556    self.out.write(' [')557    for i in range(len(value) - 1):558      self.PrintFieldValue(field, value[i])559      self.out.write(', ')560    self.PrintFieldValue(field, value[-1])561    self.out.write(']')562    self.out.write(' ' if self.as_one_line else '\n')563 564  def _PrintMessageFieldValue(self, value):565    if self.pointy_brackets:566      openb = '<'567      closeb = '>'568    else:569      openb = '{'570      closeb = '}'571 572    if self.as_one_line:573      self.out.write('%s ' % openb)574      self.PrintMessage(value)575      self.out.write(closeb)576    else:577      self.out.write('%s\n' % openb)578      self.indent += 2579      self.PrintMessage(value)580      self.indent -= 2581      self.out.write(' ' * self.indent + closeb)582 583  def PrintFieldValue(self, field, value):584    """Print a single field value (not including name).585 586    For repeated fields, the value should be a single element.587 588    Args:589      field: The descriptor of the field to be printed.590      value: The value of the field.591    """592    out = self.out593    if field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_MESSAGE:594      self._PrintMessageFieldValue(value)595    elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_ENUM:596      enum_value = field.enum_type.values_by_number.get(value, None)597      if enum_value is not None:598        out.write(enum_value.name)599      else:600        out.write(str(value))601    elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_STRING:602      out.write('\"')603      if isinstance(value, str) and not self.as_utf8:604        out_value = value.encode('utf-8')605      else:606        out_value = value607      if field.type == descriptor.FieldDescriptor.TYPE_BYTES:608        # We always need to escape all binary data in TYPE_BYTES fields.609        out_as_utf8 = False610      else:611        out_as_utf8 = self.as_utf8612      out.write(text_encoding.CEscape(out_value, out_as_utf8))613      out.write('\"')614    elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_BOOL:615      if value:616        out.write('true')617      else:618        out.write('false')619    elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_FLOAT:620      if self.float_format is not None:621        out.write('{1:{0}}'.format(self.float_format, value))622      else:623        if math.isnan(value):624          out.write(str(value))625        else:626          out.write(str(type_checkers.ToShortestFloat(value)))627    elif (field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_DOUBLE and628          self.double_format is not None):629      out.write('{1:{0}}'.format(self.double_format, value))630    else:631      out.write(str(value))632 633 634def Parse(text,635          message,636          allow_unknown_extension=False,637          allow_field_number=False,638          descriptor_pool=None,639          allow_unknown_field=False):640  """Parses a text representation of a protocol message into a message.641 642  NOTE: for historical reasons this function does not clear the input643  message. This is different from what the binary msg.ParseFrom(...) does.644  If text contains a field already set in message, the value is appended if the645  field is repeated. Otherwise, an error is raised.646 647  Example::648 649    a = MyProto()650    a.repeated_field.append('test')651    b = MyProto()652 653    # Repeated fields are combined654    text_format.Parse(repr(a), b)655    text_format.Parse(repr(a), b) # repeated_field contains ["test", "test"]656 657    # Non-repeated fields cannot be overwritten658    a.singular_field = 1659    b.singular_field = 2660    text_format.Parse(repr(a), b) # ParseError661 662    # Binary version:663    b.ParseFromString(a.SerializeToString()) # repeated_field is now "test"664 665  Caller is responsible for clearing the message as needed.666 667  Args:668    text (str): Message text representation.669    message (Message): A protocol buffer message to merge into.670    allow_unknown_extension: if True, skip over missing extensions and keep671      parsing672    allow_field_number: if True, both field number and field name are allowed.673    descriptor_pool (DescriptorPool): Descriptor pool used to resolve Any types.674    allow_unknown_field: if True, skip over unknown field and keep675      parsing. Avoid to use this option if possible. It may hide some676      errors (e.g. spelling error on field name)677 678  Returns:679    Message: The same message passed as argument.680 681  Raises:682    ParseError: On text parsing problems.683  """684  return ParseLines(text.split(b'\n' if isinstance(text, bytes) else u'\n'),685                    message,686                    allow_unknown_extension,687                    allow_field_number,688                    descriptor_pool=descriptor_pool,689                    allow_unknown_field=allow_unknown_field)690 691 692def Merge(text,693          message,694          allow_unknown_extension=False,695          allow_field_number=False,696          descriptor_pool=None,697          allow_unknown_field=False):698  """Parses a text representation of a protocol message into a message.699 700  Like Parse(), but allows repeated values for a non-repeated field, and uses701  the last one. This means any non-repeated, top-level fields specified in text702  replace those in the message.703 704  Args:705    text (str): Message text representation.706    message (Message): A protocol buffer message to merge into.707    allow_unknown_extension: if True, skip over missing extensions and keep708      parsing709    allow_field_number: if True, both field number and field name are allowed.710    descriptor_pool (DescriptorPool): Descriptor pool used to resolve Any types.711    allow_unknown_field: if True, skip over unknown field and keep712      parsing. Avoid to use this option if possible. It may hide some713      errors (e.g. spelling error on field name)714 715  Returns:716    Message: The same message passed as argument.717 718  Raises:719    ParseError: On text parsing problems.720  """721  return MergeLines(722      text.split(b'\n' if isinstance(text, bytes) else u'\n'),723      message,724      allow_unknown_extension,725      allow_field_number,726      descriptor_pool=descriptor_pool,727      allow_unknown_field=allow_unknown_field)728 729 730def ParseLines(lines,731               message,732               allow_unknown_extension=False,733               allow_field_number=False,734               descriptor_pool=None,735               allow_unknown_field=False):736  """Parses a text representation of a protocol message into a message.737 738  See Parse() for caveats.739 740  Args:741    lines: An iterable of lines of a message's text representation.742    message: A protocol buffer message to merge into.743    allow_unknown_extension: if True, skip over missing extensions and keep744      parsing745    allow_field_number: if True, both field number and field name are allowed.746    descriptor_pool: A DescriptorPool used to resolve Any types.747    allow_unknown_field: if True, skip over unknown field and keep748      parsing. Avoid to use this option if possible. It may hide some749      errors (e.g. spelling error on field name)750 751  Returns:752    The same message passed as argument.753 754  Raises:755    ParseError: On text parsing problems.756  """757  parser = _Parser(allow_unknown_extension,758                   allow_field_number,759                   descriptor_pool=descriptor_pool,760                   allow_unknown_field=allow_unknown_field)761  return parser.ParseLines(lines, message)762 763 764def MergeLines(lines,765               message,766               allow_unknown_extension=False,767               allow_field_number=False,768               descriptor_pool=None,769               allow_unknown_field=False):770  """Parses a text representation of a protocol message into a message.771 772  See Merge() for more details.773 774  Args:775    lines: An iterable of lines of a message's text representation.776    message: A protocol buffer message to merge into.777    allow_unknown_extension: if True, skip over missing extensions and keep778      parsing779    allow_field_number: if True, both field number and field name are allowed.780    descriptor_pool: A DescriptorPool used to resolve Any types.781    allow_unknown_field: if True, skip over unknown field and keep782      parsing. Avoid to use this option if possible. It may hide some783      errors (e.g. spelling error on field name)784 785  Returns:786    The same message passed as argument.787 788  Raises:789    ParseError: On text parsing problems.790  """791  parser = _Parser(allow_unknown_extension,792                   allow_field_number,793                   descriptor_pool=descriptor_pool,794                   allow_unknown_field=allow_unknown_field)795  return parser.MergeLines(lines, message)796 797 798class _Parser(object):799  """Text format parser for protocol message."""800 801  def __init__(self,802               allow_unknown_extension=False,803               allow_field_number=False,804               descriptor_pool=None,805               allow_unknown_field=False):806    self.allow_unknown_extension = allow_unknown_extension807    self.allow_field_number = allow_field_number808    self.descriptor_pool = descriptor_pool809    self.allow_unknown_field = allow_unknown_field810 811  def ParseLines(self, lines, message):812    """Parses a text representation of a protocol message into a message."""813    self._allow_multiple_scalars = False814    self._ParseOrMerge(lines, message)815    return message816 817  def MergeLines(self, lines, message):818    """Merges a text representation of a protocol message into a message."""819    self._allow_multiple_scalars = True820    self._ParseOrMerge(lines, message)821    return message822 823  def _ParseOrMerge(self, lines, message):824    """Converts a text representation of a protocol message into a message.825 826    Args:827      lines: Lines of a message's text representation.828      message: A protocol buffer message to merge into.829 830    Raises:831      ParseError: On text parsing problems.832    """833    # Tokenize expects native str lines.834    try:835      str_lines = (836          line if isinstance(line, str) else line.decode('utf-8')837          for line in lines)838      tokenizer = Tokenizer(str_lines)839    except UnicodeDecodeError as e:840      raise ParseError from e841    if message:842      self.root_type = message.DESCRIPTOR.full_name843    while not tokenizer.AtEnd():844      self._MergeField(tokenizer, message)845 846  def _MergeField(self, tokenizer, message):847    """Merges a single protocol message field into a message.848 849    Args:850      tokenizer: A tokenizer to parse the field name and values.851      message: A protocol message to record the data.852 853    Raises:854      ParseError: In case of text parsing problems.855    """856    message_descriptor = message.DESCRIPTOR857    if (message_descriptor.full_name == _ANY_FULL_TYPE_NAME and858        tokenizer.TryConsume('[')):859      type_url_prefix, packed_type_name = self._ConsumeAnyTypeUrl(tokenizer)860      tokenizer.Consume(']')861      tokenizer.TryConsume(':')862      self._DetectSilentMarker(tokenizer, message_descriptor.full_name,863                               type_url_prefix + '/' + packed_type_name)864      if tokenizer.TryConsume('<'):865        expanded_any_end_token = '>'866      else:867        tokenizer.Consume('{')868        expanded_any_end_token = '}'869      expanded_any_sub_message = _BuildMessageFromTypeName(packed_type_name,870                                                           self.descriptor_pool)871      # Direct comparison with None is used instead of implicit bool conversion872      # to avoid false positives with falsy initial values, e.g. for873      # google.protobuf.ListValue.874      if expanded_any_sub_message is None:875        raise ParseError('Type %s not found in descriptor pool' %876                         packed_type_name)877      while not tokenizer.TryConsume(expanded_any_end_token):878        if tokenizer.AtEnd():879          raise tokenizer.ParseErrorPreviousToken('Expected "%s".' %880                                                  (expanded_any_end_token,))881        self._MergeField(tokenizer, expanded_any_sub_message)882      deterministic = False883 884      message.Pack(expanded_any_sub_message,885                   type_url_prefix=type_url_prefix,886                   deterministic=deterministic)887      return888 889    if tokenizer.TryConsume('['):890      name = [tokenizer.ConsumeIdentifier()]891      while tokenizer.TryConsume('.'):892        name.append(tokenizer.ConsumeIdentifier())893      name = '.'.join(name)894 895      if not message_descriptor.is_extendable:896        raise tokenizer.ParseErrorPreviousToken(897            'Message type "%s" does not have extensions.' %898            message_descriptor.full_name)899      # pylint: disable=protected-access900      field = message.Extensions._FindExtensionByName(name)901      # pylint: enable=protected-access902      if not field:903        if self.allow_unknown_extension:904          field = None905        else:906          raise tokenizer.ParseErrorPreviousToken(907              'Extension "%s" not registered. '908              'Did you import the _pb2 module which defines it? '909              'If you are trying to place the extension in the MessageSet '910              'field of another message that is in an Any or MessageSet field, '911              'that message\'s _pb2 module must be imported as well' % name)912      elif message_descriptor != field.containing_type:913        raise tokenizer.ParseErrorPreviousToken(914            'Extension "%s" does not extend message type "%s".' %915            (name, message_descriptor.full_name))916 917      tokenizer.Consume(']')918 919    else:920      name = tokenizer.ConsumeIdentifierOrNumber()921      if self.allow_field_number and name.isdigit():922        number = ParseInteger(name, True, True)923        field = message_descriptor.fields_by_number.get(number, None)924        if not field and message_descriptor.is_extendable:925          field = message.Extensions._FindExtensionByNumber(number)926      else:927        field = message_descriptor.fields_by_name.get(name, None)928 929        # Group names are expected to be capitalized as they appear in the930        # .proto file, which actually matches their type names, not their field931        # names.932        if not field:933          field = message_descriptor.fields_by_name.get(name.lower(), None)934          if field and field.type != descriptor.FieldDescriptor.TYPE_GROUP:935            field = None936 937        if (field and field.type == descriptor.FieldDescriptor.TYPE_GROUP and938            field.message_type.name != name):939          field = None940 941      if not field and not self.allow_unknown_field:942        raise tokenizer.ParseErrorPreviousToken(943            'Message type "%s" has no field named "%s".' %944            (message_descriptor.full_name, name))945 946    if field:947      if not self._allow_multiple_scalars and field.containing_oneof:948        # Check if there's a different field set in this oneof.949        # Note that we ignore the case if the same field was set before, and we950        # apply _allow_multiple_scalars to non-scalar fields as well.951        which_oneof = message.WhichOneof(field.containing_oneof.name)952        if which_oneof is not None and which_oneof != field.name:953          raise tokenizer.ParseErrorPreviousToken(954              'Field "%s" is specified along with field "%s", another member '955              'of oneof "%s" for message type "%s".' %956              (field.name, which_oneof, field.containing_oneof.name,957               message_descriptor.full_name))958 959      if field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_MESSAGE:960        tokenizer.TryConsume(':')961        self._DetectSilentMarker(tokenizer, message_descriptor.full_name,962                                 field.full_name)963        merger = self._MergeMessageField964      else:965        tokenizer.Consume(':')966        self._DetectSilentMarker(tokenizer, message_descriptor.full_name,967                                 field.full_name)968        merger = self._MergeScalarField969 970      if (field.label == descriptor.FieldDescriptor.LABEL_REPEATED and971          tokenizer.TryConsume('[')):972        # Short repeated format, e.g. "foo: [1, 2, 3]"973        if not tokenizer.TryConsume(']'):974          while True:975            merger(tokenizer, message, field)976            if tokenizer.TryConsume(']'):977              break978            tokenizer.Consume(',')979 980      else:981        merger(tokenizer, message, field)982 983    else:  # Proto field is unknown.984      assert (self.allow_unknown_extension or self.allow_unknown_field)985      self._SkipFieldContents(tokenizer, name, message_descriptor.full_name)986 987    # For historical reasons, fields may optionally be separated by commas or988    # semicolons.989    if not tokenizer.TryConsume(','):990      tokenizer.TryConsume(';')991 992  def _LogSilentMarker(self, immediate_message_type, field_name):993    pass994 995  def _DetectSilentMarker(self, tokenizer, immediate_message_type, field_name):996    if tokenizer.contains_silent_marker_before_current_token:997      self._LogSilentMarker(immediate_message_type, field_name)998 999  def _ConsumeAnyTypeUrl(self, tokenizer):1000    """Consumes a google.protobuf.Any type URL and returns the type name."""1001    # Consume "type.googleapis.com/".1002    prefix = [tokenizer.ConsumeIdentifier()]1003    tokenizer.Consume('.')1004    prefix.append(tokenizer.ConsumeIdentifier())1005    tokenizer.Consume('.')1006    prefix.append(tokenizer.ConsumeIdentifier())1007    tokenizer.Consume('/')1008    # Consume the fully-qualified type name.1009    name = [tokenizer.ConsumeIdentifier()]1010    while tokenizer.TryConsume('.'):1011      name.append(tokenizer.ConsumeIdentifier())1012    return '.'.join(prefix), '.'.join(name)1013 1014  def _MergeMessageField(self, tokenizer, message, field):1015    """Merges a single scalar field into a message.1016 1017    Args:1018      tokenizer: A tokenizer to parse the field value.1019      message: The message of which field is a member.1020      field: The descriptor of the field to be merged.1021 1022    Raises:1023      ParseError: In case of text parsing problems.1024    """1025    is_map_entry = _IsMapEntry(field)1026 1027    if tokenizer.TryConsume('<'):1028      end_token = '>'1029    else:1030      tokenizer.Consume('{')1031      end_token = '}'1032 1033    if field.label == descriptor.FieldDescriptor.LABEL_REPEATED:1034      if field.is_extension:1035        sub_message = message.Extensions[field].add()1036      elif is_map_entry:1037        sub_message = getattr(message, field.name).GetEntryClass()()1038      else:1039        sub_message = getattr(message, field.name).add()1040    else:1041      if field.is_extension:1042        if (not self._allow_multiple_scalars and1043            message.HasExtension(field)):1044          raise tokenizer.ParseErrorPreviousToken(1045              'Message type "%s" should not have multiple "%s" extensions.' %1046              (message.DESCRIPTOR.full_name, field.full_name))1047        sub_message = message.Extensions[field]1048      else:1049        # Also apply _allow_multiple_scalars to message field.1050        # TODO: Change to _allow_singular_overwrites.1051        if (not self._allow_multiple_scalars and1052            message.HasField(field.name)):1053          raise tokenizer.ParseErrorPreviousToken(1054              'Message type "%s" should not have multiple "%s" fields.' %1055              (message.DESCRIPTOR.full_name, field.name))1056        sub_message = getattr(message, field.name)1057      sub_message.SetInParent()1058 1059    while not tokenizer.TryConsume(end_token):1060      if tokenizer.AtEnd():1061        raise tokenizer.ParseErrorPreviousToken('Expected "%s".' % (end_token,))1062      self._MergeField(tokenizer, sub_message)1063 1064    if is_map_entry:1065      value_cpptype = field.message_type.fields_by_name['value'].cpp_type1066      if value_cpptype == descriptor.FieldDescriptor.CPPTYPE_MESSAGE:1067        value = getattr(message, field.name)[sub_message.key]1068        value.CopyFrom(sub_message.value)1069      else:1070        getattr(message, field.name)[sub_message.key] = sub_message.value1071 1072  def _MergeScalarField(self, tokenizer, message, field):1073    """Merges a single scalar field into a message.1074 1075    Args:1076      tokenizer: A tokenizer to parse the field value.1077      message: A protocol message to record the data.1078      field: The descriptor of the field to be merged.1079 1080    Raises:1081      ParseError: In case of text parsing problems.1082      RuntimeError: On runtime errors.1083    """1084    _ = self.allow_unknown_extension1085    value = None1086 1087    if field.type in (descriptor.FieldDescriptor.TYPE_INT32,1088                      descriptor.FieldDescriptor.TYPE_SINT32,1089                      descriptor.FieldDescriptor.TYPE_SFIXED32):1090      value = _ConsumeInt32(tokenizer)1091    elif field.type in (descriptor.FieldDescriptor.TYPE_INT64,1092                        descriptor.FieldDescriptor.TYPE_SINT64,1093                        descriptor.FieldDescriptor.TYPE_SFIXED64):1094      value = _ConsumeInt64(tokenizer)1095    elif field.type in (descriptor.FieldDescriptor.TYPE_UINT32,1096                        descriptor.FieldDescriptor.TYPE_FIXED32):1097      value = _ConsumeUint32(tokenizer)1098    elif field.type in (descriptor.FieldDescriptor.TYPE_UINT64,1099                        descriptor.FieldDescriptor.TYPE_FIXED64):1100      value = _ConsumeUint64(tokenizer)1101    elif field.type in (descriptor.FieldDescriptor.TYPE_FLOAT,1102                        descriptor.FieldDescriptor.TYPE_DOUBLE):1103      value = tokenizer.ConsumeFloat()1104    elif field.type == descriptor.FieldDescriptor.TYPE_BOOL:1105      value = tokenizer.ConsumeBool()1106    elif field.type == descriptor.FieldDescriptor.TYPE_STRING:1107      value = tokenizer.ConsumeString()1108    elif field.type == descriptor.FieldDescriptor.TYPE_BYTES:1109      value = tokenizer.ConsumeByteString()1110    elif field.type == descriptor.FieldDescriptor.TYPE_ENUM:1111      value = tokenizer.ConsumeEnum(field)1112    else:1113      raise RuntimeError('Unknown field type %d' % field.type)1114 1115    if field.label == descriptor.FieldDescriptor.LABEL_REPEATED:1116      if field.is_extension:1117        message.Extensions[field].append(value)1118      else:1119        getattr(message, field.name).append(value)1120    else:1121      if field.is_extension:1122        if (not self._allow_multiple_scalars and1123            field.has_presence and1124            message.HasExtension(field)):1125          raise tokenizer.ParseErrorPreviousToken(1126              'Message type "%s" should not have multiple "%s" extensions.' %1127              (message.DESCRIPTOR.full_name, field.full_name))1128        else:1129          message.Extensions[field] = value1130      else:1131        duplicate_error = False1132        if not self._allow_multiple_scalars:1133          if field.has_presence:1134            duplicate_error = message.HasField(field.name)1135          else:1136            # For field that doesn't represent presence, try best effort to1137            # check multiple scalars by compare to default values.1138            duplicate_error = bool(getattr(message, field.name))1139 1140        if duplicate_error:1141          raise tokenizer.ParseErrorPreviousToken(1142              'Message type "%s" should not have multiple "%s" fields.' %1143              (message.DESCRIPTOR.full_name, field.name))1144        else:1145          setattr(message, field.name, value)1146 1147  def _SkipFieldContents(self, tokenizer, field_name, immediate_message_type):1148    """Skips over contents (value or message) of a field.1149 1150    Args:1151      tokenizer: A tokenizer to parse the field name and values.1152      field_name: The field name currently being parsed.1153      immediate_message_type: The type of the message immediately containing1154        the silent marker.1155    """1156    # Try to guess the type of this field.1157    # If this field is not a message, there should be a ":" between the1158    # field name and the field value and also the field value should not1159    # start with "{" or "<" which indicates the beginning of a message body.1160    # If there is no ":" or there is a "{" or "<" after ":", this field has1161    # to be a message or the input is ill-formed.1162    if tokenizer.TryConsume(1163        ':') and not tokenizer.LookingAt('{') and not tokenizer.LookingAt('<'):1164      self._DetectSilentMarker(tokenizer, immediate_message_type, field_name)1165      if tokenizer.LookingAt('['):1166        self._SkipRepeatedFieldValue(tokenizer)1167      else:1168        self._SkipFieldValue(tokenizer)1169    else:1170      self._DetectSilentMarker(tokenizer, immediate_message_type, field_name)1171      self._SkipFieldMessage(tokenizer, immediate_message_type)1172 1173  def _SkipField(self, tokenizer, immediate_message_type):1174    """Skips over a complete field (name and value/message).1175 1176    Args:1177      tokenizer: A tokenizer to parse the field name and values.1178      immediate_message_type: The type of the message immediately containing1179        the silent marker.1180    """1181    field_name = ''1182    if tokenizer.TryConsume('['):1183      # Consume extension or google.protobuf.Any type URL1184      field_name += '[' + tokenizer.ConsumeIdentifier()1185      num_identifiers = 11186      while tokenizer.TryConsume('.'):1187        field_name += '.' + tokenizer.ConsumeIdentifier()1188        num_identifiers += 11189      # This is possibly a type URL for an Any message.1190      if num_identifiers == 3 and tokenizer.TryConsume('/'):1191        field_name += '/' + tokenizer.ConsumeIdentifier()1192        while tokenizer.TryConsume('.'):1193          field_name += '.' + tokenizer.ConsumeIdentifier()1194      tokenizer.Consume(']')1195      field_name += ']'1196    else:1197      field_name += tokenizer.ConsumeIdentifierOrNumber()1198 1199    self._SkipFieldContents(tokenizer, field_name, immediate_message_type)1200 

Showing the first 1,200 of 1835 lines. Download the file for the rest.

codekingpro/portable-devtools · Team Ai