ll change the state of
            # dct.
            for key, field in dct.items():

                if key in _RESERVED_ATTRIBUTE_NAMES:
                    continue

                if isinstance(field, type) and issubclass(field, Enum):
                    enums.append(key)
                    continue

                if (isinstance(field, type) and
                        issubclass(field, Message) and
                        field is not Message):
                    messages.append(key)
                    continue

                # Reject anything that is not a field.
                # pylint:disable=unidiomatic-typecheck
                if type(field) is Field or not isinstance(field, Field):
                    raise MessageDefinitionError(
                        'May only use fields in message definitions.  '
                        'Found: %s = %s' %
                        (key, field))

                if field.number in by_number:
                    raise DuplicateNumberError(
                        'Field with number %d declared more than once in %s' %
                        (field.number, name))

                field.name = key

                # Place in name and number maps.
                by_name[key] = field
                by_number[field.number] = field

            # Add enums if any exist.
            if enums:
                dct['__enums__'] = sorted(enums)

            # Add messages if any exist.
            if messages:
                dct['__messages__'] = sorted(messages)

        dct['_Message__by_number'] = by_number
        dct['_Message__by_name'] = by_name

        return _DefinitionClass.__new__(cls, name, bases, dct)

    def __init__(cls, name, bases, dct):
        """Initializer required to assign references to new class."""
        if bases != (object,):
            for v in dct.values():
                if isinstance(v, _DefinitionClass) and v is not Message:
                    v._message_definition = weakref.ref(cls)

            for field in cls.all_fields():
                field._message_definition = weakref.ref(cls)

        _DefinitionClass.__init__(cls, name, bases, dct)


