~ubuntu-branches/debian/sid/protobuf/sid

« back to all changes in this revision

Viewing changes to python/google/protobuf/internal/containers.py

  • Committer: Bazaar Package Importer
  • Author(s): Julien Cristau
  • Date: 2009-06-02 16:19:00 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20090602161900-vm176i3ryt35yk91
Tags: 2.0.3-2.2
* Non-maintainer upload.
* Fix FTBFS from -2.1: don't fail when we can't clean up the java build,
  such as when openjdk isn't installed.
* Disable parallel builds, because libtool is made of fail (if binary-arch
  and build-indep run concurrently, we relink a library while it's being
  used; that doesn't work so well).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Protocol Buffers - Google's data interchange format
 
2
# Copyright 2008 Google Inc.  All rights reserved.
 
3
# http://code.google.com/p/protobuf/
 
4
#
 
5
# Redistribution and use in source and binary forms, with or without
 
6
# modification, are permitted provided that the following conditions are
 
7
# met:
 
8
#
 
9
#     * Redistributions of source code must retain the above copyright
 
10
# notice, this list of conditions and the following disclaimer.
 
11
#     * Redistributions in binary form must reproduce the above
 
12
# copyright notice, this list of conditions and the following disclaimer
 
13
# in the documentation and/or other materials provided with the
 
14
# distribution.
 
15
#     * Neither the name of Google Inc. nor the names of its
 
16
# contributors may be used to endorse or promote products derived from
 
17
# this software without specific prior written permission.
 
18
#
 
19
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 
20
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 
21
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 
22
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 
23
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 
24
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 
25
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 
26
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 
27
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 
28
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 
29
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
30
 
 
31
"""Contains container classes to represent different protocol buffer types.
 
32
 
 
33
This file defines container classes which represent categories of protocol
 
34
buffer field types which need extra maintenance. Currently these categories
 
35
are:
 
36
  - Repeated scalar fields - These are all repeated fields which aren't
 
37
    composite (e.g. they are of simple types like int32, string, etc).
 
38
  - Repeated composite fields - Repeated fields which are composite. This
 
39
    includes groups and nested messages.
 
40
"""
 
41
 
 
42
__author__ = 'petar@google.com (Petar Petrov)'
 
43
 
 
44
 
 
45
class BaseContainer(object):
 
46
 
 
47
  """Base container class."""
 
48
 
 
49
  # Minimizes memory usage and disallows assignment to other attributes.
 
50
  __slots__ = ['_message_listener', '_values']
 
51
 
 
52
  def __init__(self, message_listener):
 
53
    """
 
54
    Args:
 
55
      message_listener: A MessageListener implementation.
 
56
        The RepeatedScalarFieldContainer will call this object's
 
57
        TransitionToNonempty() method when it transitions from being empty to
 
58
        being nonempty.
 
59
    """
 
60
    self._message_listener = message_listener
 
61
    self._values = []
 
62
 
 
63
  def __getitem__(self, key):
 
64
    """Retrieves item by the specified key."""
 
65
    return self._values[key]
 
66
 
 
67
  def __len__(self):
 
68
    """Returns the number of elements in the container."""
 
69
    return len(self._values)
 
70
 
 
71
  def __ne__(self, other):
 
72
    """Checks if another instance isn't equal to this one."""
 
73
    # The concrete classes should define __eq__.
 
74
    return not self == other
 
75
 
 
76
 
 
77
class RepeatedScalarFieldContainer(BaseContainer):
 
78
 
 
79
  """Simple, type-checked, list-like container for holding repeated scalars."""
 
80
 
 
81
  # Disallows assignment to other attributes.
 
82
  __slots__ = ['_type_checker']
 
83
 
 
84
  def __init__(self, message_listener, type_checker):
 
85
    """
 
86
    Args:
 
87
      message_listener: A MessageListener implementation.
 
88
        The RepeatedScalarFieldContainer will call this object's
 
89
        TransitionToNonempty() method when it transitions from being empty to
 
90
        being nonempty.
 
91
      type_checker: A type_checkers.ValueChecker instance to run on elements
 
92
        inserted into this container.
 
93
    """
 
94
    super(RepeatedScalarFieldContainer, self).__init__(message_listener)
 
95
    self._type_checker = type_checker
 
96
 
 
97
  def append(self, elem):
 
98
    """Appends a scalar to the list. Similar to list.append()."""
 
99
    self._type_checker.CheckValue(elem)
 
100
    self._values.append(elem)
 
101
    self._message_listener.ByteSizeDirty()
 
102
    if len(self._values) == 1:
 
103
      self._message_listener.TransitionToNonempty()
 
104
 
 
105
  def remove(self, elem):
 
106
    """Removes a scalar from the list. Similar to list.remove()."""
 
107
    self._values.remove(elem)
 
108
    self._message_listener.ByteSizeDirty()
 
109
 
 
110
  def __setitem__(self, key, value):
 
111
    """Sets the item on the specified position."""
 
112
    # No need to call TransitionToNonempty(), since if we're able to
 
113
    # set the element at this index, we were already nonempty before
 
114
    # this method was called.
 
115
    self._message_listener.ByteSizeDirty()
 
116
    self._type_checker.CheckValue(value)
 
117
    self._values[key] = value
 
118
 
 
119
  def __eq__(self, other):
 
120
    """Compares the current instance with another one."""
 
121
    if self is other:
 
122
      return True
 
123
    # Special case for the same type which should be common and fast.
 
124
    if isinstance(other, self.__class__):
 
125
      return other._values == self._values
 
126
    # We are presumably comparing against some other sequence type.
 
127
    return other == self._values
 
128
 
 
129
 
 
130
class RepeatedCompositeFieldContainer(BaseContainer):
 
131
 
 
132
  """Simple, list-like container for holding repeated composite fields."""
 
133
 
 
134
  # Disallows assignment to other attributes.
 
135
  __slots__ = ['_message_descriptor']
 
136
 
 
137
  def __init__(self, message_listener, message_descriptor):
 
138
    """
 
139
    Note that we pass in a descriptor instead of the generated directly,
 
140
    since at the time we construct a _RepeatedCompositeFieldContainer we
 
141
    haven't yet necessarily initialized the type that will be contained in the
 
142
    container.
 
143
 
 
144
    Args:
 
145
      message_listener: A MessageListener implementation.
 
146
        The RepeatedCompositeFieldContainer will call this object's
 
147
        TransitionToNonempty() method when it transitions from being empty to
 
148
        being nonempty.
 
149
      message_descriptor: A Descriptor instance describing the protocol type
 
150
        that should be present in this container.  We'll use the
 
151
        _concrete_class field of this descriptor when the client calls add().
 
152
    """
 
153
    super(RepeatedCompositeFieldContainer, self).__init__(message_listener)
 
154
    self._message_descriptor = message_descriptor
 
155
 
 
156
  def add(self):
 
157
    """Adds a new element to the list and returns it."""
 
158
    new_element = self._message_descriptor._concrete_class()
 
159
    new_element._SetListener(self._message_listener)
 
160
    self._values.append(new_element)
 
161
    self._message_listener.ByteSizeDirty()
 
162
    self._message_listener.TransitionToNonempty()
 
163
    return new_element
 
164
 
 
165
  def __delitem__(self, key):
 
166
    """Deletes the element on the specified position."""
 
167
    self._message_listener.ByteSizeDirty()
 
168
    del self._values[key]
 
169
 
 
170
  def __eq__(self, other):
 
171
    """Compares the current instance with another one."""
 
172
    if self is other:
 
173
      return True
 
174
    if not isinstance(other, self.__class__):
 
175
      raise TypeError('Can only compare repeated composite fields against '
 
176
                      'other repeated composite fields.')
 
177
    return self._values == other._values
 
178
 
 
179
  # TODO(robinson): Implement, document, and test slicing support.