diff options
Diffstat (limited to 'python')
-rwxr-xr-x | python/google/protobuf/internal/containers.py | 179 | ||||
-rwxr-xr-x | python/google/protobuf/internal/decoder_test.py | 2 | ||||
-rwxr-xr-x | python/google/protobuf/internal/descriptor_test.py | 2 | ||||
-rwxr-xr-x | python/google/protobuf/internal/encoder_test.py | 2 | ||||
-rwxr-xr-x | python/google/protobuf/internal/generator_test.py | 2 | ||||
-rwxr-xr-x | python/google/protobuf/internal/input_stream_test.py | 2 | ||||
-rwxr-xr-x | python/google/protobuf/internal/output_stream_test.py | 2 | ||||
-rwxr-xr-x | python/google/protobuf/internal/reflection_test.py | 3 | ||||
-rwxr-xr-x | python/google/protobuf/internal/service_reflection_test.py | 2 | ||||
-rwxr-xr-x | python/google/protobuf/internal/text_format_test.py | 2 | ||||
-rwxr-xr-x | python/google/protobuf/internal/wire_format_test.py | 2 | ||||
-rwxr-xr-x | python/google/protobuf/message.py | 2 | ||||
-rwxr-xr-x | python/google/protobuf/reflection.py | 135 | ||||
-rwxr-xr-x | python/setup.py | 1 |
14 files changed, 205 insertions, 133 deletions
diff --git a/python/google/protobuf/internal/containers.py b/python/google/protobuf/internal/containers.py new file mode 100755 index 00000000..982badc8 --- /dev/null +++ b/python/google/protobuf/internal/containers.py @@ -0,0 +1,179 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# http://code.google.com/p/protobuf/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +"""Contains container classes to represent different protocol buffer types. + +This file defines container classes which represent categories of protocol +buffer field types which need extra maintenance. Currently these categories +are: + - Repeated scalar fields - These are all repeated fields which aren't + composite (e.g. they are of simple types like int32, string, etc). + - Repeated composite fields - Repeated fields which are composite. This + includes groups and nested messages. +""" + +__author__ = 'petar@google.com (Petar Petrov)' + + +class BaseContainer(object): + + """Base container class.""" + + # Minimizes memory usage and disallows assignment to other attributes. + __slots__ = ['_message_listener', '_values'] + + def __init__(self, message_listener): + """ + Args: + message_listener: A MessageListener implementation. + The RepeatedScalarFieldContainer will call this object's + TransitionToNonempty() method when it transitions from being empty to + being nonempty. + """ + self._message_listener = message_listener + self._values = [] + + def __getitem__(self, key): + """Retrieves item by the specified key.""" + return self._values[key] + + def __len__(self): + """Returns the number of elements in the container.""" + return len(self._values) + + def __ne__(self, other): + """Checks if another instance isn't equal to this one.""" + # The concrete classes should define __eq__. + return not self == other + + +class RepeatedScalarFieldContainer(BaseContainer): + + """Simple, type-checked, list-like container for holding repeated scalars.""" + + # Disallows assignment to other attributes. + __slots__ = ['_type_checker'] + + def __init__(self, message_listener, type_checker): + """ + Args: + message_listener: A MessageListener implementation. + The RepeatedScalarFieldContainer will call this object's + TransitionToNonempty() method when it transitions from being empty to + being nonempty. + type_checker: A type_checkers.ValueChecker instance to run on elements + inserted into this container. + """ + super(RepeatedScalarFieldContainer, self).__init__(message_listener) + self._type_checker = type_checker + + def append(self, elem): + """Appends a scalar to the list. Similar to list.append().""" + self._type_checker.CheckValue(elem) + self._values.append(elem) + self._message_listener.ByteSizeDirty() + if len(self._values) == 1: + self._message_listener.TransitionToNonempty() + + def remove(self, elem): + """Removes a scalar from the list. Similar to list.remove().""" + self._values.remove(elem) + self._message_listener.ByteSizeDirty() + + def __setitem__(self, key, value): + """Sets the item on the specified position.""" + # No need to call TransitionToNonempty(), since if we're able to + # set the element at this index, we were already nonempty before + # this method was called. + self._message_listener.ByteSizeDirty() + self._type_checker.CheckValue(value) + self._values[key] = value + + def __eq__(self, other): + """Compares the current instance with another one.""" + if self is other: + return True + # Special case for the same type which should be common and fast. + if isinstance(other, self.__class__): + return other._values == self._values + # We are presumably comparing against some other sequence type. + return other == self._values + + +class RepeatedCompositeFieldContainer(BaseContainer): + + """Simple, list-like container for holding repeated composite fields.""" + + # Disallows assignment to other attributes. + __slots__ = ['_message_descriptor'] + + def __init__(self, message_listener, message_descriptor): + """ + Note that we pass in a descriptor instead of the generated directly, + since at the time we construct a _RepeatedCompositeFieldContainer we + haven't yet necessarily initialized the type that will be contained in the + container. + + Args: + message_listener: A MessageListener implementation. + The RepeatedCompositeFieldContainer will call this object's + TransitionToNonempty() method when it transitions from being empty to + being nonempty. + message_descriptor: A Descriptor instance describing the protocol type + that should be present in this container. We'll use the + _concrete_class field of this descriptor when the client calls add(). + """ + super(RepeatedCompositeFieldContainer, self).__init__(message_listener) + self._message_descriptor = message_descriptor + + def add(self): + """Adds a new element to the list and returns it.""" + new_element = self._message_descriptor._concrete_class() + new_element._SetListener(self._message_listener) + self._values.append(new_element) + self._message_listener.ByteSizeDirty() + self._message_listener.TransitionToNonempty() + return new_element + + def __delitem__(self, key): + """Deletes the element on the specified position.""" + self._message_listener.ByteSizeDirty() + del self._values[key] + + def __eq__(self, other): + """Compares the current instance with another one.""" + if self is other: + return True + if not isinstance(other, self.__class__): + raise TypeError('Can only compare repeated composite fields against ' + 'other repeated composite fields.') + return self._values == other._values + + # TODO(robinson): Implement, document, and test slicing support. diff --git a/python/google/protobuf/internal/decoder_test.py b/python/google/protobuf/internal/decoder_test.py index e020f8dc..abcc07fc 100755 --- a/python/google/protobuf/internal/decoder_test.py +++ b/python/google/protobuf/internal/decoder_test.py @@ -1,3 +1,5 @@ +#! /usr/bin/python +# # Protocol Buffers - Google's data interchange format # Copyright 2008 Google Inc. All rights reserved. # http://code.google.com/p/protobuf/ diff --git a/python/google/protobuf/internal/descriptor_test.py b/python/google/protobuf/internal/descriptor_test.py index eecf09ba..eb9f2be8 100755 --- a/python/google/protobuf/internal/descriptor_test.py +++ b/python/google/protobuf/internal/descriptor_test.py @@ -1,3 +1,5 @@ +#! /usr/bin/python +# # Protocol Buffers - Google's data interchange format # Copyright 2008 Google Inc. All rights reserved. # http://code.google.com/p/protobuf/ diff --git a/python/google/protobuf/internal/encoder_test.py b/python/google/protobuf/internal/encoder_test.py index 4a0c3d23..61668223 100755 --- a/python/google/protobuf/internal/encoder_test.py +++ b/python/google/protobuf/internal/encoder_test.py @@ -1,3 +1,5 @@ +#! /usr/bin/python +# # Protocol Buffers - Google's data interchange format # Copyright 2008 Google Inc. All rights reserved. # http://code.google.com/p/protobuf/ diff --git a/python/google/protobuf/internal/generator_test.py b/python/google/protobuf/internal/generator_test.py index ce22f2bc..11fcfa0c 100755 --- a/python/google/protobuf/internal/generator_test.py +++ b/python/google/protobuf/internal/generator_test.py @@ -1,3 +1,5 @@ +#! /usr/bin/python +# # Protocol Buffers - Google's data interchange format # Copyright 2008 Google Inc. All rights reserved. # http://code.google.com/p/protobuf/ diff --git a/python/google/protobuf/internal/input_stream_test.py b/python/google/protobuf/internal/input_stream_test.py index d96a14c6..8cc1d126 100755 --- a/python/google/protobuf/internal/input_stream_test.py +++ b/python/google/protobuf/internal/input_stream_test.py @@ -1,3 +1,5 @@ +#! /usr/bin/python +# # Protocol Buffers - Google's data interchange format # Copyright 2008 Google Inc. All rights reserved. # http://code.google.com/p/protobuf/ diff --git a/python/google/protobuf/internal/output_stream_test.py b/python/google/protobuf/internal/output_stream_test.py index 36da5327..df92eecd 100755 --- a/python/google/protobuf/internal/output_stream_test.py +++ b/python/google/protobuf/internal/output_stream_test.py @@ -1,3 +1,5 @@ +#! /usr/bin/python +# # Protocol Buffers - Google's data interchange format # Copyright 2008 Google Inc. All rights reserved. # http://code.google.com/p/protobuf/ diff --git a/python/google/protobuf/internal/reflection_test.py b/python/google/protobuf/internal/reflection_test.py index c8e60005..c2ca5132 100755 --- a/python/google/protobuf/internal/reflection_test.py +++ b/python/google/protobuf/internal/reflection_test.py @@ -1,5 +1,6 @@ +#! /usr/bin/python # -*- coding: utf-8 -*- - +# # Protocol Buffers - Google's data interchange format # Copyright 2008 Google Inc. All rights reserved. # http://code.google.com/p/protobuf/ diff --git a/python/google/protobuf/internal/service_reflection_test.py b/python/google/protobuf/internal/service_reflection_test.py index 00a36af6..29492e16 100755 --- a/python/google/protobuf/internal/service_reflection_test.py +++ b/python/google/protobuf/internal/service_reflection_test.py @@ -1,3 +1,5 @@ +#! /usr/bin/python +# # Protocol Buffers - Google's data interchange format # Copyright 2008 Google Inc. All rights reserved. # http://code.google.com/p/protobuf/ diff --git a/python/google/protobuf/internal/text_format_test.py b/python/google/protobuf/internal/text_format_test.py index c48760e2..871590e7 100755 --- a/python/google/protobuf/internal/text_format_test.py +++ b/python/google/protobuf/internal/text_format_test.py @@ -1,3 +1,5 @@ +#! /usr/bin/python +# # Protocol Buffers - Google's data interchange format # Copyright 2008 Google Inc. All rights reserved. # http://code.google.com/p/protobuf/ diff --git a/python/google/protobuf/internal/wire_format_test.py b/python/google/protobuf/internal/wire_format_test.py index 4f6078f2..76007786 100755 --- a/python/google/protobuf/internal/wire_format_test.py +++ b/python/google/protobuf/internal/wire_format_test.py @@ -1,3 +1,5 @@ +#! /usr/bin/python +# # Protocol Buffers - Google's data interchange format # Copyright 2008 Google Inc. All rights reserved. # http://code.google.com/p/protobuf/ diff --git a/python/google/protobuf/message.py b/python/google/protobuf/message.py index 83779b15..4da024ca 100755 --- a/python/google/protobuf/message.py +++ b/python/google/protobuf/message.py @@ -198,7 +198,7 @@ class Message(object): # Typically (in python), an underscore is appended to names that are # keywords. So they would become lambda_ or yield_. # """ - def ListFields(self, field_name): + def ListFields(self): """Returns a list of (FieldDescriptor, value) tuples for all fields in the message which are not empty. A singular field is non-empty if HasField() would return true, and a repeated field is non-empty if diff --git a/python/google/protobuf/reflection.py b/python/google/protobuf/reflection.py index d80942e8..c35742ce 100755 --- a/python/google/protobuf/reflection.py +++ b/python/google/protobuf/reflection.py @@ -54,6 +54,7 @@ import heapq import threading import weakref # We use "as" to avoid name collisions with variables. +from google.protobuf.internal import containers from google.protobuf.internal import decoder from google.protobuf.internal import encoder from google.protobuf.internal import message_listener as message_listener_mod @@ -274,9 +275,10 @@ def _DefaultValueForField(message, field): if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: # We can't look at _concrete_class yet since it might not have # been set. (Depends on order in which we initialize the classes). - return _RepeatedCompositeFieldContainer(listener, field.message_type) + return containers.RepeatedCompositeFieldContainer( + listener, field.message_type) else: - return _RepeatedScalarFieldContainer( + return containers.RepeatedScalarFieldContainer( listener, type_checkers.GetTypeChecker(field.cpp_type, field.type)) if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: @@ -1270,135 +1272,6 @@ class _Listener(object): pass -# TODO(robinson): Move elsewhere? -# TODO(robinson): Provide a clear() method here in addition to ClearField()? -class _RepeatedScalarFieldContainer(object): - - """Simple, type-checked, list-like container for holding repeated scalars.""" - - # Minimizes memory usage and disallows assignment to other attributes. - __slots__ = ['_message_listener', '_type_checker', '_values'] - - def __init__(self, message_listener, type_checker): - """ - Args: - message_listener: A MessageListener implementation. - The _RepeatedScalarFieldContaininer will call this object's - TransitionToNonempty() method when it transitions from being empty to - being nonempty. - type_checker: A _ValueChecker instance to run on elements inserted - into this container. - """ - self._message_listener = message_listener - self._type_checker = type_checker - self._values = [] - - def append(self, elem): - self._type_checker.CheckValue(elem) - self._values.append(elem) - self._message_listener.ByteSizeDirty() - if len(self._values) == 1: - self._message_listener.TransitionToNonempty() - - def remove(self, elem): - self._values.remove(elem) - self._message_listener.ByteSizeDirty() - - # List-like __getitem__() support also makes us iterable (via "iter(foo)" - # or implicitly via "for i in mylist:") for free. - def __getitem__(self, key): - return self._values[key] - - def __setitem__(self, key, value): - # No need to call TransitionToNonempty(), since if we're able to - # set the element at this index, we were already nonempty before - # this method was called. - self._message_listener.ByteSizeDirty() - self._type_checker.CheckValue(value) - self._values[key] = value - - def __len__(self): - return len(self._values) - - def __eq__(self, other): - if self is other: - return True - # Special case for the same type which should be common and fast. - if isinstance(other, self.__class__): - return other._values == self._values - # We are presumably comparing against some other sequence type. - return other == self._values - - def __ne__(self, other): - # Can't use != here since it would infinitely recurse. - return not self == other - - -# TODO(robinson): Move elsewhere? -# TODO(robinson): Provide a clear() method here in addition to ClearField()? -# TODO(robinson): Unify common functionality with -# _RepeatedScalarFieldContaininer? -class _RepeatedCompositeFieldContainer(object): - - """Simple, list-like container for holding repeated composite fields.""" - - # Minimizes memory usage and disallows assignment to other attributes. - __slots__ = ['_values', '_message_descriptor', '_message_listener'] - - def __init__(self, message_listener, message_descriptor): - """Note that we pass in a descriptor instead of the generated directly, - since at the time we construct a _RepeatedCompositeFieldContainer we - haven't yet necessarily initialized the type that will be contained in the - container. - - Args: - message_listener: A MessageListener implementation. - The _RepeatedCompositeFieldContainer will call this object's - TransitionToNonempty() method when it transitions from being empty to - being nonempty. - message_descriptor: A Descriptor instance describing the protocol type - that should be present in this container. We'll use the - _concrete_class field of this descriptor when the client calls add(). - """ - self._message_listener = message_listener - self._message_descriptor = message_descriptor - self._values = [] - - def add(self): - new_element = self._message_descriptor._concrete_class() - new_element._SetListener(self._message_listener) - self._values.append(new_element) - self._message_listener.ByteSizeDirty() - self._message_listener.TransitionToNonempty() - return new_element - - def __delitem__(self, key): - self._message_listener.ByteSizeDirty() - del self._values[key] - - # List-like __getitem__() support also makes us iterable (via "iter(foo)" - # or implicitly via "for i in mylist:") for free. - def __getitem__(self, key): - return self._values[key] - - def __len__(self): - return len(self._values) - - def __eq__(self, other): - if self is other: - return True - if not isinstance(other, self.__class__): - raise TypeError('Can only compare repeated composite fields against ' - 'other repeated composite fields.') - return self._values == other._values - - def __ne__(self, other): - # Can't use != here since it would infinitely recurse. - return not self == other - - # TODO(robinson): Implement, document, and test slicing support. - - # TODO(robinson): Move elsewhere? This file is getting pretty ridiculous... # TODO(robinson): Unify error handling of "unknown extension" crap. # TODO(robinson): There's so much similarity between the way that diff --git a/python/setup.py b/python/setup.py index f0ee329d..cda2c0eb 100755 --- a/python/setup.py +++ b/python/setup.py @@ -108,6 +108,7 @@ if __name__ == '__main__': test_suite = 'setup.MakeTestSuite', # Must list modules explicitly so that we don't install tests. py_modules = [ + 'google.protobuf.internal.containers', 'google.protobuf.internal.decoder', 'google.protobuf.internal.encoder', 'google.protobuf.internal.input_stream', |