class Message(six.with_metaclass(_MessageClass, object)):
    """Base class for user defined message objects.

    Used to define messages for efficient transmission across network or
    process space.  Messages are defined using the field classes (IntegerField,
    FloatField, EnumField, etc.).

    Messages are more restricted than normal classes in that they may
    only contain field attributes and other Message and Enum
    definitions. These restrictions are in place because the structure
    of the Message class is intentended to itself be transmitted
    across network or process space and used directly by clients or
    even other servers. As such methods and non-field attributes could
    not be transmitted with the structural information causing
    discrepancies between different languages and implementations.

    Initialization and validation:

      A Message object is considered to be initialized if it has all required
      fields and any nested messages are also initialized.

      Calling 'check_initialized' will raise a ValidationException if it is not
      initialized; 'is_initialized' returns a boolean value indicating if it is
      valid.

      Validation automatically occurs when Message objects are created
      and populated.  Validation that a given value will be compatible with
      a field that it is assigned to can be done through the Field instances
      validate() method.  The validate method used on a message will check that
      all values of a message and its sub-messages are valid.  Assingning an
      invalid value to a field will raise a ValidationException.

    Example:

      # Trade type.
      class TradeType(Enum):
        BUY = 1
        SELL = 2
        SHORT = 3
        CALL = 4

      class Lot(Message):
        price = IntegerField(1, required=True)
        quantity = IntegerField(2, required=True)

      class Order(Message):
        symbol = StringField(1, required=True)
        total_quantity = IntegerField(2, required=True)
        trade_type = EnumField(TradeType, 3, required=True)
        lots = MessageField(Lot, 4, repeated=True)
        limit = IntegerField(5)

      order = Order(symbol='GOOG',
                    total_quantity=10,
                    trade_type=TradeType.BUY)

      lot1 = Lot(price=304,
                 quantity=7)

      lot2 = Lot(price = 305,
                 quantity=3)

      order.lots = [lot1, lot2]

      # Now object is initialized!
      order.check_initialized()

    """

    def __init__(self, **kwargs):
        """Initialize internal messages state.

        Args:
          A message can be initialized via the constructor by passing
          in keyword arguments corresponding to fields. For example:

            class Date(Message):
              day = IntegerField(1)
              month = IntegerField(2)
              year = IntegerField(3)

          Invoking:

            date = Date(day=6, month=6, year=1911)

          is the same as doing:

            date = Date()
            date.day = 6
            date.month = 6
            date.year = 1911

        """
        # Tag being an essential implementation detail must be private.
        self.__tags = {}
        self.__unrecognized_fields = {}

        assigned = set()
        for name, value in kwargs.items():
            setattr(self, name, value)
            assigned.add(name)

        # initialize repeated fields.
        for field in self.all_fields():
            if field.repeated and field.name not in assigned:
                setattr(self, field.name, [])

    def check_initialized(self):
        """Check class for initialization status.

        Check that all required fields are initialized

        Raises:
          ValidationError: If message is not initialized.
        """
        for name, field in self.__by_name.items():
            value = getattr(self, name)
            if value is None:
                if field.required:
                    raise ValidationError(
                        "Message %s is missing required field %s" %
                        (type(self).__name__, name))
            else:
                try:
                    if (isinstance(field, MessageField) and
                            issubclass(field.message_type, Message)):
                        if field.repeated:
                            for item in value:
                                item_message_value = field.value_to_message(
                                    item)
                                item_message_value.check_initialized()
                        else:
                            message_value = field.value_to_message(value)
                            message_value.check_initialized()
                except ValidationError as err:
                    if not hasattr(err, 'message_name'):
                        err.message_name = type(self).__name__
                    raise

    def is_initialized(self):
        """Get initialization status.

        Returns:
          True if message is valid, else False.
        """
        try:
            self.check_initialized()
        except ValidationError:
            return False
        else:
            return True

    @classmethod
    def all_fields(cls):
        """Get all field definition objects.

        Ordering is arbitrary.

        Returns:
          Iterator over all values in arbitrary order.
        """
        return cls.__by_name.values()

    @classmethod
    def field_by_name(cls, name):
        """Get field by name.

        Returns:
          Field object associated with name.

        Raises:
          KeyError if no field found by that name.
        """
        return cls.__by_name[name]

    @classmethod
    def field_by_number(cls, number):
        """Get field by number.

        Returns:
          Field object associated with number.

        Raises:
          KeyError if no field found by that number.
        """
        return cls.__by_number[number]

    def get_assigned_value(self, name):
        """Get the assigned value of an attribute.

        Get the underlying value of an attribute. If value has not
        been set, will not return the default for the field.

        Args:
          name: Name of attribute to get.

        Returns:
          Value of attribute, None if it has not been set.

        """
        message_type = type(self)
        try:
            field = message_type.field_by_name(name)
        except KeyError:
            raise AttributeError('Message %s has no field %s' % (
                message_type.__name__, name))
        return self.__tags.get(field.number)

    def reset(self, name):
        """Reset assigned value for field.

        Resetting a field will return it to its default value or None.

        Args:
          name: Name of field to reset.
        """
        message_type = type(self)
        try:
            field = message_type.field_by_name(name)
        except KeyError:
            if name not in message_type.__by_name:
                raise AttributeError('Message %s has no field %s' % (
                    message_type.__name__, name))
        if field.repeated:
            self.__tags[field.number] = FieldList(field, [])
        else:
            self.__tags.pop(field.number, None)

    def all_unrecognized_fields(self):
        """Get the names of all unrecognized fields in this message."""
        return list(self.__unrecognized_fields.keys())

    def get_unrecognized_field_info(self, key, value_default=None,
                                    variant_default=None):
        """Get the value and variant of an unknown field in this message.

        Args:
          key: The name or number of the field to retrieve.
          value_default: Value to be returned if the key isn't found.
          variant_default: Value to be returned as variant if the key isn't
            found.

        Returns:
          (value, variant), where value and variant are whatever was passed
          to set_unrecognized_field.
        """
        value, variant = self.__unrecognized_fields.get(key, (value_default,
                                                              variant_default))
        return value, variant

    def set_unrecognized_field(self, key, value, variant):
        """Set an unrecognized field, used when decoding a message.

        Args:
          key: The name or number used to refer to this unknown value.
          value: The value of the field.
          variant: Type information needed to interpret the value or re-encode
            it.

        Raises:
          TypeError: If the variant is not an instance of messages.Variant.
        """
        if not isinstance(variant, Variant):
            raise TypeError('Variant type %s is not valid.' % variant)
        self.__unrecognized_fields[key] = value, variant

    def __setattr__(self, name, value):
        """Change set behavior for messages.

        Messages may only be assigned values that are fields.

        Does not try to validate field when set.

        Args:
          name: Name of field to assign to.
          value: Value to assign to field.

        Raises:
          AttributeError when trying to assign value that is not a field.
        """
        if name in self.__by_name or name.startswith('_Message__'):
            object.__setattr__(self, name, value)
        else:
            raise AttributeError("May not assign arbitrary value %s "
                                 "to message %s" % (name, type(self).__name__))

    def __repr__(self):
        """Make string representation of message.

        Example:

          class MyMessage(messages.Message):
            integer_value = messages.IntegerField(1)
            string_value = messages.StringField(2)

          my_message = MyMessage()
          my_message.integer_value = 42
          my_message.string_value = u'A string'

          print my_message
          >>> <MyMessage
          ...  integer_value: 42
          ...  string_value: u'A string'>

        Returns:
          String representation of message, including the values
          of all fields and repr of all sub-messages.
        """
        body = ['<', type(self).__name__]
        for field in sorted(self.all_fields(),
                            key=lambda f: f.number):
            attribute = field.name
            value = self.get_assigned_value(field.name)
            if value is not None:
                body.append('\n %s: %s' % (attribute, repr(value)))
        body.append('>')
        return ''.join(body)

    def __eq__(self, other):
        """Equality operator.

        Does field by field comparison with other message.  For
        equality, must be same type and values of all fields must be
        equal.

        Messages not required to be initialized for comparison.

        Does not attempt to determine equality for values that have
        default values that are not set.  In other words:

          class HasDefault(Message):

            attr1 = StringField(1, default='default value')

          message1 = HasDefault()
          message2 = HasDefault()
          message2.attr1 = 'default value'

          message1 != message2

        Does not compare unknown values.

        Args:
          other: Other message to compare with.
        """
        # TODO(user): Implement "equivalent" which does comparisons
        # taking default values in to consideration.
        if self is other:
            return True

        if type(self) is not type(other):
            return False

        return self.__tags == other.__tags

    def __ne__(self, other):
        """Not equals operator.

        Does field by field comparison with other message.  For
        non-equality, must be different type or any value of a field must be
        non-equal to the same field in the other instance.

        Messages not required to be initialized for comparison.

        Args:
          other: Other message to compare with.
        """
        return not self.__eq__(other)


