17e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# Protocol Buffers - Google's data interchange format
27e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# Copyright 2008 Google Inc.  All rights reserved.
37e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# http://code.google.com/p/protobuf/
47e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang#
57e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# Redistribution and use in source and binary forms, with or without
67e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# modification, are permitted provided that the following conditions are
77e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# met:
87e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang#
97e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang#     * Redistributions of source code must retain the above copyright
107e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# notice, this list of conditions and the following disclaimer.
117e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang#     * Redistributions in binary form must reproduce the above
127e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# copyright notice, this list of conditions and the following disclaimer
137e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# in the documentation and/or other materials provided with the
147e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# distribution.
157e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang#     * Neither the name of Google Inc. nor the names of its
167e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# contributors may be used to endorse or promote products derived from
177e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# this software without specific prior written permission.
187e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang#
197e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
207e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
217e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
227e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
237e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
247e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
257e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
267e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
277e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
287e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
297e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
307e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
317e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang# This code is meant to work on Python 2.4 and above only.
327e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
337e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang"""Contains a metaclass and helper functions used to create
347e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wangprotocol message classes from Descriptor objects at runtime.
357e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
367e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing WangRecall that a metaclass is the "type" of a class.
377e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang(A class is to a metaclass what an instance is to a class.)
387e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
397e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing WangIn this case, we use the GeneratedProtocolMessageType metaclass
407e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wangto inject all the useful functionality into the classes
417e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wangoutput by the protocol compiler at compile-time.
427e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
437e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing WangThe upshot of all this is that the real implementation
447e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wangdetails for ALL pure-Python protocol buffers are *here in
457e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wangthis file*.
467e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang"""
477e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
487e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang__author__ = 'robinson@google.com (Will Robinson)'
497e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
507e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
517e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wangfrom google.protobuf.internal import api_implementation
527e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wangfrom google.protobuf import descriptor as descriptor_mod
537e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wangfrom google.protobuf import message
547e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
557e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang_FieldDescriptor = descriptor_mod.FieldDescriptor
567e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
577e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
587e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wangif api_implementation.Type() == 'cpp':
597e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  if api_implementation.Version() == 2:
607e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    from google.protobuf.internal.cpp import cpp_message
617e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    _NewMessage = cpp_message.NewMessage
627e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    _InitMessage = cpp_message.InitMessage
637e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  else:
647e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    from google.protobuf.internal import cpp_message
657e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    _NewMessage = cpp_message.NewMessage
667e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    _InitMessage = cpp_message.InitMessage
677e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wangelse:
687e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  from google.protobuf.internal import python_message
697e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  _NewMessage = python_message.NewMessage
707e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  _InitMessage = python_message.InitMessage
717e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
727e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
737e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wangclass GeneratedProtocolMessageType(type):
747e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
757e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  """Metaclass for protocol message classes created at runtime from Descriptors.
767e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
777e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  We add implementations for all methods described in the Message class.  We
787e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  also create properties to allow getting/setting all fields in the protocol
797e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  message.  Finally, we create slots to prevent users from accidentally
807e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  "setting" nonexistent fields in the protocol message, which then wouldn't get
817e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  serialized / deserialized properly.
827e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
837e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  The protocol compiler currently uses this metaclass to create protocol
847e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  message classes at runtime.  Clients can also manually create their own
857e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  classes at runtime, as in this example:
867e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
877e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  mydescriptor = Descriptor(.....)
887e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  class MyProtoClass(Message):
897e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    __metaclass__ = GeneratedProtocolMessageType
907e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    DESCRIPTOR = mydescriptor
917e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  myproto_instance = MyProtoClass()
927e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  myproto.foo_field = 23
937e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  ...
947e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  """
957e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
967e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  # Must be consistent with the protocol-compiler code in
977e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  # proto2/compiler/internal/generator.*.
987e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  _DESCRIPTOR_KEY = 'DESCRIPTOR'
997e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1007e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  def __new__(cls, name, bases, dictionary):
1017e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    """Custom allocation for runtime-generated class types.
1027e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1037e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    We override __new__ because this is apparently the only place
1047e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    where we can meaningfully set __slots__ on the class we're creating(?).
1057e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    (The interplay between metaclasses and slots is not very well-documented).
1067e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1077e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    Args:
1087e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang      name: Name of the class (ignored, but required by the
1097e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang        metaclass protocol).
1107e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang      bases: Base classes of the class we're constructing.
1117e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang        (Should be message.Message).  We ignore this field, but
1127e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang        it's required by the metaclass protocol
1137e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang      dictionary: The class dictionary of the class we're
1147e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang        constructing.  dictionary[_DESCRIPTOR_KEY] must contain
1157e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang        a Descriptor object describing this protocol message
1167e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang        type.
1177e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1187e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    Returns:
1197e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang      Newly-allocated class.
1207e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    """
1217e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    descriptor = dictionary[GeneratedProtocolMessageType._DESCRIPTOR_KEY]
1227e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    bases = _NewMessage(bases, descriptor, dictionary)
1237e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    superclass = super(GeneratedProtocolMessageType, cls)
1247e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1257e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    new_class = superclass.__new__(cls, name, bases, dictionary)
1267e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    setattr(descriptor, '_concrete_class', new_class)
1277e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    return new_class
1287e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1297e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  def __init__(cls, name, bases, dictionary):
1307e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    """Here we perform the majority of our work on the class.
1317e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    We add enum getters, an __init__ method, implementations
1327e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    of all Message methods, and properties for all fields
1337e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    in the protocol type.
1347e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1357e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    Args:
1367e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang      name: Name of the class (ignored, but required by the
1377e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang        metaclass protocol).
1387e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang      bases: Base classes of the class we're constructing.
1397e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang        (Should be message.Message).  We ignore this field, but
1407e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang        it's required by the metaclass protocol
1417e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang      dictionary: The class dictionary of the class we're
1427e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang        constructing.  dictionary[_DESCRIPTOR_KEY] must contain
1437e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang        a Descriptor object describing this protocol message
1447e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang        type.
1457e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    """
1467e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    descriptor = dictionary[GeneratedProtocolMessageType._DESCRIPTOR_KEY]
1477e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    _InitMessage(descriptor, cls)
1487e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    superclass = super(GeneratedProtocolMessageType, cls)
1497e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    superclass.__init__(name, bases, dictionary)
1507e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1517e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1527e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wangdef ParseMessage(descriptor, byte_str):
1537e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  """Generate a new Message instance from this Descriptor and a byte string.
1547e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1557e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  Args:
1567e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    descriptor: Protobuf Descriptor object
1577e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    byte_str: Serialized protocol buffer byte string
1587e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1597e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  Returns:
1607e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    Newly created protobuf Message object.
1617e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  """
1627e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1637e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  class _ResultClass(message.Message):
1647e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    __metaclass__ = GeneratedProtocolMessageType
1657e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang    DESCRIPTOR = descriptor
1667e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang
1677e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  new_msg = _ResultClass()
1687e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  new_msg.ParseFromString(byte_str)
1697e7f2e9122af6c7e7e7d4ba205fdf46d50b95eefYing Wang  return new_msg
170