1fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# Protocol Buffers - Google's data interchange format
2fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# Copyright 2008 Google Inc.  All rights reserved.
3fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# http://code.google.com/p/protobuf/
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
31fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# This code is meant to work on Python 2.4 and above only.
32fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#
33fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# TODO(robinson): Helpers for verbose, common checks like seeing if a
34fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# descriptor's cpp_type is CPPTYPE_MESSAGE.
35fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
36fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville"""Contains a metaclass and helper functions used to create
37fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleprotocol message classes from Descriptor objects at runtime.
38fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
39fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleRecall that a metaclass is the "type" of a class.
40fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville(A class is to a metaclass what an instance is to a class.)
41fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
42fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleIn this case, we use the GeneratedProtocolMessageType metaclass
43fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleto inject all the useful functionality into the classes
44fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleoutput by the protocol compiler at compile-time.
45fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
46fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleThe upshot of all this is that the real implementation
47fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilledetails for ALL pure-Python protocol buffers are *here in
48fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillethis file*.
49fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville"""
50fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
51fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville__author__ = 'robinson@google.com (Will Robinson)'
52fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
53d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savilletry:
54d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  from cStringIO import StringIO
55d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savilleexcept ImportError:
56d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  from StringIO import StringIO
57d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savilleimport struct
58fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleimport weakref
59d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
60fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# We use "as" to avoid name collisions with variables.
61fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillefrom google.protobuf.internal import containers
62fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillefrom google.protobuf.internal import decoder
63fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillefrom google.protobuf.internal import encoder
64fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillefrom google.protobuf.internal import message_listener as message_listener_mod
65fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillefrom google.protobuf.internal import type_checkers
66fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillefrom google.protobuf.internal import wire_format
67fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillefrom google.protobuf import descriptor as descriptor_mod
68fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillefrom google.protobuf import message as message_mod
69fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillefrom google.protobuf import text_format
70fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
71fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville_FieldDescriptor = descriptor_mod.FieldDescriptor
72fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
73fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
74fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleclass GeneratedProtocolMessageType(type):
75fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
76fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  """Metaclass for protocol message classes created at runtime from Descriptors.
77fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
78fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  We add implementations for all methods described in the Message class.  We
79fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  also create properties to allow getting/setting all fields in the protocol
80fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  message.  Finally, we create slots to prevent users from accidentally
81fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  "setting" nonexistent fields in the protocol message, which then wouldn't get
82fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  serialized / deserialized properly.
83fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
84fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  The protocol compiler currently uses this metaclass to create protocol
85fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  message classes at runtime.  Clients can also manually create their own
86fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  classes at runtime, as in this example:
87fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
88fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  mydescriptor = Descriptor(.....)
89fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  class MyProtoClass(Message):
90fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    __metaclass__ = GeneratedProtocolMessageType
91fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    DESCRIPTOR = mydescriptor
92fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  myproto_instance = MyProtoClass()
93fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  myproto.foo_field = 23
94fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ...
95fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  """
96fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
97fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  # Must be consistent with the protocol-compiler code in
98fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  # proto2/compiler/internal/generator.*.
99fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  _DESCRIPTOR_KEY = 'DESCRIPTOR'
100fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
101fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  def __new__(cls, name, bases, dictionary):
102fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    """Custom allocation for runtime-generated class types.
103fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
104fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    We override __new__ because this is apparently the only place
105fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    where we can meaningfully set __slots__ on the class we're creating(?).
106fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    (The interplay between metaclasses and slots is not very well-documented).
107fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
108fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    Args:
109fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      name: Name of the class (ignored, but required by the
110fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        metaclass protocol).
111fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      bases: Base classes of the class we're constructing.
112fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        (Should be message.Message).  We ignore this field, but
113fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        it's required by the metaclass protocol
114fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      dictionary: The class dictionary of the class we're
115fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        constructing.  dictionary[_DESCRIPTOR_KEY] must contain
116fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        a Descriptor object describing this protocol message
117fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        type.
118fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
119fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    Returns:
120fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      Newly-allocated class.
121fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    """
122fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    descriptor = dictionary[GeneratedProtocolMessageType._DESCRIPTOR_KEY]
123fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    _AddSlots(descriptor, dictionary)
124fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    _AddClassAttributesForNestedExtensions(descriptor, dictionary)
125fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    superclass = super(GeneratedProtocolMessageType, cls)
126fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    return superclass.__new__(cls, name, bases, dictionary)
127fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
128fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  def __init__(cls, name, bases, dictionary):
129fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    """Here we perform the majority of our work on the class.
130fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    We add enum getters, an __init__ method, implementations
131fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    of all Message methods, and properties for all fields
132fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    in the protocol type.
133fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
134fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    Args:
135fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      name: Name of the class (ignored, but required by the
136fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        metaclass protocol).
137fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      bases: Base classes of the class we're constructing.
138fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        (Should be message.Message).  We ignore this field, but
139fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        it's required by the metaclass protocol
140fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      dictionary: The class dictionary of the class we're
141fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        constructing.  dictionary[_DESCRIPTOR_KEY] must contain
142fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        a Descriptor object describing this protocol message
143fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        type.
144fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    """
145fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    descriptor = dictionary[GeneratedProtocolMessageType._DESCRIPTOR_KEY]
146d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
147d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    cls._decoders_by_tag = {}
148d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    cls._extensions_by_name = {}
149d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    cls._extensions_by_number = {}
150d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    if (descriptor.has_options and
151d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        descriptor.GetOptions().message_set_wire_format):
152d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      cls._decoders_by_tag[decoder.MESSAGE_SET_ITEM_TAG] = (
153d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          decoder.MessageSetItemDecoder(cls._extensions_by_number))
154d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
155fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    # We act as a "friend" class of the descriptor, setting
156fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    # its _concrete_class attribute the first time we use a
157fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    # given descriptor to initialize a concrete protocol message
158d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    # class.  We also attach stuff to each FieldDescriptor for quick
159d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    # lookup later on.
160fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    concrete_class_attr_name = '_concrete_class'
161fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    if not hasattr(descriptor, concrete_class_attr_name):
162fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      setattr(descriptor, concrete_class_attr_name, cls)
163d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      for field in descriptor.fields:
164d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        _AttachFieldHelpers(cls, field)
165d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
166fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    _AddEnumValues(descriptor, cls)
167fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    _AddInitMethod(descriptor, cls)
168fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    _AddPropertiesForFields(descriptor, cls)
169fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    _AddPropertiesForExtensions(descriptor, cls)
170fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    _AddStaticMethods(cls)
171fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    _AddMessageMethods(descriptor, cls)
172fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    _AddPrivateHelperMethods(cls)
173fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    superclass = super(GeneratedProtocolMessageType, cls)
174fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    superclass.__init__(name, bases, dictionary)
175fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
176fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
177fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# Stateless helpers for GeneratedProtocolMessageType below.
178fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# Outside clients should not access these directly.
179fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#
180fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# I opted not to make any of these methods on the metaclass, to make it more
181fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# clear that I'm not really using any state there and to keep clients from
182fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# thinking that they have direct access to these construction helpers.
183fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
184fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
185fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilledef _PropertyName(proto_field_name):
186fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  """Returns the name of the public property attribute which
187fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  clients can use to get and (in some cases) set the value
188fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  of a protocol message field.
189fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
190fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  Args:
191fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    proto_field_name: The protocol message field name, exactly
192fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      as it appears (or would appear) in a .proto file.
193fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  """
194fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  # TODO(robinson): Escape Python keywords (e.g., yield), and test this support.
195fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  # nnorwitz makes my day by writing:
196fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  # """
197fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  # FYI.  See the keyword module in the stdlib. This could be as simple as:
198fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  #
199fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  # if keyword.iskeyword(proto_field_name):
200fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  #   return proto_field_name + "_"
201fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  # return proto_field_name
202fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  # """
203d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  # Kenton says:  The above is a BAD IDEA.  People rely on being able to use
204d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  #   getattr() and setattr() to reflectively manipulate field values.  If we
205d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  #   rename the properties, then every such user has to also make sure to apply
206d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  #   the same transformation.  Note that currently if you name a field "yield",
207d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  #   you can still access it just fine using getattr/setattr -- it's not even
208d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  #   that cumbersome to do so.
209d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  # TODO(kenton):  Remove this method entirely if/when everyone agrees with my
210d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  #   position.
211fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  return proto_field_name
212fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
213fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
214d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savilledef _VerifyExtensionHandle(message, extension_handle):
215d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  """Verify that the given extension handle is valid."""
216fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
217d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  if not isinstance(extension_handle, _FieldDescriptor):
218d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    raise KeyError('HasExtension() expects an extension handle, got: %s' %
219d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville                   extension_handle)
220fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
221d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  if not extension_handle.is_extension:
222d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    raise KeyError('"%s" is not an extension.' % extension_handle.full_name)
223fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
224d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  if extension_handle.containing_type is not message.DESCRIPTOR:
225d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    raise KeyError('Extension "%s" extends message type "%s", but this '
226d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville                   'message is of type "%s".' %
227d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville                   (extension_handle.full_name,
228d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville                    extension_handle.containing_type.full_name,
229d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville                    message.DESCRIPTOR.full_name))
230fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
231fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
232fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilledef _AddSlots(message_descriptor, dictionary):
233fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  """Adds a __slots__ entry to dictionary, containing the names of all valid
234fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  attributes for this message type.
235fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
236fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  Args:
237fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    message_descriptor: A Descriptor instance describing this message type.
238fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    dictionary: Class dictionary to which we'll add a '__slots__' entry.
239fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  """
240d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  dictionary['__slots__'] = ['_cached_byte_size',
241d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville                             '_cached_byte_size_dirty',
242d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville                             '_fields',
243d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville                             '_is_present_in_parent',
244d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville                             '_listener',
245d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville                             '_listener_for_children',
246d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville                             '__weakref__']
247d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
248d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
249d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savilledef _IsMessageSetExtension(field):
250d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  return (field.is_extension and
251d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          field.containing_type.has_options and
252d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          field.containing_type.GetOptions().message_set_wire_format and
253d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          field.type == _FieldDescriptor.TYPE_MESSAGE and
254d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          field.message_type == field.extension_scope and
255d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          field.label == _FieldDescriptor.LABEL_OPTIONAL)
256d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
257d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
258d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savilledef _AttachFieldHelpers(cls, field_descriptor):
259d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  is_repeated = (field_descriptor.label == _FieldDescriptor.LABEL_REPEATED)
260d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  is_packed = (field_descriptor.has_options and
261d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville               field_descriptor.GetOptions().packed)
262d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
263d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  if _IsMessageSetExtension(field_descriptor):
264d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    field_encoder = encoder.MessageSetItemEncoder(field_descriptor.number)
265d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    sizer = encoder.MessageSetItemSizer(field_descriptor.number)
266d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  else:
267d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    field_encoder = type_checkers.TYPE_TO_ENCODER[field_descriptor.type](
268d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        field_descriptor.number, is_repeated, is_packed)
269d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    sizer = type_checkers.TYPE_TO_SIZER[field_descriptor.type](
270d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        field_descriptor.number, is_repeated, is_packed)
271d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
272d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  field_descriptor._encoder = field_encoder
273d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  field_descriptor._sizer = sizer
274d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  field_descriptor._default_constructor = _DefaultValueConstructorForField(
275d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      field_descriptor)
276d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
277d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  def AddDecoder(wiretype, is_packed):
278d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    tag_bytes = encoder.TagBytes(field_descriptor.number, wiretype)
279d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    cls._decoders_by_tag[tag_bytes] = (
280d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        type_checkers.TYPE_TO_DECODER[field_descriptor.type](
281d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville            field_descriptor.number, is_repeated, is_packed,
282d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville            field_descriptor, field_descriptor._default_constructor))
283d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
284d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  AddDecoder(type_checkers.FIELD_TYPE_TO_WIRE_TYPE[field_descriptor.type],
285d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville             False)
286d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
287d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  if is_repeated and wire_format.IsTypePackable(field_descriptor.type):
288d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    # To support wire compatibility of adding packed = true, add a decoder for
289d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    # packed values regardless of the field's options.
290d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    AddDecoder(wire_format.WIRETYPE_LENGTH_DELIMITED, True)
291fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
292fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
293fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilledef _AddClassAttributesForNestedExtensions(descriptor, dictionary):
294fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  extension_dict = descriptor.extensions_by_name
295fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  for extension_name, extension_field in extension_dict.iteritems():
296fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    assert extension_name not in dictionary
297fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    dictionary[extension_name] = extension_field
298fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
299fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
300fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilledef _AddEnumValues(descriptor, cls):
301fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  """Sets class-level attributes for all enum fields defined in this message.
302fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
303fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  Args:
304fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    descriptor: Descriptor object for this message type.
305fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    cls: Class we're constructing for this message type.
306fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  """
307fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  for enum_type in descriptor.enum_types:
308fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    for enum_value in enum_type.values:
309fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      setattr(cls, enum_value.name, enum_value.number)
310fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
311fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
312d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savilledef _DefaultValueConstructorForField(field):
313d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  """Returns a function which returns a default value for a field.
314fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
315fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  Args:
316d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    field: FieldDescriptor object for this field.
317d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
318d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  The returned function has one argument:
319fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    message: Message instance containing this field, or a weakref proxy
320fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      of same.
321fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
322d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  That function in turn returns a default value for this field.  The default
323d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    value may refer back to |message| via a weak reference.
324fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  """
325d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
326fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  if field.label == _FieldDescriptor.LABEL_REPEATED:
327fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    if field.default_value != []:
328fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      raise ValueError('Repeated field default value not empty list: %s' % (
329fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville          field.default_value))
330fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
331fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      # We can't look at _concrete_class yet since it might not have
332fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      # been set.  (Depends on order in which we initialize the classes).
333d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      message_type = field.message_type
334d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      def MakeRepeatedMessageDefault(message):
335d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        return containers.RepeatedCompositeFieldContainer(
336d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville            message._listener_for_children, field.message_type)
337d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      return MakeRepeatedMessageDefault
338fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    else:
339d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      type_checker = type_checkers.GetTypeChecker(field.cpp_type, field.type)
340d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      def MakeRepeatedScalarDefault(message):
341d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        return containers.RepeatedScalarFieldContainer(
342d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville            message._listener_for_children, type_checker)
343d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      return MakeRepeatedScalarDefault
344fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
345fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
346d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    # _concrete_class may not yet be initialized.
347d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    message_type = field.message_type
348d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    def MakeSubMessageDefault(message):
349d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      result = message_type._concrete_class()
350d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      result._SetListener(message._listener_for_children)
351d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      return result
352d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    return MakeSubMessageDefault
353fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
354d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  def MakeScalarDefault(message):
355d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    return field.default_value
356d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  return MakeScalarDefault
357fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
358fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
359fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilledef _AddInitMethod(message_descriptor, cls):
360fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  """Adds an __init__ method to cls."""
361fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  fields = message_descriptor.fields
362fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  def init(self, **kwargs):
363fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    self._cached_byte_size = 0
364fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    self._cached_byte_size_dirty = False
365d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    self._fields = {}
366d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    self._is_present_in_parent = False
367fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    self._listener = message_listener_mod.NullMessageListener()
368d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    self._listener_for_children = _Listener(self)
369fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    for field_name, field_value in kwargs.iteritems():
370fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      field = _GetFieldByName(message_descriptor, field_name)
371d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      if field is None:
372d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        raise TypeError("%s() got an unexpected keyword argument '%s'" %
373d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville                        (message_descriptor.name, field_name))
374d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      if field.label == _FieldDescriptor.LABEL_REPEATED:
375d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        copy = field._default_constructor(self)
376d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:  # Composite
377d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          for val in field_value:
378d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville            copy.add().MergeFrom(val)
379d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        else:  # Scalar
380d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          copy.extend(field_value)
381d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        self._fields[field] = copy
382d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      elif field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
383d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        copy = field._default_constructor(self)
384d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        copy.MergeFrom(field_value)
385d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        self._fields[field] = copy
386d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      else:
387d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        self._fields[field] = field_value
388fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
389fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  init.__module__ = None
390fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  init.__doc__ = None
391fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  cls.__init__ = init
392fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
393fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
394fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilledef _GetFieldByName(message_descriptor, field_name):
395fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  """Returns a field descriptor by field name.
396fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
397fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  Args:
398fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    message_descriptor: A Descriptor describing all fields in message.
399fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    field_name: The name of the field to retrieve.
400fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  Returns:
401fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    The field descriptor associated with the field name.
402fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  """
403fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  try:
404fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    return message_descriptor.fields_by_name[field_name]
405fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  except KeyError:
406fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    raise ValueError('Protocol message has no "%s" field.' % field_name)
407fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
408fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
409fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilledef _AddPropertiesForFields(descriptor, cls):
410fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  """Adds properties for all fields in this protocol message type."""
411fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  for field in descriptor.fields:
412fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    _AddPropertiesForField(field, cls)
413fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
414d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  if descriptor.is_extendable:
415d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    # _ExtensionDict is just an adaptor with no state so we allocate a new one
416d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    # every time it is accessed.
417d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    cls.Extensions = property(lambda self: _ExtensionDict(self))
418d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
419fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
420fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilledef _AddPropertiesForField(field, cls):
421fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  """Adds a public property for a protocol message field.
422fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  Clients can use this property to get and (in the case
423fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  of non-repeated scalar fields) directly set the value
424fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  of a protocol message field.
425fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
426fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  Args:
427fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    field: A FieldDescriptor for this field.
428fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    cls: The class we're constructing.
429fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  """
430fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  # Catch it if we add other types that we should
431fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  # handle specially here.
432fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  assert _FieldDescriptor.MAX_CPPTYPE == 10
433fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
434fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  constant_name = field.name.upper() + "_FIELD_NUMBER"
435fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  setattr(cls, constant_name, field.number)
436fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
437fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  if field.label == _FieldDescriptor.LABEL_REPEATED:
438fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    _AddPropertiesForRepeatedField(field, cls)
439fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  elif field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
440fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    _AddPropertiesForNonRepeatedCompositeField(field, cls)
441fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  else:
442fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    _AddPropertiesForNonRepeatedScalarField(field, cls)
443fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
444fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
445fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilledef _AddPropertiesForRepeatedField(field, cls):
446fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  """Adds a public property for a "repeated" protocol message field.  Clients
447fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  can use this property to get the value of the field, which will be either a
448fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  _RepeatedScalarFieldContainer or _RepeatedCompositeFieldContainer (see
449fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  below).
450fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
451fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  Note that when clients add values to these containers, we perform
452fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  type-checking in the case of repeated scalar fields, and we also set any
453fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  necessary "has" bits as a side-effect.
454fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
455fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  Args:
456fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    field: A FieldDescriptor for this field.
457fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    cls: The class we're constructing.
458fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  """
459fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  proto_field_name = field.name
460fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  property_name = _PropertyName(proto_field_name)
461fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
462fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  def getter(self):
463d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    field_value = self._fields.get(field)
464d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    if field_value is None:
465d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      # Construct a new object to represent this field.
466d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      field_value = field._default_constructor(self)
467d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
468d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      # Atomically check if another thread has preempted us and, if not, swap
469d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      # in the new object we just created.  If someone has preempted us, we
470d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      # take that object and discard ours.
471d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      # WARNING:  We are relying on setdefault() being atomic.  This is true
472d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      #   in CPython but we haven't investigated others.  This warning appears
473d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      #   in several other locations in this file.
474d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      field_value = self._fields.setdefault(field, field_value)
475d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    return field_value
476fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  getter.__module__ = None
477fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  getter.__doc__ = 'Getter for %s.' % proto_field_name
478fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
479fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  # We define a setter just so we can throw an exception with a more
480fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  # helpful error message.
481fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  def setter(self, new_value):
482fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    raise AttributeError('Assignment not allowed to repeated field '
483fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville                         '"%s" in protocol message object.' % proto_field_name)
484fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
485fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  doc = 'Magic attribute generated for "%s" proto field.' % proto_field_name
486fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  setattr(cls, property_name, property(getter, setter, doc=doc))
487fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
488fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
489fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilledef _AddPropertiesForNonRepeatedScalarField(field, cls):
490fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  """Adds a public property for a nonrepeated, scalar protocol message field.
491fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  Clients can use this property to get and directly set the value of the field.
492fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  Note that when the client sets the value of a field by using this property,
493fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  all necessary "has" bits are set as a side-effect, and we also perform
494fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  type-checking.
495fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
496fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  Args:
497fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    field: A FieldDescriptor for this field.
498fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    cls: The class we're constructing.
499fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  """
500fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  proto_field_name = field.name
501fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  property_name = _PropertyName(proto_field_name)
502fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  type_checker = type_checkers.GetTypeChecker(field.cpp_type, field.type)
503d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  default_value = field.default_value
504fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
505fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  def getter(self):
506d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    return self._fields.get(field, default_value)
507fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  getter.__module__ = None
508fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  getter.__doc__ = 'Getter for %s.' % proto_field_name
509fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  def setter(self, new_value):
510fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    type_checker.CheckValue(new_value)
511d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    self._fields[field] = new_value
512d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    # Check _cached_byte_size_dirty inline to improve performance, since scalar
513d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    # setters are called frequently.
514d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    if not self._cached_byte_size_dirty:
515d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      self._Modified()
516fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  setter.__module__ = None
517fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  setter.__doc__ = 'Setter for %s.' % proto_field_name
518fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
519fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  # Add a property to encapsulate the getter/setter.
520fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  doc = 'Magic attribute generated for "%s" proto field.' % proto_field_name
521fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  setattr(cls, property_name, property(getter, setter, doc=doc))
522fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
523fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
524fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilledef _AddPropertiesForNonRepeatedCompositeField(field, cls):
525fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  """Adds a public property for a nonrepeated, composite protocol message field.
526fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  A composite field is a "group" or "message" field.
527fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
528fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  Clients can use this property to get the value of the field, but cannot
529fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  assign to the property directly.
530fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
531fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  Args:
532fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    field: A FieldDescriptor for this field.
533fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    cls: The class we're constructing.
534fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  """
535fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  # TODO(robinson): Remove duplication with similar method
536fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  # for non-repeated scalars.
537fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  proto_field_name = field.name
538fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  property_name = _PropertyName(proto_field_name)
539fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  message_type = field.message_type
540fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
541fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  def getter(self):
542d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    field_value = self._fields.get(field)
543fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    if field_value is None:
544d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      # Construct a new object to represent this field.
545d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      field_value = message_type._concrete_class()
546d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      field_value._SetListener(self._listener_for_children)
547d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
548d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      # Atomically check if another thread has preempted us and, if not, swap
549d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      # in the new object we just created.  If someone has preempted us, we
550d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      # take that object and discard ours.
551d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      # WARNING:  We are relying on setdefault() being atomic.  This is true
552d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      #   in CPython but we haven't investigated others.  This warning appears
553d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      #   in several other locations in this file.
554d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      field_value = self._fields.setdefault(field, field_value)
555fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    return field_value
556fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  getter.__module__ = None
557fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  getter.__doc__ = 'Getter for %s.' % proto_field_name
558fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
559fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  # We define a setter just so we can throw an exception with a more
560fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  # helpful error message.
561fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  def setter(self, new_value):
562fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    raise AttributeError('Assignment not allowed to composite field '
563fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville                         '"%s" in protocol message object.' % proto_field_name)
564fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
565fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  # Add a property to encapsulate the getter.
566fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  doc = 'Magic attribute generated for "%s" proto field.' % proto_field_name
567fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  setattr(cls, property_name, property(getter, setter, doc=doc))
568fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
569fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
570fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilledef _AddPropertiesForExtensions(descriptor, cls):
571fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  """Adds properties for all fields in this protocol message type."""
572fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  extension_dict = descriptor.extensions_by_name
573fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  for extension_name, extension_field in extension_dict.iteritems():
574fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    constant_name = extension_name.upper() + "_FIELD_NUMBER"
575fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    setattr(cls, constant_name, extension_field.number)
576fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
577fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
578fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilledef _AddStaticMethods(cls):
579fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  # TODO(robinson): This probably needs to be thread-safe(?)
580fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  def RegisterExtension(extension_handle):
581fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    extension_handle.containing_type = cls.DESCRIPTOR
582d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    _AttachFieldHelpers(cls, extension_handle)
583d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
584d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    # Try to insert our extension, failing if an extension with the same number
585d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    # already exists.
586d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    actual_handle = cls._extensions_by_number.setdefault(
587d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        extension_handle.number, extension_handle)
588d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    if actual_handle is not extension_handle:
589d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      raise AssertionError(
590d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          'Extensions "%s" and "%s" both try to extend message type "%s" with '
591d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          'field number %d.' %
592d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          (extension_handle.full_name, actual_handle.full_name,
593d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville           cls.DESCRIPTOR.full_name, extension_handle.number))
594d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
595d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    cls._extensions_by_name[extension_handle.full_name] = extension_handle
596d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
597d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    handle = extension_handle  # avoid line wrapping
598d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    if _IsMessageSetExtension(handle):
599d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      # MessageSet extension.  Also register under type name.
600d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      cls._extensions_by_name[
601d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          extension_handle.message_type.full_name] = extension_handle
602d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
603fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  cls.RegisterExtension = staticmethod(RegisterExtension)
604fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
605fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  def FromString(s):
606fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    message = cls()
607fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    message.MergeFromString(s)
608fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    return message
609fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  cls.FromString = staticmethod(FromString)
610fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
611fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
612d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savilledef _IsPresent(item):
613d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  """Given a (FieldDescriptor, value) tuple from _fields, return true if the
614d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  value should be included in the list returned by ListFields()."""
615d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
616d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  if item[0].label == _FieldDescriptor.LABEL_REPEATED:
617d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    return bool(item[1])
618d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  elif item[0].cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
619d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    return item[1]._is_present_in_parent
620d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  else:
621d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    return True
622d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
623d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
624fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilledef _AddListFieldsMethod(message_descriptor, cls):
625fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  """Helper for _AddMessageMethods()."""
626fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
627fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  def ListFields(self):
628d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    all_fields = [item for item in self._fields.iteritems() if _IsPresent(item)]
629d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    all_fields.sort(key = lambda item: item[0].number)
630d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    return all_fields
631fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
632fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  cls.ListFields = ListFields
633fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
634d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
635d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savilledef _AddHasFieldMethod(message_descriptor, cls):
636fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  """Helper for _AddMessageMethods()."""
637d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
638d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  singular_fields = {}
639d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  for field in message_descriptor.fields:
640d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    if field.label != _FieldDescriptor.LABEL_REPEATED:
641d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      singular_fields[field.name] = field
642d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
643fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  def HasField(self, field_name):
644fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    try:
645d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      field = singular_fields[field_name]
646d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    except KeyError:
647d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      raise ValueError(
648d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          'Protocol message has no singular "%s" field.' % field_name)
649d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
650d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
651d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      value = self._fields.get(field)
652d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      return value is not None and value._is_present_in_parent
653d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    else:
654d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      return field in self._fields
655fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  cls.HasField = HasField
656fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
657fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
658d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savilledef _AddClearFieldMethod(message_descriptor, cls):
659fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  """Helper for _AddMessageMethods()."""
660fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  def ClearField(self, field_name):
661d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    try:
662d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      field = message_descriptor.fields_by_name[field_name]
663d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    except KeyError:
664d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      raise ValueError('Protocol message has no "%s" field.' % field_name)
665d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
666d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    if field in self._fields:
667d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      # Note:  If the field is a sub-message, its listener will still point
668d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      #   at us.  That's fine, because the worst than can happen is that it
669d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      #   will call _Modified() and invalidate our byte size.  Big deal.
670d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      del self._fields[field]
671d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
672d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    # Always call _Modified() -- even if nothing was changed, this is
673d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    # a mutating method, and thus calling it should cause the field to become
674d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    # present in the parent message.
675d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    self._Modified()
676d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
677fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  cls.ClearField = ClearField
678fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
679fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
680fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilledef _AddClearExtensionMethod(cls):
681fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  """Helper for _AddMessageMethods()."""
682fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  def ClearExtension(self, extension_handle):
683d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    _VerifyExtensionHandle(self, extension_handle)
684d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
685d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    # Similar to ClearField(), above.
686d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    if extension_handle in self._fields:
687d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      del self._fields[extension_handle]
688d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    self._Modified()
689fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  cls.ClearExtension = ClearExtension
690fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
691fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
692d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savilledef _AddClearMethod(message_descriptor, cls):
693fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  """Helper for _AddMessageMethods()."""
694fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  def Clear(self):
695fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    # Clear fields.
696d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    self._fields = {}
697d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    self._Modified()
698fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  cls.Clear = Clear
699fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
700fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
701fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilledef _AddHasExtensionMethod(cls):
702fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  """Helper for _AddMessageMethods()."""
703fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  def HasExtension(self, extension_handle):
704d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    _VerifyExtensionHandle(self, extension_handle)
705d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    if extension_handle.label == _FieldDescriptor.LABEL_REPEATED:
706d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      raise KeyError('"%s" is repeated.' % extension_handle.full_name)
707d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
708d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    if extension_handle.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
709d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      value = self._fields.get(extension_handle)
710d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      return value is not None and value._is_present_in_parent
711d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    else:
712d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      return extension_handle in self._fields
713fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  cls.HasExtension = HasExtension
714fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
715fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
716fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilledef _AddEqualsMethod(message_descriptor, cls):
717fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  """Helper for _AddMessageMethods()."""
718fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  def __eq__(self, other):
719fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    if (not isinstance(other, message_mod.Message) or
720fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville        other.DESCRIPTOR != self.DESCRIPTOR):
721fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      return False
722fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
723fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    if self is other:
724fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      return True
725fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
726d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    return self.ListFields() == other.ListFields()
727fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
728fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  cls.__eq__ = __eq__
729fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
730fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
731fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilledef _AddStrMethod(message_descriptor, cls):
732fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  """Helper for _AddMessageMethods()."""
733fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  def __str__(self):
734fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    return text_format.MessageToString(self)
735fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  cls.__str__ = __str__
736fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
737fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
738fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilledef _AddSetListenerMethod(cls):
739fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  """Helper for _AddMessageMethods()."""
740fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  def SetListener(self, listener):
741fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    if listener is None:
742fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      self._listener = message_listener_mod.NullMessageListener()
743fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    else:
744fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      self._listener = listener
745fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  cls._SetListener = SetListener
746fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
747fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
748fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilledef _BytesForNonRepeatedElement(value, field_number, field_type):
749fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  """Returns the number of bytes needed to serialize a non-repeated element.
750fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  The returned byte count includes space for tag information and any
751fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  other additional space associated with serializing value.
752fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
753fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  Args:
754fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    value: Value we're serializing.
755fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    field_number: Field number of this value.  (Since the field number
756fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      is stored as part of a varint-encoded tag, this has an impact
757fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      on the total bytes required to serialize the value).
758fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    field_type: The type of the field.  One of the TYPE_* constants
759fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      within FieldDescriptor.
760fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  """
761fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  try:
762fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    fn = type_checkers.TYPE_TO_BYTE_SIZE_FN[field_type]
763fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    return fn(field_number, value)
764fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  except KeyError:
765fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    raise message_mod.EncodeError('Unrecognized field type: %d' % field_type)
766fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
767fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
768fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilledef _AddByteSizeMethod(message_descriptor, cls):
769fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  """Helper for _AddMessageMethods()."""
770fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
771fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  def ByteSize(self):
772fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    if not self._cached_byte_size_dirty:
773fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      return self._cached_byte_size
774fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
775fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    size = 0
776d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    for field_descriptor, field_value in self.ListFields():
777d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      size += field_descriptor._sizer(field_value)
778fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
779fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    self._cached_byte_size = size
780fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    self._cached_byte_size_dirty = False
781d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    self._listener_for_children.dirty = False
782fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    return size
783fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
784fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  cls.ByteSize = ByteSize
785fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
786fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
787fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilledef _AddSerializeToStringMethod(message_descriptor, cls):
788fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  """Helper for _AddMessageMethods()."""
789fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
790fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  def SerializeToString(self):
791fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    # Check if the message has all of its required fields set.
792fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    errors = []
793d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    if not self.IsInitialized():
794d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      raise message_mod.EncodeError(
795d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          'Message is missing required fields: ' +
796d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          ','.join(self.FindInitializationErrors()))
797fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    return self.SerializePartialToString()
798fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  cls.SerializeToString = SerializeToString
799fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
800fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
801fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilledef _AddSerializePartialToStringMethod(message_descriptor, cls):
802fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  """Helper for _AddMessageMethods()."""
803fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
804fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  def SerializePartialToString(self):
805d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    out = StringIO()
806d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    self._InternalSerialize(out.write)
807d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    return out.getvalue()
808fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  cls.SerializePartialToString = SerializePartialToString
809fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
810d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  def InternalSerialize(self, write_bytes):
811d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    for field_descriptor, field_value in self.ListFields():
812d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      field_descriptor._encoder(write_bytes, field_value)
813d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  cls._InternalSerialize = InternalSerialize
814fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
815fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
816d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savilledef _AddMergeFromStringMethod(message_descriptor, cls):
817d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  """Helper for _AddMessageMethods()."""
818d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  def MergeFromString(self, serialized):
819d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    length = len(serialized)
820d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    try:
821d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      if self._InternalParse(serialized, 0, length) != length:
822d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        # The only reason _InternalParse would return early is if it
823d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        # encountered an end-group tag.
824d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        raise message_mod.DecodeError('Unexpected end-group tag.')
825d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    except IndexError:
826d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      raise message_mod.DecodeError('Truncated message.')
827d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    except struct.error, e:
828d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      raise message_mod.DecodeError(e)
829d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    return length   # Return this for legacy reasons.
830d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  cls.MergeFromString = MergeFromString
831fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
832d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  local_ReadTag = decoder.ReadTag
833d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  local_SkipField = decoder.SkipField
834d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  decoders_by_tag = cls._decoders_by_tag
835d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
836d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  def InternalParse(self, buffer, pos, end):
837d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    self._Modified()
838d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    field_dict = self._fields
839d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    while pos != end:
840d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      (tag_bytes, new_pos) = local_ReadTag(buffer, pos)
841d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      field_decoder = decoders_by_tag.get(tag_bytes)
842d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      if field_decoder is None:
843d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        new_pos = local_SkipField(buffer, new_pos, end, tag_bytes)
844d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        if new_pos == -1:
845d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          return pos
846d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        pos = new_pos
847d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      else:
848d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        pos = field_decoder(buffer, new_pos, end, self, field_dict)
849d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    return pos
850d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  cls._InternalParse = InternalParse
851fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
852fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
853d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savilledef _AddIsInitializedMethod(message_descriptor, cls):
854d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  """Adds the IsInitialized and FindInitializationError methods to the
855d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  protocol message class."""
856fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
857d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  required_fields = [field for field in message_descriptor.fields
858d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville                           if field.label == _FieldDescriptor.LABEL_REQUIRED]
859fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
860d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  def IsInitialized(self, errors=None):
861d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    """Checks if all required fields of a message are set.
862fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
863d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    Args:
864d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      errors:  A list which, if provided, will be populated with the field
865d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville               paths of all missing required fields.
866fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
867d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    Returns:
868d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      True iff the specified message has all required fields set.
869d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    """
870fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
871d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    # Performance is critical so we avoid HasField() and ListFields().
872fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
873d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    for field in required_fields:
874d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      if (field not in self._fields or
875d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          (field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE and
876d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville           not self._fields[field]._is_present_in_parent)):
877d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        if errors is not None:
878d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          errors.extend(self.FindInitializationErrors())
879d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        return False
880fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
881d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    for field, value in self._fields.iteritems():
882d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
883d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        if field.label == _FieldDescriptor.LABEL_REPEATED:
884d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          for element in value:
885d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville            if not element.IsInitialized():
886d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville              if errors is not None:
887d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville                errors.extend(self.FindInitializationErrors())
888d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville              return False
889d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        elif value._is_present_in_parent and not value.IsInitialized():
890d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          if errors is not None:
891d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville            errors.extend(self.FindInitializationErrors())
892d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          return False
893fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
894fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    return True
895fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
896d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  cls.IsInitialized = IsInitialized
897fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
898d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  def FindInitializationErrors(self):
899d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    """Finds required fields which are not initialized.
900fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
901d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    Returns:
902d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      A list of strings.  Each string is a path to an uninitialized field from
903d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      the top-level message, e.g. "foo.bar[5].baz".
904d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    """
905fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
906d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    errors = []  # simplify things
907fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
908d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    for field in required_fields:
909d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      if not self.HasField(field.name):
910d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        errors.append(field.name)
911fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
912d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    for field, value in self.ListFields():
913d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
914d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        if field.is_extension:
915d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          name = "(%s)" % field.full_name
916d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        else:
917d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          name = field.name
918fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
919d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        if field.label == _FieldDescriptor.LABEL_REPEATED:
920d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          for i in xrange(len(value)):
921d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville            element = value[i]
922d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville            prefix = "%s[%d]." % (name, i)
923d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville            sub_errors = element.FindInitializationErrors()
924d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville            errors += [ prefix + error for error in sub_errors ]
925d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        else:
926d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          prefix = name + "."
927d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          sub_errors = value.FindInitializationErrors()
928d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          errors += [ prefix + error for error in sub_errors ]
929fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
930d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    return errors
931fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
932d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  cls.FindInitializationErrors = FindInitializationErrors
933fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
934fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
935fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilledef _AddMergeFromMethod(cls):
936d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  LABEL_REPEATED = _FieldDescriptor.LABEL_REPEATED
937d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  CPPTYPE_MESSAGE = _FieldDescriptor.CPPTYPE_MESSAGE
938d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
939fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  def MergeFrom(self, msg):
940fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    assert msg is not self
941d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    self._Modified()
942d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
943d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    fields = self._fields
944d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
945d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    for field, value in msg._fields.iteritems():
946d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      if field.label == LABEL_REPEATED or field.cpp_type == CPPTYPE_MESSAGE:
947d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        field_value = fields.get(field)
948d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        if field_value is None:
949d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          # Construct a new object to represent this field.
950d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          field_value = field._default_constructor(self)
951d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          fields[field] = field_value
952d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        field_value.MergeFrom(value)
953d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      else:
954d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        self._fields[field] = value
955fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  cls.MergeFrom = MergeFrom
956fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
957fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
958fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilledef _AddMessageMethods(message_descriptor, cls):
959fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  """Adds implementations of all Message methods to cls."""
960fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  _AddListFieldsMethod(message_descriptor, cls)
961d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  _AddHasFieldMethod(message_descriptor, cls)
962d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  _AddClearFieldMethod(message_descriptor, cls)
963d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  if message_descriptor.is_extendable:
964d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    _AddClearExtensionMethod(cls)
965d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    _AddHasExtensionMethod(cls)
966d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  _AddClearMethod(message_descriptor, cls)
967fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  _AddEqualsMethod(message_descriptor, cls)
968fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  _AddStrMethod(message_descriptor, cls)
969fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  _AddSetListenerMethod(cls)
970fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  _AddByteSizeMethod(message_descriptor, cls)
971fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  _AddSerializeToStringMethod(message_descriptor, cls)
972fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  _AddSerializePartialToStringMethod(message_descriptor, cls)
973fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  _AddMergeFromStringMethod(message_descriptor, cls)
974d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  _AddIsInitializedMethod(message_descriptor, cls)
975fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  _AddMergeFromMethod(cls)
976fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
977fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
978fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilledef _AddPrivateHelperMethods(cls):
979fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  """Adds implementation of private helper methods to cls."""
980fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
981d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  def Modified(self):
982fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    """Sets the _cached_byte_size_dirty bit to true,
983fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    and propagates this to our listener iff this was a state change.
984fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    """
985d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
986d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    # Note:  Some callers check _cached_byte_size_dirty before calling
987d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    #   _Modified() as an extra optimization.  So, if this method is ever
988d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    #   changed such that it does stuff even when _cached_byte_size_dirty is
989d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    #   already true, the callers need to be updated.
990fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    if not self._cached_byte_size_dirty:
991fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      self._cached_byte_size_dirty = True
992d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      self._listener_for_children.dirty = True
993d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      self._is_present_in_parent = True
994d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      self._listener.Modified()
995d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
996d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  cls._Modified = Modified
997d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  cls.SetInParent = Modified
998fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
999fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1000fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleclass _Listener(object):
1001fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1002fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  """MessageListener implementation that a parent message registers with its
1003fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  child message.
1004fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1005fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  In order to support semantics like:
1006fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1007d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    foo.bar.baz.qux = 23
1008fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    assert foo.HasField('bar')
1009fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1010fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  ...child objects must have back references to their parents.
1011fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  This helper class is at the heart of this support.
1012fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  """
1013fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1014d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  def __init__(self, parent_message):
1015fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    """Args:
1016d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      parent_message: The message whose _Modified() method we should call when
1017d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        we receive Modified() messages.
1018fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    """
1019fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    # This listener establishes a back reference from a child (contained) object
1020fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    # to its parent (containing) object.  We make this a weak reference to avoid
1021fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    # creating cyclic garbage when the client finishes with the 'parent' object
1022fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    # in the tree.
1023fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    if isinstance(parent_message, weakref.ProxyType):
1024fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      self._parent_message_weakref = parent_message
1025fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    else:
1026fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      self._parent_message_weakref = weakref.proxy(parent_message)
1027fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1028d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    # As an optimization, we also indicate directly on the listener whether
1029d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    # or not the parent message is dirty.  This way we can avoid traversing
1030d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    # up the tree in the common case.
1031d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    self.dirty = False
1032d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
1033d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  def Modified(self):
1034d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    if self.dirty:
1035d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      return
1036fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    try:
1037fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      # Propagate the signal to our parents iff this is the first field set.
1038d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      self._parent_message_weakref._Modified()
1039fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    except ReferenceError:
1040fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      # We can get here if a client has kept a reference to a child object,
1041fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      # and is now setting a field on it, but the child's parent has been
1042fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      # garbage-collected.  This is not an error.
1043fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      pass
1044fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1045fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1046fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# TODO(robinson): Move elsewhere?  This file is getting pretty ridiculous...
1047fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# TODO(robinson): Unify error handling of "unknown extension" crap.
1048fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# TODO(robinson): Support iteritems()-style iteration over all
1049fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville# extensions with the "has" bits turned on?
1050fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleclass _ExtensionDict(object):
1051fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1052fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  """Dict-like container for supporting an indexable "Extensions"
1053fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  field on proto instances.
1054fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1055fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  Note that in all cases we expect extension handles to be
1056fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  FieldDescriptors.
1057fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  """
1058fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1059d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  def __init__(self, extended_message):
1060d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    """extended_message: Message instance for which we are the Extensions dict.
1061d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    """
1062fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1063d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    self._extended_message = extended_message
1064fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1065d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  def __getitem__(self, extension_handle):
1066d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    """Returns the current value of the given extension handle."""
1067fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1068d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    _VerifyExtensionHandle(self._extended_message, extension_handle)
1069fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1070d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    result = self._extended_message._fields.get(extension_handle)
1071d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    if result is not None:
1072d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      return result
1073fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1074d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    if extension_handle.label == _FieldDescriptor.LABEL_REPEATED:
1075d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      result = extension_handle._default_constructor(self._extended_message)
1076d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    elif extension_handle.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
1077d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      result = extension_handle.message_type._concrete_class()
1078d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      try:
1079d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        result._SetListener(self._extended_message._listener_for_children)
1080d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      except ReferenceError:
1081d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        pass
1082d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    else:
1083d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      # Singular scalar -- just return the default without inserting into the
1084d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      # dict.
1085d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      return extension_handle.default_value
1086fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1087d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    # Atomically check if another thread has preempted us and, if not, swap
1088d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    # in the new object we just created.  If someone has preempted us, we
1089d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    # take that object and discard ours.
1090d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    # WARNING:  We are relying on setdefault() being atomic.  This is true
1091d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    #   in CPython but we haven't investigated others.  This warning appears
1092d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    #   in several other locations in this file.
1093d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    result = self._extended_message._fields.setdefault(
1094d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        extension_handle, result)
1095fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1096d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    return result
1097fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1098fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  def __eq__(self, other):
1099d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    if not isinstance(other, self.__class__):
1100d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      return False
1101d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
1102d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    my_fields = self._extended_message.ListFields()
1103d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    other_fields = other._extended_message.ListFields()
1104d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
1105d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    # Get rid of non-extension fields.
1106d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    my_fields    = [ field for field in my_fields    if field.is_extension ]
1107d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    other_fields = [ field for field in other_fields if field.is_extension ]
1108d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
1109d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    return my_fields == other_fields
1110fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1111fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  def __ne__(self, other):
1112fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    return not self == other
1113fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1114fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  # Note that this is only meaningful for non-repeated, scalar extension
1115d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  # fields.  Note also that we may have to call _Modified() when we do
1116d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  # successfully set a field this way, to set any necssary "has" bits in the
1117d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  # ancestors of the extended message.
1118fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  def __setitem__(self, extension_handle, value):
1119fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    """If extension_handle specifies a non-repeated, scalar extension
1120fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    field, sets the value of that field.
1121fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    """
1122fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1123d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    _VerifyExtensionHandle(self._extended_message, extension_handle)
1124d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
1125d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    if (extension_handle.label == _FieldDescriptor.LABEL_REPEATED or
1126d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        extension_handle.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE):
1127d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      raise TypeError(
1128d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          'Cannot assign to extension "%s" because it is a repeated or '
1129d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville          'composite type.' % extension_handle.full_name)
1130d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
1131d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    # It's slightly wasteful to lookup the type checker each time,
1132d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    # but we expect this to be a vanishingly uncommon case anyway.
1133d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    type_checker = type_checkers.GetTypeChecker(
1134d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        extension_handle.cpp_type, extension_handle.type)
1135d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    type_checker.CheckValue(value)
1136d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    self._extended_message._fields[extension_handle] = value
1137d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    self._extended_message._Modified()
1138fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1139fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  def _FindExtensionByName(self, name):
1140fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    """Tries to find a known extension with the specified name.
1141fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1142fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    Args:
1143fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      name: Extension full name.
1144fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1145fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    Returns:
1146fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      Extension field descriptor.
1147fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    """
1148d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    return self._extended_message._extensions_by_name.get(name, None)
1149