class FieldList(list):
    """List implementation that validates field values.

    This list implementation overrides all methods that add values in
    to a list in order to validate those new elements. Attempting to
    add or set list values that are not of the correct type will raise
    ValidationError.

    """

    def __init__(self, field_instance, sequence):
        """Constructor.

        Args:
          field_instance: Instance of field that validates the list.
          sequence: List or tuple to construct list from.
        """
        if not field_instance.repeated:
            raise FieldDefinitionError(
                'FieldList may only accept repeated fields')
        self.__field = field_instance
        self.__field.validate(sequence)
        list.__init__(self, sequence)

    def __getstate__(self):
        """Enable pickling.

        The assigned field instance can't be pickled if it belongs to
        a Message definition (message_definition uses a weakref), so
        the Message class and field number are returned in that case.

        Returns:
          A 3-tuple containing:
            - The field instance, or None if it belongs to a Message class.
            - The Message class that the field instance belongs to, or None.
            - The field instance number of the Message class it belongs to, or
                None.

        """
        message_class = self.__field.message_definition()
        if message_class is None:
            return self.__field, None, None
        return None, message_class, self.__field.number

    def __setstate__(self, state):
        """Enable unpickling.

        Args:
          state: A 3-tuple containing:
            - The field instance, or None if it belongs to a Message class.
            - The Message class that the field instance belongs to, or None.
            - The field instance number of the Message class it belongs to, or
                None.
        """
        field_instance, message_class, number = state
        if field_instance is None:
            self.__field = message_class.field_by_number(number)
        else:
            self.__field = field_instance

    @property
    def field(self):
        """Field that validates list."""
        return self.__field

    def __setslice__(self, i, j, sequence):
        """Validate slice assignment to list."""
        self.__field.validate(sequence)
        list.__setslice__(self, i, j, sequence)

    def __setitem__(self, index, value):
        """Validate item assignment to list."""
        if isinstance(index, slice):
            self.__field.validate(value)
        else:
            self.__field.validate_element(value)
        list.__setitem__(self, index, value)

    def append(self, value):
        """Validate item appending to list."""
        if getattr(self, '_FieldList__field', None):
            self.__field.validate_element(value)
        return list.append(self, value)

    def extend(self, sequence):
        """Validate extension of list."""
        if getattr(self, '_FieldList__field', None):
            self.__field.validate(sequence)
        return list.extend(self, sequence)

    def insert(self, index, value):
        """Validate item insertion to list."""
        self.__field.validate_element(value)
        return list.insert(self, index, value)


