extension_dict.py
Go to the documentation of this file.
1 # Protocol Buffers - Google's data interchange format
2 # Copyright 2008 Google Inc. All rights reserved.
3 # https://developers.google.com/protocol-buffers/
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 _ExtensionDict class to represent extensions.
32 """
33 
34 from google.protobuf.internal import type_checkers
35 from google.protobuf.descriptor import FieldDescriptor
36 
37 
38 def _VerifyExtensionHandle(message, extension_handle):
39  """Verify that the given extension handle is valid."""
40 
41  if not isinstance(extension_handle, FieldDescriptor):
42  raise KeyError('HasExtension() expects an extension handle, got: %s' %
43  extension_handle)
44 
45  if not extension_handle.is_extension:
46  raise KeyError('"%s" is not an extension.' % extension_handle.full_name)
47 
48  if not extension_handle.containing_type:
49  raise KeyError('"%s" is missing a containing_type.'
50  % extension_handle.full_name)
51 
52  if extension_handle.containing_type is not message.DESCRIPTOR:
53  raise KeyError('Extension "%s" extends message type "%s", but this '
54  'message is of type "%s".' %
55  (extension_handle.full_name,
56  extension_handle.containing_type.full_name,
57  message.DESCRIPTOR.full_name))
58 
59 
60 # TODO(robinson): Unify error handling of "unknown extension" crap.
61 # TODO(robinson): Support iteritems()-style iteration over all
62 # extensions with the "has" bits turned on?
63 class _ExtensionDict(object):
64 
65  """Dict-like container for Extension fields on proto instances.
66 
67  Note that in all cases we expect extension handles to be
68  FieldDescriptors.
69  """
70 
71  def __init__(self, extended_message):
72  """
73  Args:
74  extended_message: Message instance for which we are the Extensions dict.
75  """
76  self._extended_message = extended_message
77 
78  def __getitem__(self, extension_handle):
79  """Returns the current value of the given extension handle."""
80 
81  _VerifyExtensionHandle(self._extended_message, extension_handle)
82 
83  result = self._extended_message._fields.get(extension_handle)
84  if result is not None:
85  return result
86 
87  if extension_handle.label == FieldDescriptor.LABEL_REPEATED:
88  result = extension_handle._default_constructor(self._extended_message)
89  elif extension_handle.cpp_type == FieldDescriptor.CPPTYPE_MESSAGE:
90  assert getattr(extension_handle.message_type, '_concrete_class', None), (
91  'Uninitialized concrete class found for field %r (message type %r)'
92  % (extension_handle.full_name,
93  extension_handle.message_type.full_name))
94  result = extension_handle.message_type._concrete_class()
95  try:
96  result._SetListener(self._extended_message._listener_for_children)
97  except ReferenceError:
98  pass
99  else:
100  # Singular scalar -- just return the default without inserting into the
101  # dict.
102  return extension_handle.default_value
103 
104  # Atomically check if another thread has preempted us and, if not, swap
105  # in the new object we just created. If someone has preempted us, we
106  # take that object and discard ours.
107  # WARNING: We are relying on setdefault() being atomic. This is true
108  # in CPython but we haven't investigated others. This warning appears
109  # in several other locations in this file.
110  result = self._extended_message._fields.setdefault(
111  extension_handle, result)
112 
113  return result
114 
115  def __eq__(self, other):
116  if not isinstance(other, self.__class__):
117  return False
118 
119  my_fields = self._extended_message.ListFields()
120  other_fields = other._extended_message.ListFields()
121 
122  # Get rid of non-extension fields.
123  my_fields = [field for field in my_fields if field.is_extension]
124  other_fields = [field for field in other_fields if field.is_extension]
125 
126  return my_fields == other_fields
127 
128  def __ne__(self, other):
129  return not self == other
130 
131  def __len__(self):
132  fields = self._extended_message.ListFields()
133  # Get rid of non-extension fields.
134  extension_fields = [field for field in fields if field[0].is_extension]
135  return len(extension_fields)
136 
137  def __hash__(self):
138  raise TypeError('unhashable object')
139 
140  # Note that this is only meaningful for non-repeated, scalar extension
141  # fields. Note also that we may have to call _Modified() when we do
142  # successfully set a field this way, to set any necssary "has" bits in the
143  # ancestors of the extended message.
144  def __setitem__(self, extension_handle, value):
145  """If extension_handle specifies a non-repeated, scalar extension
146  field, sets the value of that field.
147  """
148 
149  _VerifyExtensionHandle(self._extended_message, extension_handle)
150 
151  if (extension_handle.label == FieldDescriptor.LABEL_REPEATED or
152  extension_handle.cpp_type == FieldDescriptor.CPPTYPE_MESSAGE):
153  raise TypeError(
154  'Cannot assign to extension "%s" because it is a repeated or '
155  'composite type.' % extension_handle.full_name)
156 
157  # It's slightly wasteful to lookup the type checker each time,
158  # but we expect this to be a vanishingly uncommon case anyway.
159  type_checker = type_checkers.GetTypeChecker(extension_handle)
160  # pylint: disable=protected-access
161  self._extended_message._fields[extension_handle] = (
162  type_checker.CheckValue(value))
164 
165  def _FindExtensionByName(self, name):
166  """Tries to find a known extension with the specified name.
167 
168  Args:
169  name: Extension full name.
170 
171  Returns:
172  Extension field descriptor.
173  """
174  return self._extended_message._extensions_by_name.get(name, None)
175 
176  def _FindExtensionByNumber(self, number):
177  """Tries to find a known extension with the field number.
178 
179  Args:
180  number: Extension field number.
181 
182  Returns:
183  Extension field descriptor.
184  """
185  return self._extended_message._extensions_by_number.get(number, None)
186 
187  def __iter__(self):
188  # Return a generator over the populated extension fields
189  return (f[0] for f in self._extended_message.ListFields()
190  if f[0].is_extension)
191 
192  def __contains__(self, extension_handle):
193  _VerifyExtensionHandle(self._extended_message, extension_handle)
194 
195  if extension_handle not in self._extended_message._fields:
196  return False
197 
198  if extension_handle.label == FieldDescriptor.LABEL_REPEATED:
199  return bool(self._extended_message._fields.get(extension_handle))
200 
201  if extension_handle.cpp_type == FieldDescriptor.CPPTYPE_MESSAGE:
202  value = self._extended_message._fields.get(extension_handle)
203  # pylint: disable=protected-access
204  return value is not None and value._is_present_in_parent
205 
206  return True
google::protobuf.internal.extension_dict._VerifyExtensionHandle
def _VerifyExtensionHandle(message, extension_handle)
Definition: extension_dict.py:38
getattr
static uint64_t getattr(const tarjan *t, const upb_refcounted *r)
Definition: ruby/ext/google/protobuf_c/upb.c:5868
google::protobuf.internal.extension_dict._ExtensionDict.__init__
def __init__(self, extended_message)
Definition: extension_dict.py:71
google::protobuf.descriptor
Definition: descriptor.py:1
google::protobuf.internal.extension_dict._ExtensionDict._FindExtensionByNumber
def _FindExtensionByNumber(self, number)
Definition: extension_dict.py:176
google::protobuf.internal.extension_dict._ExtensionDict._FindExtensionByName
def _FindExtensionByName(self, name)
Definition: extension_dict.py:165
google::protobuf.internal.extension_dict._ExtensionDict.__getitem__
def __getitem__(self, extension_handle)
Definition: extension_dict.py:78
google::protobuf.internal.extension_dict._ExtensionDict._extended_message
_extended_message
Definition: extension_dict.py:76
google::protobuf.internal.extension_dict._ExtensionDict.__eq__
def __eq__(self, other)
Definition: extension_dict.py:115
google::protobuf.internal.extension_dict._ExtensionDict.__setitem__
def __setitem__(self, extension_handle, value)
Definition: extension_dict.py:144
google::protobuf.internal
Definition: python/google/protobuf/internal/__init__.py:1
google::protobuf.internal.extension_dict._ExtensionDict.__ne__
def __ne__(self, other)
Definition: extension_dict.py:128
google::protobuf.internal.python_message._Modified
_Modified
Definition: python_message.py:1466
google::protobuf.internal.extension_dict._ExtensionDict.__len__
def __len__(self)
Definition: extension_dict.py:131
google::protobuf.internal.python_message.ListFields
ListFields
Definition: python_message.py:819
google::protobuf.internal.extension_dict._ExtensionDict.__contains__
def __contains__(self, extension_handle)
Definition: extension_dict.py:192
len
int len
Definition: php/ext/google/protobuf/map.c:206
google::protobuf.internal.extension_dict._ExtensionDict
Definition: extension_dict.py:63
google::protobuf.internal.extension_dict._ExtensionDict.__iter__
def __iter__(self)
Definition: extension_dict.py:187
google::protobuf.internal.extension_dict._ExtensionDict.__hash__
def __hash__(self)
Definition: extension_dict.py:137


libaditof
Author(s):
autogenerated on Wed May 21 2025 02:06:51