class _FieldMeta(type):

    def __init__(cls, name, bases, dct):
        getattr(cls, '_Field__variant_to_type').update(
            (variant, cls) for variant in dct.get('VARIANTS', []))
        type.__init__(cls, name, bases, dct)


# TODO(user): Prevent additional field subclasses.
class Field(six.with_metaclass(_FieldMeta, object)):
    """Definition for message field."""

    __initialized = False  # pylint:disable=invalid-name
    __variant_to_type = {}  # pylint:disable=invalid-name

    @util.positional(2)
    def __init__(self,
                 number,
                 required=False,
                 repeated=False,
                 variant=None,
                 default=None):
        """Constructor.

        The required and repeated parameters are mutually exclusive.
        Setting both to True will raise a FieldDefinitionError.

        Sub-class Attributes:
          Each sub-class of Field must define the following:
            VARIANTS: Set of variant types accepted by that field.
            DEFAULT_VARIANT: Default variant type if not specified in
              constructor.

        Args:
          number: Number of field.  Must be unique per message class.
          required: Whether or not field is required.  Mutually exclusive with
            'repeated'.
          repeated: Whether or not field is repeated.  Mutually exclusive with
            'required'.
          variant: Wire-format variant hint.
          default: Default value for field if not found in stream.

        Raises:
          InvalidVariantError when invalid variant for field is provided.
          InvalidDefaultError when invalid default for field is provided.
          FieldDefinitionError when invalid number provided or mutually
            exclusive fields are used.
          InvalidNumberError when the field number is out of range or reserved.

        """
        if not isinstance(number, int) or not 1 <= number <= MAX_FIELD_NUMBER:
            raise InvalidNumberError(
                'Invalid number for field: %s\n'
                'Number must be 1 or greater and %d or less' %
                (number, MAX_FIELD_NUMBER))

        if FIRST_RESERVED_FIELD_NUMBER <= number <= LAST_RESERVED_FIELD_NUMBER:
            raise InvalidNumberError('Tag number %d is a reserved number.\n'
                                     'Numbers %d to %d are reserved' %
                                     (number, FIRST_RESERVED_FIELD_NUMBER,
                                      LAST_RESERVED_FIELD_NUMBER))

        if repeated and required:
            raise FieldDefinitionError('Cannot set both repeated and required')

        if variant is None:
            variant = self.DEFAULT_VARIANT

        if repeated and default is not None:
            raise FieldDefinitionError('Repeated fields may not have defaults')

        if variant not in self.VARIANTS:
            raise InvalidVariantError(
                'Invalid variant: %s\nValid variants for %s are %r' %
                (variant, type(self).__name__, sorted(self.VARIANTS)))

        self.number = number
        self.required = required
        self.repeated = repeated
        self.variant = variant

        if default is not None:
            try:
                self.validate_default(default)
            except ValidationError as err:
                try:
                    name = self.name
                except AttributeError:
                    # For when raising error before name initialization.
                    raise InvalidDefaultError(
                        'Invalid default value for %s: %r: %s' %
                        (self.__class__.__name__, default, err))
                else:
                    raise InvalidDefaultError(
                        'Invalid default value for field %s: '
                        '%r: %s' % (name, default, err))

        self.__default = default
        self.__initialized = True

    def __setattr__(self, name, value):
        """Setter overidden to prevent assignment to fields after creation.

        Args:
          name: Name of attribute to set.
          value: Value to assign.
        """
        # Special case post-init names.  They need to be set after constructor.
        if name in _POST_INIT_FIELD_ATTRIBUTE_NAMES:
            object.__setattr__(self, name, value)
            return

        # All other attributes must be set before __initialized.
        if not self.__initialized:
            # Not initialized yet, allow assignment.
            object.__setattr__(self, name, value)
        else:
            raise AttributeError('Field objects are read-only')

    def __set__(self, message_instance, value):
        """Set value on message.

        Args:
          message_instance: Message instance to set value on.
          value: Value to set on message.
        """
        # Reaches in to message instance directly to assign to private tags.
        if value is None:
            if self.repeated:
                raise ValidationError(
                    'May not assign None to repeated field %s' % self.name)
            else:
                message_instance._Message__tags.pop(self.number, None)
        else:
            if self.repeated:
                value = FieldList(self, value)
            else:
                value = self.validate(value)
            message_instance._Message__tags[self.number] = value

    def __get__(self, message_instance, message_class):
        if message_instance is None:
            return self

        result = message_instance._Message__tags.get(self.number)
        if result is None:
            return self.default
        return result

    def validate_element(self, value):
        """Validate single element of field.

        This is different from validate in that it is used on individual
        values of repeated fields.

        Args:
          value: Value to validate.

        Returns:
          The value casted in the expected type.

        Raises:
          ValidationError if value is not expected type.
        """
        if not isinstance(value, self.type):

            # Authorize int values as float.
            if isinstance(value, six.integer_types) and self.type == float:
                return float(value)

            if value is None:
                if self.required:
                    raise ValidationError('Required field is missing')
            else:
                try:
                    name = self.name
                except AttributeError:
                    raise ValidationError('Expected type %s for %s, '
                                          'found %s (type %s)' %
                                          (self.type, self.__class__.__name__,
                                           value, type(value)))
                else:
                    raise ValidationError(
                        'Expected type %s for field %s, found %s (type %s)' %
                        (self.type, name, value, type(value)))
        return value

    def __validate(self, value, validate_element):
        """Internal validation function.

        Validate an internal value using a function to validate
        individual elements.

        Args:
          value: Value to validate.
          validate_element: Function to use to validate individual elements.

        Raises:
          ValidationError if value is not expected type.

        """
        if not self.repeated:
            return validate_element(value)
        else:
            # Must be a list or tuple, may not be a string.
            if isinstance(value, (list, tuple)):
                result = []
                for element in value:
                    if element is None:
                        try:
                            name = self.name
                        except AttributeError:
                            raise ValidationError(
                                'Repeated values for %s '
                                'may not be None' % self.__class__.__name__)
                        else:
                            raise ValidationError(
                                'Repeated values for field %s '
                                'may not be None' % name)
                    result.append(validate_element(element))
                return result
            elif value is not None:
                try:
                    name = self.name
                except AttributeError:
                    raise ValidationError('%s is repeated. Found: %s' % (
                        self.__class__.__name__, value))
                else:
                    raise ValidationError(
                        'Field %s is repeated. Found: %s' % (name, value))
        return value

    def validate(self, value):
        """Validate value assigned to field.

        Args:
          value: Value to validate.

        Returns:
          the value in casted in the correct type.

        Raises:
          ValidationError if value is not expected type.
        """
        return self.__validate(value, self.validate_element)

    def validate_default_element(self, value):
        """Validate value as assigned to field default field.

        Some fields may allow for delayed resolution of default types
        necessary in the case of circular definition references. In
        this case, the default value might be a place holder that is
        resolved when needed after all the message classes are
        defined.

        Args:
          value: Default value to validate.

        Returns:
          the value in casted in the correct type.

        Raises:
          ValidationError if value is not expected type.

        """
        return self.validate_element(value)

    def validate_default(self, value):
        """Validate default value assigned to field.

        Args:
          value: Value to validate.

        Returns:
          the value in casted in the correct type.

        Raises:
          ValidationError if value is not expected type.
        """
        return self.__validate(value, self.validate_default_element)

    def message_definition(self):
        """Get Message definition that contains this Field definition.

        Returns:
          Containing Message definition for Field. Will return None if
          for some reason Field is defined outside of a Message class.

        """
        try:
            return self._message_definition()
        except AttributeError:
            return None

    @property
    def default(self):
        """Get default value for field."""
        return self.__default

    @classmethod
    def lookup_field_type_by_variant(cls, variant):
        return cls.__variant_to_type[variant]


class IntegerField(Field):
    """Field definition for integer values."""

    VARIANTS = frozenset([
        Variant.INT32,
        Variant.INT64,
        Variant.UINT32,
        Variant.UINT64,
        Variant.SINT32,
        Variant.SINT64,
    ])

    DEFAULT_VARIANT = Variant.INT64

    type = six.integer_types


class FloatField(Field):
    """Field definition for float values."""

    VARIANTS = frozenset([
        Variant.FLOAT,
        Variant.DOUBLE,
    ])

    DEFAULT_VARIANT = Variant.DOUBLE

    type = float


class BooleanField(Field):
    """Field definition for boolean values."""

    VARIANTS = frozenset([Variant.BOOL])

    DEFAULT_VARIANT = Variant.BOOL

    type = bool


class BytesField(Field):
    """Field definition for byte string values."""

    VARIANTS = frozenset([Variant.BYTES])

    DEFAULT_VARIANT = Variant.BYTES

    type = bytes


class StringField(Field):
    """Field definition for unicode string values."""

    VARIANTS = frozenset([Variant.STRING])

    DEFAULT_VARIANT = Variant.STRING

    type = six.text_type

    def validate_element(self, value):
        """Validate StringField allowing for str and unicode.

        Raises:
          ValidationError if a str value is not UTF-8.
        """
        # If value is str is it considered valid.  Satisfies "required=True".
        if isinstance(value, bytes):
            try:
                six.text_type(value, 'UTF-8')
            except UnicodeDecodeError as err:
                try:
                    _ = self.name
                except AttributeError:
                    validation_error = ValidationError(
                        'Field encountered non-UTF-8 string %r: %s' % (value,
                                                                       err))
                else:
                    validation_error = ValidationError(
                        'Field %s encountered non-UTF-8 string %r: %s' % (
                            self.name, value, err))
                    validation_error.field_name = self.name
                raise validation_error
        else:
            return super(StringField, self).validate_element(value)
        return value


class MessageField(Field):
    """Field definition for sub-message values.

    Message fields contain instance of other messages.  Instances stored
    on messages stored on message fields  are considered to be owned by
    the containing message instance and should not be shared between
    owning instances.

    Message fields must be defined to reference a single type of message.
    Normally message field are defined by passing the referenced message
    class in to the constructor.

    It is possible to define a message field for a type that does not
    yet exist by passing the name of the message in to the constructor
    instead of a message class. Resolution of the actual type of the
    message is deferred until it is needed, for example, during
    message verification. Names provided to the constructor must refer
    to a class within the same python module as the class that is
    using it. Names refer to messages relative to the containing
    messages scope. For example, the two fields of OuterMessage refer
    to the same message type:

      class Outer(Message):

        inner_relative = MessageField('Inner', 1)
        inner_absolute = MessageField('Outer.Inner', 2)

        class Inner(Message):
          ...

    When resolving an actual type, MessageField will traverse the
    entire scope of nested messages to match a message name. This
    makes it easy for siblings to reference siblings:

      class Outer(Message):

        class Inner(Message):

          sibling = MessageField('Sibling', 1)

        class Sibling(Message):
          ...

    """

    VARIANTS = frozenset([Variant.MESSAGE])

    DEFAULT_VARIANT = Variant.MESSAGE

    @util.positional(3)
    def __init__(self,
                 message_type,
                 number,
                 required=False,
                 repeated=False,
                 variant=None):
        """Constructor.

        Args:
          message_type: Message type for field.  Must be subclass of Message.
          number: Number of field.  Must be unique per message class.
          required: Whether or not field is required.  Mutually exclusive to
            'repeated'.
          repeated: Whether or not field is rep