1*1b3f573fSAndroid Build Coastguard Worker# Protocol Buffers - Google's data interchange format 2*1b3f573fSAndroid Build Coastguard Worker# Copyright 2008 Google Inc. All rights reserved. 3*1b3f573fSAndroid Build Coastguard Worker# https://developers.google.com/protocol-buffers/ 4*1b3f573fSAndroid Build Coastguard Worker# 5*1b3f573fSAndroid Build Coastguard Worker# Redistribution and use in source and binary forms, with or without 6*1b3f573fSAndroid Build Coastguard Worker# modification, are permitted provided that the following conditions are 7*1b3f573fSAndroid Build Coastguard Worker# met: 8*1b3f573fSAndroid Build Coastguard Worker# 9*1b3f573fSAndroid Build Coastguard Worker# * Redistributions of source code must retain the above copyright 10*1b3f573fSAndroid Build Coastguard Worker# notice, this list of conditions and the following disclaimer. 11*1b3f573fSAndroid Build Coastguard Worker# * Redistributions in binary form must reproduce the above 12*1b3f573fSAndroid Build Coastguard Worker# copyright notice, this list of conditions and the following disclaimer 13*1b3f573fSAndroid Build Coastguard Worker# in the documentation and/or other materials provided with the 14*1b3f573fSAndroid Build Coastguard Worker# distribution. 15*1b3f573fSAndroid Build Coastguard Worker# * Neither the name of Google Inc. nor the names of its 16*1b3f573fSAndroid Build Coastguard Worker# contributors may be used to endorse or promote products derived from 17*1b3f573fSAndroid Build Coastguard Worker# this software without specific prior written permission. 18*1b3f573fSAndroid Build Coastguard Worker# 19*1b3f573fSAndroid Build Coastguard Worker# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20*1b3f573fSAndroid Build Coastguard Worker# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21*1b3f573fSAndroid Build Coastguard Worker# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22*1b3f573fSAndroid Build Coastguard Worker# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23*1b3f573fSAndroid Build Coastguard Worker# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24*1b3f573fSAndroid Build Coastguard Worker# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25*1b3f573fSAndroid Build Coastguard Worker# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26*1b3f573fSAndroid Build Coastguard Worker# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27*1b3f573fSAndroid Build Coastguard Worker# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28*1b3f573fSAndroid Build Coastguard Worker# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29*1b3f573fSAndroid Build Coastguard Worker# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30*1b3f573fSAndroid Build Coastguard Worker 31*1b3f573fSAndroid Build Coastguard Worker"""Contains container classes to represent different protocol buffer types. 32*1b3f573fSAndroid Build Coastguard Worker 33*1b3f573fSAndroid Build Coastguard WorkerThis file defines container classes which represent categories of protocol 34*1b3f573fSAndroid Build Coastguard Workerbuffer field types which need extra maintenance. Currently these categories 35*1b3f573fSAndroid Build Coastguard Workerare: 36*1b3f573fSAndroid Build Coastguard Worker 37*1b3f573fSAndroid Build Coastguard Worker- Repeated scalar fields - These are all repeated fields which aren't 38*1b3f573fSAndroid Build Coastguard Worker composite (e.g. they are of simple types like int32, string, etc). 39*1b3f573fSAndroid Build Coastguard Worker- Repeated composite fields - Repeated fields which are composite. This 40*1b3f573fSAndroid Build Coastguard Worker includes groups and nested messages. 41*1b3f573fSAndroid Build Coastguard Worker""" 42*1b3f573fSAndroid Build Coastguard Worker 43*1b3f573fSAndroid Build Coastguard Workerimport collections.abc 44*1b3f573fSAndroid Build Coastguard Workerimport copy 45*1b3f573fSAndroid Build Coastguard Workerimport pickle 46*1b3f573fSAndroid Build Coastguard Workerfrom typing import ( 47*1b3f573fSAndroid Build Coastguard Worker Any, 48*1b3f573fSAndroid Build Coastguard Worker Iterable, 49*1b3f573fSAndroid Build Coastguard Worker Iterator, 50*1b3f573fSAndroid Build Coastguard Worker List, 51*1b3f573fSAndroid Build Coastguard Worker MutableMapping, 52*1b3f573fSAndroid Build Coastguard Worker MutableSequence, 53*1b3f573fSAndroid Build Coastguard Worker NoReturn, 54*1b3f573fSAndroid Build Coastguard Worker Optional, 55*1b3f573fSAndroid Build Coastguard Worker Sequence, 56*1b3f573fSAndroid Build Coastguard Worker TypeVar, 57*1b3f573fSAndroid Build Coastguard Worker Union, 58*1b3f573fSAndroid Build Coastguard Worker overload, 59*1b3f573fSAndroid Build Coastguard Worker) 60*1b3f573fSAndroid Build Coastguard Worker 61*1b3f573fSAndroid Build Coastguard Worker 62*1b3f573fSAndroid Build Coastguard Worker_T = TypeVar('_T') 63*1b3f573fSAndroid Build Coastguard Worker_K = TypeVar('_K') 64*1b3f573fSAndroid Build Coastguard Worker_V = TypeVar('_V') 65*1b3f573fSAndroid Build Coastguard Worker 66*1b3f573fSAndroid Build Coastguard Worker 67*1b3f573fSAndroid Build Coastguard Workerclass BaseContainer(Sequence[_T]): 68*1b3f573fSAndroid Build Coastguard Worker """Base container class.""" 69*1b3f573fSAndroid Build Coastguard Worker 70*1b3f573fSAndroid Build Coastguard Worker # Minimizes memory usage and disallows assignment to other attributes. 71*1b3f573fSAndroid Build Coastguard Worker __slots__ = ['_message_listener', '_values'] 72*1b3f573fSAndroid Build Coastguard Worker 73*1b3f573fSAndroid Build Coastguard Worker def __init__(self, message_listener: Any) -> None: 74*1b3f573fSAndroid Build Coastguard Worker """ 75*1b3f573fSAndroid Build Coastguard Worker Args: 76*1b3f573fSAndroid Build Coastguard Worker message_listener: A MessageListener implementation. 77*1b3f573fSAndroid Build Coastguard Worker The RepeatedScalarFieldContainer will call this object's 78*1b3f573fSAndroid Build Coastguard Worker Modified() method when it is modified. 79*1b3f573fSAndroid Build Coastguard Worker """ 80*1b3f573fSAndroid Build Coastguard Worker self._message_listener = message_listener 81*1b3f573fSAndroid Build Coastguard Worker self._values = [] 82*1b3f573fSAndroid Build Coastguard Worker 83*1b3f573fSAndroid Build Coastguard Worker @overload 84*1b3f573fSAndroid Build Coastguard Worker def __getitem__(self, key: int) -> _T: 85*1b3f573fSAndroid Build Coastguard Worker ... 86*1b3f573fSAndroid Build Coastguard Worker 87*1b3f573fSAndroid Build Coastguard Worker @overload 88*1b3f573fSAndroid Build Coastguard Worker def __getitem__(self, key: slice) -> List[_T]: 89*1b3f573fSAndroid Build Coastguard Worker ... 90*1b3f573fSAndroid Build Coastguard Worker 91*1b3f573fSAndroid Build Coastguard Worker def __getitem__(self, key): 92*1b3f573fSAndroid Build Coastguard Worker """Retrieves item by the specified key.""" 93*1b3f573fSAndroid Build Coastguard Worker return self._values[key] 94*1b3f573fSAndroid Build Coastguard Worker 95*1b3f573fSAndroid Build Coastguard Worker def __len__(self) -> int: 96*1b3f573fSAndroid Build Coastguard Worker """Returns the number of elements in the container.""" 97*1b3f573fSAndroid Build Coastguard Worker return len(self._values) 98*1b3f573fSAndroid Build Coastguard Worker 99*1b3f573fSAndroid Build Coastguard Worker def __ne__(self, other: Any) -> bool: 100*1b3f573fSAndroid Build Coastguard Worker """Checks if another instance isn't equal to this one.""" 101*1b3f573fSAndroid Build Coastguard Worker # The concrete classes should define __eq__. 102*1b3f573fSAndroid Build Coastguard Worker return not self == other 103*1b3f573fSAndroid Build Coastguard Worker 104*1b3f573fSAndroid Build Coastguard Worker __hash__ = None 105*1b3f573fSAndroid Build Coastguard Worker 106*1b3f573fSAndroid Build Coastguard Worker def __repr__(self) -> str: 107*1b3f573fSAndroid Build Coastguard Worker return repr(self._values) 108*1b3f573fSAndroid Build Coastguard Worker 109*1b3f573fSAndroid Build Coastguard Worker def sort(self, *args, **kwargs) -> None: 110*1b3f573fSAndroid Build Coastguard Worker # Continue to support the old sort_function keyword argument. 111*1b3f573fSAndroid Build Coastguard Worker # This is expected to be a rare occurrence, so use LBYL to avoid 112*1b3f573fSAndroid Build Coastguard Worker # the overhead of actually catching KeyError. 113*1b3f573fSAndroid Build Coastguard Worker if 'sort_function' in kwargs: 114*1b3f573fSAndroid Build Coastguard Worker kwargs['cmp'] = kwargs.pop('sort_function') 115*1b3f573fSAndroid Build Coastguard Worker self._values.sort(*args, **kwargs) 116*1b3f573fSAndroid Build Coastguard Worker 117*1b3f573fSAndroid Build Coastguard Worker def reverse(self) -> None: 118*1b3f573fSAndroid Build Coastguard Worker self._values.reverse() 119*1b3f573fSAndroid Build Coastguard Worker 120*1b3f573fSAndroid Build Coastguard Worker 121*1b3f573fSAndroid Build Coastguard Worker# TODO(slebedev): Remove this. BaseContainer does *not* conform to 122*1b3f573fSAndroid Build Coastguard Worker# MutableSequence, only its subclasses do. 123*1b3f573fSAndroid Build Coastguard Workercollections.abc.MutableSequence.register(BaseContainer) 124*1b3f573fSAndroid Build Coastguard Worker 125*1b3f573fSAndroid Build Coastguard Worker 126*1b3f573fSAndroid Build Coastguard Workerclass RepeatedScalarFieldContainer(BaseContainer[_T], MutableSequence[_T]): 127*1b3f573fSAndroid Build Coastguard Worker """Simple, type-checked, list-like container for holding repeated scalars.""" 128*1b3f573fSAndroid Build Coastguard Worker 129*1b3f573fSAndroid Build Coastguard Worker # Disallows assignment to other attributes. 130*1b3f573fSAndroid Build Coastguard Worker __slots__ = ['_type_checker'] 131*1b3f573fSAndroid Build Coastguard Worker 132*1b3f573fSAndroid Build Coastguard Worker def __init__( 133*1b3f573fSAndroid Build Coastguard Worker self, 134*1b3f573fSAndroid Build Coastguard Worker message_listener: Any, 135*1b3f573fSAndroid Build Coastguard Worker type_checker: Any, 136*1b3f573fSAndroid Build Coastguard Worker ) -> None: 137*1b3f573fSAndroid Build Coastguard Worker """Args: 138*1b3f573fSAndroid Build Coastguard Worker 139*1b3f573fSAndroid Build Coastguard Worker message_listener: A MessageListener implementation. The 140*1b3f573fSAndroid Build Coastguard Worker RepeatedScalarFieldContainer will call this object's Modified() method 141*1b3f573fSAndroid Build Coastguard Worker when it is modified. 142*1b3f573fSAndroid Build Coastguard Worker type_checker: A type_checkers.ValueChecker instance to run on elements 143*1b3f573fSAndroid Build Coastguard Worker inserted into this container. 144*1b3f573fSAndroid Build Coastguard Worker """ 145*1b3f573fSAndroid Build Coastguard Worker super().__init__(message_listener) 146*1b3f573fSAndroid Build Coastguard Worker self._type_checker = type_checker 147*1b3f573fSAndroid Build Coastguard Worker 148*1b3f573fSAndroid Build Coastguard Worker def append(self, value: _T) -> None: 149*1b3f573fSAndroid Build Coastguard Worker """Appends an item to the list. Similar to list.append().""" 150*1b3f573fSAndroid Build Coastguard Worker self._values.append(self._type_checker.CheckValue(value)) 151*1b3f573fSAndroid Build Coastguard Worker if not self._message_listener.dirty: 152*1b3f573fSAndroid Build Coastguard Worker self._message_listener.Modified() 153*1b3f573fSAndroid Build Coastguard Worker 154*1b3f573fSAndroid Build Coastguard Worker def insert(self, key: int, value: _T) -> None: 155*1b3f573fSAndroid Build Coastguard Worker """Inserts the item at the specified position. Similar to list.insert().""" 156*1b3f573fSAndroid Build Coastguard Worker self._values.insert(key, self._type_checker.CheckValue(value)) 157*1b3f573fSAndroid Build Coastguard Worker if not self._message_listener.dirty: 158*1b3f573fSAndroid Build Coastguard Worker self._message_listener.Modified() 159*1b3f573fSAndroid Build Coastguard Worker 160*1b3f573fSAndroid Build Coastguard Worker def extend(self, elem_seq: Iterable[_T]) -> None: 161*1b3f573fSAndroid Build Coastguard Worker """Extends by appending the given iterable. Similar to list.extend().""" 162*1b3f573fSAndroid Build Coastguard Worker if elem_seq is None: 163*1b3f573fSAndroid Build Coastguard Worker return 164*1b3f573fSAndroid Build Coastguard Worker try: 165*1b3f573fSAndroid Build Coastguard Worker elem_seq_iter = iter(elem_seq) 166*1b3f573fSAndroid Build Coastguard Worker except TypeError: 167*1b3f573fSAndroid Build Coastguard Worker if not elem_seq: 168*1b3f573fSAndroid Build Coastguard Worker # silently ignore falsy inputs :-/. 169*1b3f573fSAndroid Build Coastguard Worker # TODO(ptucker): Deprecate this behavior. b/18413862 170*1b3f573fSAndroid Build Coastguard Worker return 171*1b3f573fSAndroid Build Coastguard Worker raise 172*1b3f573fSAndroid Build Coastguard Worker 173*1b3f573fSAndroid Build Coastguard Worker new_values = [self._type_checker.CheckValue(elem) for elem in elem_seq_iter] 174*1b3f573fSAndroid Build Coastguard Worker if new_values: 175*1b3f573fSAndroid Build Coastguard Worker self._values.extend(new_values) 176*1b3f573fSAndroid Build Coastguard Worker self._message_listener.Modified() 177*1b3f573fSAndroid Build Coastguard Worker 178*1b3f573fSAndroid Build Coastguard Worker def MergeFrom( 179*1b3f573fSAndroid Build Coastguard Worker self, 180*1b3f573fSAndroid Build Coastguard Worker other: Union['RepeatedScalarFieldContainer[_T]', Iterable[_T]], 181*1b3f573fSAndroid Build Coastguard Worker ) -> None: 182*1b3f573fSAndroid Build Coastguard Worker """Appends the contents of another repeated field of the same type to this 183*1b3f573fSAndroid Build Coastguard Worker one. We do not check the types of the individual fields. 184*1b3f573fSAndroid Build Coastguard Worker """ 185*1b3f573fSAndroid Build Coastguard Worker self._values.extend(other) 186*1b3f573fSAndroid Build Coastguard Worker self._message_listener.Modified() 187*1b3f573fSAndroid Build Coastguard Worker 188*1b3f573fSAndroid Build Coastguard Worker def remove(self, elem: _T): 189*1b3f573fSAndroid Build Coastguard Worker """Removes an item from the list. Similar to list.remove().""" 190*1b3f573fSAndroid Build Coastguard Worker self._values.remove(elem) 191*1b3f573fSAndroid Build Coastguard Worker self._message_listener.Modified() 192*1b3f573fSAndroid Build Coastguard Worker 193*1b3f573fSAndroid Build Coastguard Worker def pop(self, key: Optional[int] = -1) -> _T: 194*1b3f573fSAndroid Build Coastguard Worker """Removes and returns an item at a given index. Similar to list.pop().""" 195*1b3f573fSAndroid Build Coastguard Worker value = self._values[key] 196*1b3f573fSAndroid Build Coastguard Worker self.__delitem__(key) 197*1b3f573fSAndroid Build Coastguard Worker return value 198*1b3f573fSAndroid Build Coastguard Worker 199*1b3f573fSAndroid Build Coastguard Worker @overload 200*1b3f573fSAndroid Build Coastguard Worker def __setitem__(self, key: int, value: _T) -> None: 201*1b3f573fSAndroid Build Coastguard Worker ... 202*1b3f573fSAndroid Build Coastguard Worker 203*1b3f573fSAndroid Build Coastguard Worker @overload 204*1b3f573fSAndroid Build Coastguard Worker def __setitem__(self, key: slice, value: Iterable[_T]) -> None: 205*1b3f573fSAndroid Build Coastguard Worker ... 206*1b3f573fSAndroid Build Coastguard Worker 207*1b3f573fSAndroid Build Coastguard Worker def __setitem__(self, key, value) -> None: 208*1b3f573fSAndroid Build Coastguard Worker """Sets the item on the specified position.""" 209*1b3f573fSAndroid Build Coastguard Worker if isinstance(key, slice): 210*1b3f573fSAndroid Build Coastguard Worker if key.step is not None: 211*1b3f573fSAndroid Build Coastguard Worker raise ValueError('Extended slices not supported') 212*1b3f573fSAndroid Build Coastguard Worker self._values[key] = map(self._type_checker.CheckValue, value) 213*1b3f573fSAndroid Build Coastguard Worker self._message_listener.Modified() 214*1b3f573fSAndroid Build Coastguard Worker else: 215*1b3f573fSAndroid Build Coastguard Worker self._values[key] = self._type_checker.CheckValue(value) 216*1b3f573fSAndroid Build Coastguard Worker self._message_listener.Modified() 217*1b3f573fSAndroid Build Coastguard Worker 218*1b3f573fSAndroid Build Coastguard Worker def __delitem__(self, key: Union[int, slice]) -> None: 219*1b3f573fSAndroid Build Coastguard Worker """Deletes the item at the specified position.""" 220*1b3f573fSAndroid Build Coastguard Worker del self._values[key] 221*1b3f573fSAndroid Build Coastguard Worker self._message_listener.Modified() 222*1b3f573fSAndroid Build Coastguard Worker 223*1b3f573fSAndroid Build Coastguard Worker def __eq__(self, other: Any) -> bool: 224*1b3f573fSAndroid Build Coastguard Worker """Compares the current instance with another one.""" 225*1b3f573fSAndroid Build Coastguard Worker if self is other: 226*1b3f573fSAndroid Build Coastguard Worker return True 227*1b3f573fSAndroid Build Coastguard Worker # Special case for the same type which should be common and fast. 228*1b3f573fSAndroid Build Coastguard Worker if isinstance(other, self.__class__): 229*1b3f573fSAndroid Build Coastguard Worker return other._values == self._values 230*1b3f573fSAndroid Build Coastguard Worker # We are presumably comparing against some other sequence type. 231*1b3f573fSAndroid Build Coastguard Worker return other == self._values 232*1b3f573fSAndroid Build Coastguard Worker 233*1b3f573fSAndroid Build Coastguard Worker def __deepcopy__( 234*1b3f573fSAndroid Build Coastguard Worker self, 235*1b3f573fSAndroid Build Coastguard Worker unused_memo: Any = None, 236*1b3f573fSAndroid Build Coastguard Worker ) -> 'RepeatedScalarFieldContainer[_T]': 237*1b3f573fSAndroid Build Coastguard Worker clone = RepeatedScalarFieldContainer( 238*1b3f573fSAndroid Build Coastguard Worker copy.deepcopy(self._message_listener), self._type_checker) 239*1b3f573fSAndroid Build Coastguard Worker clone.MergeFrom(self) 240*1b3f573fSAndroid Build Coastguard Worker return clone 241*1b3f573fSAndroid Build Coastguard Worker 242*1b3f573fSAndroid Build Coastguard Worker def __reduce__(self, **kwargs) -> NoReturn: 243*1b3f573fSAndroid Build Coastguard Worker raise pickle.PickleError( 244*1b3f573fSAndroid Build Coastguard Worker "Can't pickle repeated scalar fields, convert to list first") 245*1b3f573fSAndroid Build Coastguard Worker 246*1b3f573fSAndroid Build Coastguard Worker 247*1b3f573fSAndroid Build Coastguard Worker# TODO(slebedev): Constrain T to be a subtype of Message. 248*1b3f573fSAndroid Build Coastguard Workerclass RepeatedCompositeFieldContainer(BaseContainer[_T], MutableSequence[_T]): 249*1b3f573fSAndroid Build Coastguard Worker """Simple, list-like container for holding repeated composite fields.""" 250*1b3f573fSAndroid Build Coastguard Worker 251*1b3f573fSAndroid Build Coastguard Worker # Disallows assignment to other attributes. 252*1b3f573fSAndroid Build Coastguard Worker __slots__ = ['_message_descriptor'] 253*1b3f573fSAndroid Build Coastguard Worker 254*1b3f573fSAndroid Build Coastguard Worker def __init__(self, message_listener: Any, message_descriptor: Any) -> None: 255*1b3f573fSAndroid Build Coastguard Worker """ 256*1b3f573fSAndroid Build Coastguard Worker Note that we pass in a descriptor instead of the generated directly, 257*1b3f573fSAndroid Build Coastguard Worker since at the time we construct a _RepeatedCompositeFieldContainer we 258*1b3f573fSAndroid Build Coastguard Worker haven't yet necessarily initialized the type that will be contained in the 259*1b3f573fSAndroid Build Coastguard Worker container. 260*1b3f573fSAndroid Build Coastguard Worker 261*1b3f573fSAndroid Build Coastguard Worker Args: 262*1b3f573fSAndroid Build Coastguard Worker message_listener: A MessageListener implementation. 263*1b3f573fSAndroid Build Coastguard Worker The RepeatedCompositeFieldContainer will call this object's 264*1b3f573fSAndroid Build Coastguard Worker Modified() method when it is modified. 265*1b3f573fSAndroid Build Coastguard Worker message_descriptor: A Descriptor instance describing the protocol type 266*1b3f573fSAndroid Build Coastguard Worker that should be present in this container. We'll use the 267*1b3f573fSAndroid Build Coastguard Worker _concrete_class field of this descriptor when the client calls add(). 268*1b3f573fSAndroid Build Coastguard Worker """ 269*1b3f573fSAndroid Build Coastguard Worker super().__init__(message_listener) 270*1b3f573fSAndroid Build Coastguard Worker self._message_descriptor = message_descriptor 271*1b3f573fSAndroid Build Coastguard Worker 272*1b3f573fSAndroid Build Coastguard Worker def add(self, **kwargs: Any) -> _T: 273*1b3f573fSAndroid Build Coastguard Worker """Adds a new element at the end of the list and returns it. Keyword 274*1b3f573fSAndroid Build Coastguard Worker arguments may be used to initialize the element. 275*1b3f573fSAndroid Build Coastguard Worker """ 276*1b3f573fSAndroid Build Coastguard Worker new_element = self._message_descriptor._concrete_class(**kwargs) 277*1b3f573fSAndroid Build Coastguard Worker new_element._SetListener(self._message_listener) 278*1b3f573fSAndroid Build Coastguard Worker self._values.append(new_element) 279*1b3f573fSAndroid Build Coastguard Worker if not self._message_listener.dirty: 280*1b3f573fSAndroid Build Coastguard Worker self._message_listener.Modified() 281*1b3f573fSAndroid Build Coastguard Worker return new_element 282*1b3f573fSAndroid Build Coastguard Worker 283*1b3f573fSAndroid Build Coastguard Worker def append(self, value: _T) -> None: 284*1b3f573fSAndroid Build Coastguard Worker """Appends one element by copying the message.""" 285*1b3f573fSAndroid Build Coastguard Worker new_element = self._message_descriptor._concrete_class() 286*1b3f573fSAndroid Build Coastguard Worker new_element._SetListener(self._message_listener) 287*1b3f573fSAndroid Build Coastguard Worker new_element.CopyFrom(value) 288*1b3f573fSAndroid Build Coastguard Worker self._values.append(new_element) 289*1b3f573fSAndroid Build Coastguard Worker if not self._message_listener.dirty: 290*1b3f573fSAndroid Build Coastguard Worker self._message_listener.Modified() 291*1b3f573fSAndroid Build Coastguard Worker 292*1b3f573fSAndroid Build Coastguard Worker def insert(self, key: int, value: _T) -> None: 293*1b3f573fSAndroid Build Coastguard Worker """Inserts the item at the specified position by copying.""" 294*1b3f573fSAndroid Build Coastguard Worker new_element = self._message_descriptor._concrete_class() 295*1b3f573fSAndroid Build Coastguard Worker new_element._SetListener(self._message_listener) 296*1b3f573fSAndroid Build Coastguard Worker new_element.CopyFrom(value) 297*1b3f573fSAndroid Build Coastguard Worker self._values.insert(key, new_element) 298*1b3f573fSAndroid Build Coastguard Worker if not self._message_listener.dirty: 299*1b3f573fSAndroid Build Coastguard Worker self._message_listener.Modified() 300*1b3f573fSAndroid Build Coastguard Worker 301*1b3f573fSAndroid Build Coastguard Worker def extend(self, elem_seq: Iterable[_T]) -> None: 302*1b3f573fSAndroid Build Coastguard Worker """Extends by appending the given sequence of elements of the same type 303*1b3f573fSAndroid Build Coastguard Worker 304*1b3f573fSAndroid Build Coastguard Worker as this one, copying each individual message. 305*1b3f573fSAndroid Build Coastguard Worker """ 306*1b3f573fSAndroid Build Coastguard Worker message_class = self._message_descriptor._concrete_class 307*1b3f573fSAndroid Build Coastguard Worker listener = self._message_listener 308*1b3f573fSAndroid Build Coastguard Worker values = self._values 309*1b3f573fSAndroid Build Coastguard Worker for message in elem_seq: 310*1b3f573fSAndroid Build Coastguard Worker new_element = message_class() 311*1b3f573fSAndroid Build Coastguard Worker new_element._SetListener(listener) 312*1b3f573fSAndroid Build Coastguard Worker new_element.MergeFrom(message) 313*1b3f573fSAndroid Build Coastguard Worker values.append(new_element) 314*1b3f573fSAndroid Build Coastguard Worker listener.Modified() 315*1b3f573fSAndroid Build Coastguard Worker 316*1b3f573fSAndroid Build Coastguard Worker def MergeFrom( 317*1b3f573fSAndroid Build Coastguard Worker self, 318*1b3f573fSAndroid Build Coastguard Worker other: Union['RepeatedCompositeFieldContainer[_T]', Iterable[_T]], 319*1b3f573fSAndroid Build Coastguard Worker ) -> None: 320*1b3f573fSAndroid Build Coastguard Worker """Appends the contents of another repeated field of the same type to this 321*1b3f573fSAndroid Build Coastguard Worker one, copying each individual message. 322*1b3f573fSAndroid Build Coastguard Worker """ 323*1b3f573fSAndroid Build Coastguard Worker self.extend(other) 324*1b3f573fSAndroid Build Coastguard Worker 325*1b3f573fSAndroid Build Coastguard Worker def remove(self, elem: _T) -> None: 326*1b3f573fSAndroid Build Coastguard Worker """Removes an item from the list. Similar to list.remove().""" 327*1b3f573fSAndroid Build Coastguard Worker self._values.remove(elem) 328*1b3f573fSAndroid Build Coastguard Worker self._message_listener.Modified() 329*1b3f573fSAndroid Build Coastguard Worker 330*1b3f573fSAndroid Build Coastguard Worker def pop(self, key: Optional[int] = -1) -> _T: 331*1b3f573fSAndroid Build Coastguard Worker """Removes and returns an item at a given index. Similar to list.pop().""" 332*1b3f573fSAndroid Build Coastguard Worker value = self._values[key] 333*1b3f573fSAndroid Build Coastguard Worker self.__delitem__(key) 334*1b3f573fSAndroid Build Coastguard Worker return value 335*1b3f573fSAndroid Build Coastguard Worker 336*1b3f573fSAndroid Build Coastguard Worker @overload 337*1b3f573fSAndroid Build Coastguard Worker def __setitem__(self, key: int, value: _T) -> None: 338*1b3f573fSAndroid Build Coastguard Worker ... 339*1b3f573fSAndroid Build Coastguard Worker 340*1b3f573fSAndroid Build Coastguard Worker @overload 341*1b3f573fSAndroid Build Coastguard Worker def __setitem__(self, key: slice, value: Iterable[_T]) -> None: 342*1b3f573fSAndroid Build Coastguard Worker ... 343*1b3f573fSAndroid Build Coastguard Worker 344*1b3f573fSAndroid Build Coastguard Worker def __setitem__(self, key, value): 345*1b3f573fSAndroid Build Coastguard Worker # This method is implemented to make RepeatedCompositeFieldContainer 346*1b3f573fSAndroid Build Coastguard Worker # structurally compatible with typing.MutableSequence. It is 347*1b3f573fSAndroid Build Coastguard Worker # otherwise unsupported and will always raise an error. 348*1b3f573fSAndroid Build Coastguard Worker raise TypeError( 349*1b3f573fSAndroid Build Coastguard Worker f'{self.__class__.__name__} object does not support item assignment') 350*1b3f573fSAndroid Build Coastguard Worker 351*1b3f573fSAndroid Build Coastguard Worker def __delitem__(self, key: Union[int, slice]) -> None: 352*1b3f573fSAndroid Build Coastguard Worker """Deletes the item at the specified position.""" 353*1b3f573fSAndroid Build Coastguard Worker del self._values[key] 354*1b3f573fSAndroid Build Coastguard Worker self._message_listener.Modified() 355*1b3f573fSAndroid Build Coastguard Worker 356*1b3f573fSAndroid Build Coastguard Worker def __eq__(self, other: Any) -> bool: 357*1b3f573fSAndroid Build Coastguard Worker """Compares the current instance with another one.""" 358*1b3f573fSAndroid Build Coastguard Worker if self is other: 359*1b3f573fSAndroid Build Coastguard Worker return True 360*1b3f573fSAndroid Build Coastguard Worker if not isinstance(other, self.__class__): 361*1b3f573fSAndroid Build Coastguard Worker raise TypeError('Can only compare repeated composite fields against ' 362*1b3f573fSAndroid Build Coastguard Worker 'other repeated composite fields.') 363*1b3f573fSAndroid Build Coastguard Worker return self._values == other._values 364*1b3f573fSAndroid Build Coastguard Worker 365*1b3f573fSAndroid Build Coastguard Worker 366*1b3f573fSAndroid Build Coastguard Workerclass ScalarMap(MutableMapping[_K, _V]): 367*1b3f573fSAndroid Build Coastguard Worker """Simple, type-checked, dict-like container for holding repeated scalars.""" 368*1b3f573fSAndroid Build Coastguard Worker 369*1b3f573fSAndroid Build Coastguard Worker # Disallows assignment to other attributes. 370*1b3f573fSAndroid Build Coastguard Worker __slots__ = ['_key_checker', '_value_checker', '_values', '_message_listener', 371*1b3f573fSAndroid Build Coastguard Worker '_entry_descriptor'] 372*1b3f573fSAndroid Build Coastguard Worker 373*1b3f573fSAndroid Build Coastguard Worker def __init__( 374*1b3f573fSAndroid Build Coastguard Worker self, 375*1b3f573fSAndroid Build Coastguard Worker message_listener: Any, 376*1b3f573fSAndroid Build Coastguard Worker key_checker: Any, 377*1b3f573fSAndroid Build Coastguard Worker value_checker: Any, 378*1b3f573fSAndroid Build Coastguard Worker entry_descriptor: Any, 379*1b3f573fSAndroid Build Coastguard Worker ) -> None: 380*1b3f573fSAndroid Build Coastguard Worker """ 381*1b3f573fSAndroid Build Coastguard Worker Args: 382*1b3f573fSAndroid Build Coastguard Worker message_listener: A MessageListener implementation. 383*1b3f573fSAndroid Build Coastguard Worker The ScalarMap will call this object's Modified() method when it 384*1b3f573fSAndroid Build Coastguard Worker is modified. 385*1b3f573fSAndroid Build Coastguard Worker key_checker: A type_checkers.ValueChecker instance to run on keys 386*1b3f573fSAndroid Build Coastguard Worker inserted into this container. 387*1b3f573fSAndroid Build Coastguard Worker value_checker: A type_checkers.ValueChecker instance to run on values 388*1b3f573fSAndroid Build Coastguard Worker inserted into this container. 389*1b3f573fSAndroid Build Coastguard Worker entry_descriptor: The MessageDescriptor of a map entry: key and value. 390*1b3f573fSAndroid Build Coastguard Worker """ 391*1b3f573fSAndroid Build Coastguard Worker self._message_listener = message_listener 392*1b3f573fSAndroid Build Coastguard Worker self._key_checker = key_checker 393*1b3f573fSAndroid Build Coastguard Worker self._value_checker = value_checker 394*1b3f573fSAndroid Build Coastguard Worker self._entry_descriptor = entry_descriptor 395*1b3f573fSAndroid Build Coastguard Worker self._values = {} 396*1b3f573fSAndroid Build Coastguard Worker 397*1b3f573fSAndroid Build Coastguard Worker def __getitem__(self, key: _K) -> _V: 398*1b3f573fSAndroid Build Coastguard Worker try: 399*1b3f573fSAndroid Build Coastguard Worker return self._values[key] 400*1b3f573fSAndroid Build Coastguard Worker except KeyError: 401*1b3f573fSAndroid Build Coastguard Worker key = self._key_checker.CheckValue(key) 402*1b3f573fSAndroid Build Coastguard Worker val = self._value_checker.DefaultValue() 403*1b3f573fSAndroid Build Coastguard Worker self._values[key] = val 404*1b3f573fSAndroid Build Coastguard Worker return val 405*1b3f573fSAndroid Build Coastguard Worker 406*1b3f573fSAndroid Build Coastguard Worker def __contains__(self, item: _K) -> bool: 407*1b3f573fSAndroid Build Coastguard Worker # We check the key's type to match the strong-typing flavor of the API. 408*1b3f573fSAndroid Build Coastguard Worker # Also this makes it easier to match the behavior of the C++ implementation. 409*1b3f573fSAndroid Build Coastguard Worker self._key_checker.CheckValue(item) 410*1b3f573fSAndroid Build Coastguard Worker return item in self._values 411*1b3f573fSAndroid Build Coastguard Worker 412*1b3f573fSAndroid Build Coastguard Worker @overload 413*1b3f573fSAndroid Build Coastguard Worker def get(self, key: _K) -> Optional[_V]: 414*1b3f573fSAndroid Build Coastguard Worker ... 415*1b3f573fSAndroid Build Coastguard Worker 416*1b3f573fSAndroid Build Coastguard Worker @overload 417*1b3f573fSAndroid Build Coastguard Worker def get(self, key: _K, default: _T) -> Union[_V, _T]: 418*1b3f573fSAndroid Build Coastguard Worker ... 419*1b3f573fSAndroid Build Coastguard Worker 420*1b3f573fSAndroid Build Coastguard Worker # We need to override this explicitly, because our defaultdict-like behavior 421*1b3f573fSAndroid Build Coastguard Worker # will make the default implementation (from our base class) always insert 422*1b3f573fSAndroid Build Coastguard Worker # the key. 423*1b3f573fSAndroid Build Coastguard Worker def get(self, key, default=None): 424*1b3f573fSAndroid Build Coastguard Worker if key in self: 425*1b3f573fSAndroid Build Coastguard Worker return self[key] 426*1b3f573fSAndroid Build Coastguard Worker else: 427*1b3f573fSAndroid Build Coastguard Worker return default 428*1b3f573fSAndroid Build Coastguard Worker 429*1b3f573fSAndroid Build Coastguard Worker def __setitem__(self, key: _K, value: _V) -> _T: 430*1b3f573fSAndroid Build Coastguard Worker checked_key = self._key_checker.CheckValue(key) 431*1b3f573fSAndroid Build Coastguard Worker checked_value = self._value_checker.CheckValue(value) 432*1b3f573fSAndroid Build Coastguard Worker self._values[checked_key] = checked_value 433*1b3f573fSAndroid Build Coastguard Worker self._message_listener.Modified() 434*1b3f573fSAndroid Build Coastguard Worker 435*1b3f573fSAndroid Build Coastguard Worker def __delitem__(self, key: _K) -> None: 436*1b3f573fSAndroid Build Coastguard Worker del self._values[key] 437*1b3f573fSAndroid Build Coastguard Worker self._message_listener.Modified() 438*1b3f573fSAndroid Build Coastguard Worker 439*1b3f573fSAndroid Build Coastguard Worker def __len__(self) -> int: 440*1b3f573fSAndroid Build Coastguard Worker return len(self._values) 441*1b3f573fSAndroid Build Coastguard Worker 442*1b3f573fSAndroid Build Coastguard Worker def __iter__(self) -> Iterator[_K]: 443*1b3f573fSAndroid Build Coastguard Worker return iter(self._values) 444*1b3f573fSAndroid Build Coastguard Worker 445*1b3f573fSAndroid Build Coastguard Worker def __repr__(self) -> str: 446*1b3f573fSAndroid Build Coastguard Worker return repr(self._values) 447*1b3f573fSAndroid Build Coastguard Worker 448*1b3f573fSAndroid Build Coastguard Worker def MergeFrom(self, other: 'ScalarMap[_K, _V]') -> None: 449*1b3f573fSAndroid Build Coastguard Worker self._values.update(other._values) 450*1b3f573fSAndroid Build Coastguard Worker self._message_listener.Modified() 451*1b3f573fSAndroid Build Coastguard Worker 452*1b3f573fSAndroid Build Coastguard Worker def InvalidateIterators(self) -> None: 453*1b3f573fSAndroid Build Coastguard Worker # It appears that the only way to reliably invalidate iterators to 454*1b3f573fSAndroid Build Coastguard Worker # self._values is to ensure that its size changes. 455*1b3f573fSAndroid Build Coastguard Worker original = self._values 456*1b3f573fSAndroid Build Coastguard Worker self._values = original.copy() 457*1b3f573fSAndroid Build Coastguard Worker original[None] = None 458*1b3f573fSAndroid Build Coastguard Worker 459*1b3f573fSAndroid Build Coastguard Worker # This is defined in the abstract base, but we can do it much more cheaply. 460*1b3f573fSAndroid Build Coastguard Worker def clear(self) -> None: 461*1b3f573fSAndroid Build Coastguard Worker self._values.clear() 462*1b3f573fSAndroid Build Coastguard Worker self._message_listener.Modified() 463*1b3f573fSAndroid Build Coastguard Worker 464*1b3f573fSAndroid Build Coastguard Worker def GetEntryClass(self) -> Any: 465*1b3f573fSAndroid Build Coastguard Worker return self._entry_descriptor._concrete_class 466*1b3f573fSAndroid Build Coastguard Worker 467*1b3f573fSAndroid Build Coastguard Worker 468*1b3f573fSAndroid Build Coastguard Workerclass MessageMap(MutableMapping[_K, _V]): 469*1b3f573fSAndroid Build Coastguard Worker """Simple, type-checked, dict-like container for with submessage values.""" 470*1b3f573fSAndroid Build Coastguard Worker 471*1b3f573fSAndroid Build Coastguard Worker # Disallows assignment to other attributes. 472*1b3f573fSAndroid Build Coastguard Worker __slots__ = ['_key_checker', '_values', '_message_listener', 473*1b3f573fSAndroid Build Coastguard Worker '_message_descriptor', '_entry_descriptor'] 474*1b3f573fSAndroid Build Coastguard Worker 475*1b3f573fSAndroid Build Coastguard Worker def __init__( 476*1b3f573fSAndroid Build Coastguard Worker self, 477*1b3f573fSAndroid Build Coastguard Worker message_listener: Any, 478*1b3f573fSAndroid Build Coastguard Worker message_descriptor: Any, 479*1b3f573fSAndroid Build Coastguard Worker key_checker: Any, 480*1b3f573fSAndroid Build Coastguard Worker entry_descriptor: Any, 481*1b3f573fSAndroid Build Coastguard Worker ) -> None: 482*1b3f573fSAndroid Build Coastguard Worker """ 483*1b3f573fSAndroid Build Coastguard Worker Args: 484*1b3f573fSAndroid Build Coastguard Worker message_listener: A MessageListener implementation. 485*1b3f573fSAndroid Build Coastguard Worker The ScalarMap will call this object's Modified() method when it 486*1b3f573fSAndroid Build Coastguard Worker is modified. 487*1b3f573fSAndroid Build Coastguard Worker key_checker: A type_checkers.ValueChecker instance to run on keys 488*1b3f573fSAndroid Build Coastguard Worker inserted into this container. 489*1b3f573fSAndroid Build Coastguard Worker value_checker: A type_checkers.ValueChecker instance to run on values 490*1b3f573fSAndroid Build Coastguard Worker inserted into this container. 491*1b3f573fSAndroid Build Coastguard Worker entry_descriptor: The MessageDescriptor of a map entry: key and value. 492*1b3f573fSAndroid Build Coastguard Worker """ 493*1b3f573fSAndroid Build Coastguard Worker self._message_listener = message_listener 494*1b3f573fSAndroid Build Coastguard Worker self._message_descriptor = message_descriptor 495*1b3f573fSAndroid Build Coastguard Worker self._key_checker = key_checker 496*1b3f573fSAndroid Build Coastguard Worker self._entry_descriptor = entry_descriptor 497*1b3f573fSAndroid Build Coastguard Worker self._values = {} 498*1b3f573fSAndroid Build Coastguard Worker 499*1b3f573fSAndroid Build Coastguard Worker def __getitem__(self, key: _K) -> _V: 500*1b3f573fSAndroid Build Coastguard Worker key = self._key_checker.CheckValue(key) 501*1b3f573fSAndroid Build Coastguard Worker try: 502*1b3f573fSAndroid Build Coastguard Worker return self._values[key] 503*1b3f573fSAndroid Build Coastguard Worker except KeyError: 504*1b3f573fSAndroid Build Coastguard Worker new_element = self._message_descriptor._concrete_class() 505*1b3f573fSAndroid Build Coastguard Worker new_element._SetListener(self._message_listener) 506*1b3f573fSAndroid Build Coastguard Worker self._values[key] = new_element 507*1b3f573fSAndroid Build Coastguard Worker self._message_listener.Modified() 508*1b3f573fSAndroid Build Coastguard Worker return new_element 509*1b3f573fSAndroid Build Coastguard Worker 510*1b3f573fSAndroid Build Coastguard Worker def get_or_create(self, key: _K) -> _V: 511*1b3f573fSAndroid Build Coastguard Worker """get_or_create() is an alias for getitem (ie. map[key]). 512*1b3f573fSAndroid Build Coastguard Worker 513*1b3f573fSAndroid Build Coastguard Worker Args: 514*1b3f573fSAndroid Build Coastguard Worker key: The key to get or create in the map. 515*1b3f573fSAndroid Build Coastguard Worker 516*1b3f573fSAndroid Build Coastguard Worker This is useful in cases where you want to be explicit that the call is 517*1b3f573fSAndroid Build Coastguard Worker mutating the map. This can avoid lint errors for statements like this 518*1b3f573fSAndroid Build Coastguard Worker that otherwise would appear to be pointless statements: 519*1b3f573fSAndroid Build Coastguard Worker 520*1b3f573fSAndroid Build Coastguard Worker msg.my_map[key] 521*1b3f573fSAndroid Build Coastguard Worker """ 522*1b3f573fSAndroid Build Coastguard Worker return self[key] 523*1b3f573fSAndroid Build Coastguard Worker 524*1b3f573fSAndroid Build Coastguard Worker @overload 525*1b3f573fSAndroid Build Coastguard Worker def get(self, key: _K) -> Optional[_V]: 526*1b3f573fSAndroid Build Coastguard Worker ... 527*1b3f573fSAndroid Build Coastguard Worker 528*1b3f573fSAndroid Build Coastguard Worker @overload 529*1b3f573fSAndroid Build Coastguard Worker def get(self, key: _K, default: _T) -> Union[_V, _T]: 530*1b3f573fSAndroid Build Coastguard Worker ... 531*1b3f573fSAndroid Build Coastguard Worker 532*1b3f573fSAndroid Build Coastguard Worker # We need to override this explicitly, because our defaultdict-like behavior 533*1b3f573fSAndroid Build Coastguard Worker # will make the default implementation (from our base class) always insert 534*1b3f573fSAndroid Build Coastguard Worker # the key. 535*1b3f573fSAndroid Build Coastguard Worker def get(self, key, default=None): 536*1b3f573fSAndroid Build Coastguard Worker if key in self: 537*1b3f573fSAndroid Build Coastguard Worker return self[key] 538*1b3f573fSAndroid Build Coastguard Worker else: 539*1b3f573fSAndroid Build Coastguard Worker return default 540*1b3f573fSAndroid Build Coastguard Worker 541*1b3f573fSAndroid Build Coastguard Worker def __contains__(self, item: _K) -> bool: 542*1b3f573fSAndroid Build Coastguard Worker item = self._key_checker.CheckValue(item) 543*1b3f573fSAndroid Build Coastguard Worker return item in self._values 544*1b3f573fSAndroid Build Coastguard Worker 545*1b3f573fSAndroid Build Coastguard Worker def __setitem__(self, key: _K, value: _V) -> NoReturn: 546*1b3f573fSAndroid Build Coastguard Worker raise ValueError('May not set values directly, call my_map[key].foo = 5') 547*1b3f573fSAndroid Build Coastguard Worker 548*1b3f573fSAndroid Build Coastguard Worker def __delitem__(self, key: _K) -> None: 549*1b3f573fSAndroid Build Coastguard Worker key = self._key_checker.CheckValue(key) 550*1b3f573fSAndroid Build Coastguard Worker del self._values[key] 551*1b3f573fSAndroid Build Coastguard Worker self._message_listener.Modified() 552*1b3f573fSAndroid Build Coastguard Worker 553*1b3f573fSAndroid Build Coastguard Worker def __len__(self) -> int: 554*1b3f573fSAndroid Build Coastguard Worker return len(self._values) 555*1b3f573fSAndroid Build Coastguard Worker 556*1b3f573fSAndroid Build Coastguard Worker def __iter__(self) -> Iterator[_K]: 557*1b3f573fSAndroid Build Coastguard Worker return iter(self._values) 558*1b3f573fSAndroid Build Coastguard Worker 559*1b3f573fSAndroid Build Coastguard Worker def __repr__(self) -> str: 560*1b3f573fSAndroid Build Coastguard Worker return repr(self._values) 561*1b3f573fSAndroid Build Coastguard Worker 562*1b3f573fSAndroid Build Coastguard Worker def MergeFrom(self, other: 'MessageMap[_K, _V]') -> None: 563*1b3f573fSAndroid Build Coastguard Worker # pylint: disable=protected-access 564*1b3f573fSAndroid Build Coastguard Worker for key in other._values: 565*1b3f573fSAndroid Build Coastguard Worker # According to documentation: "When parsing from the wire or when merging, 566*1b3f573fSAndroid Build Coastguard Worker # if there are duplicate map keys the last key seen is used". 567*1b3f573fSAndroid Build Coastguard Worker if key in self: 568*1b3f573fSAndroid Build Coastguard Worker del self[key] 569*1b3f573fSAndroid Build Coastguard Worker self[key].CopyFrom(other[key]) 570*1b3f573fSAndroid Build Coastguard Worker # self._message_listener.Modified() not required here, because 571*1b3f573fSAndroid Build Coastguard Worker # mutations to submessages already propagate. 572*1b3f573fSAndroid Build Coastguard Worker 573*1b3f573fSAndroid Build Coastguard Worker def InvalidateIterators(self) -> None: 574*1b3f573fSAndroid Build Coastguard Worker # It appears that the only way to reliably invalidate iterators to 575*1b3f573fSAndroid Build Coastguard Worker # self._values is to ensure that its size changes. 576*1b3f573fSAndroid Build Coastguard Worker original = self._values 577*1b3f573fSAndroid Build Coastguard Worker self._values = original.copy() 578*1b3f573fSAndroid Build Coastguard Worker original[None] = None 579*1b3f573fSAndroid Build Coastguard Worker 580*1b3f573fSAndroid Build Coastguard Worker # This is defined in the abstract base, but we can do it much more cheaply. 581*1b3f573fSAndroid Build Coastguard Worker def clear(self) -> None: 582*1b3f573fSAndroid Build Coastguard Worker self._values.clear() 583*1b3f573fSAndroid Build Coastguard Worker self._message_listener.Modified() 584*1b3f573fSAndroid Build Coastguard Worker 585*1b3f573fSAndroid Build Coastguard Worker def GetEntryClass(self) -> Any: 586*1b3f573fSAndroid Build Coastguard Worker return self._entry_descriptor._concrete_class 587*1b3f573fSAndroid Build Coastguard Worker 588*1b3f573fSAndroid Build Coastguard Worker 589*1b3f573fSAndroid Build Coastguard Workerclass _UnknownField: 590*1b3f573fSAndroid Build Coastguard Worker """A parsed unknown field.""" 591*1b3f573fSAndroid Build Coastguard Worker 592*1b3f573fSAndroid Build Coastguard Worker # Disallows assignment to other attributes. 593*1b3f573fSAndroid Build Coastguard Worker __slots__ = ['_field_number', '_wire_type', '_data'] 594*1b3f573fSAndroid Build Coastguard Worker 595*1b3f573fSAndroid Build Coastguard Worker def __init__(self, field_number, wire_type, data): 596*1b3f573fSAndroid Build Coastguard Worker self._field_number = field_number 597*1b3f573fSAndroid Build Coastguard Worker self._wire_type = wire_type 598*1b3f573fSAndroid Build Coastguard Worker self._data = data 599*1b3f573fSAndroid Build Coastguard Worker return 600*1b3f573fSAndroid Build Coastguard Worker 601*1b3f573fSAndroid Build Coastguard Worker def __lt__(self, other): 602*1b3f573fSAndroid Build Coastguard Worker # pylint: disable=protected-access 603*1b3f573fSAndroid Build Coastguard Worker return self._field_number < other._field_number 604*1b3f573fSAndroid Build Coastguard Worker 605*1b3f573fSAndroid Build Coastguard Worker def __eq__(self, other): 606*1b3f573fSAndroid Build Coastguard Worker if self is other: 607*1b3f573fSAndroid Build Coastguard Worker return True 608*1b3f573fSAndroid Build Coastguard Worker # pylint: disable=protected-access 609*1b3f573fSAndroid Build Coastguard Worker return (self._field_number == other._field_number and 610*1b3f573fSAndroid Build Coastguard Worker self._wire_type == other._wire_type and 611*1b3f573fSAndroid Build Coastguard Worker self._data == other._data) 612*1b3f573fSAndroid Build Coastguard Worker 613*1b3f573fSAndroid Build Coastguard Worker 614*1b3f573fSAndroid Build Coastguard Workerclass UnknownFieldRef: # pylint: disable=missing-class-docstring 615*1b3f573fSAndroid Build Coastguard Worker 616*1b3f573fSAndroid Build Coastguard Worker def __init__(self, parent, index): 617*1b3f573fSAndroid Build Coastguard Worker self._parent = parent 618*1b3f573fSAndroid Build Coastguard Worker self._index = index 619*1b3f573fSAndroid Build Coastguard Worker 620*1b3f573fSAndroid Build Coastguard Worker def _check_valid(self): 621*1b3f573fSAndroid Build Coastguard Worker if not self._parent: 622*1b3f573fSAndroid Build Coastguard Worker raise ValueError('UnknownField does not exist. ' 623*1b3f573fSAndroid Build Coastguard Worker 'The parent message might be cleared.') 624*1b3f573fSAndroid Build Coastguard Worker if self._index >= len(self._parent): 625*1b3f573fSAndroid Build Coastguard Worker raise ValueError('UnknownField does not exist. ' 626*1b3f573fSAndroid Build Coastguard Worker 'The parent message might be cleared.') 627*1b3f573fSAndroid Build Coastguard Worker 628*1b3f573fSAndroid Build Coastguard Worker @property 629*1b3f573fSAndroid Build Coastguard Worker def field_number(self): 630*1b3f573fSAndroid Build Coastguard Worker self._check_valid() 631*1b3f573fSAndroid Build Coastguard Worker # pylint: disable=protected-access 632*1b3f573fSAndroid Build Coastguard Worker return self._parent._internal_get(self._index)._field_number 633*1b3f573fSAndroid Build Coastguard Worker 634*1b3f573fSAndroid Build Coastguard Worker @property 635*1b3f573fSAndroid Build Coastguard Worker def wire_type(self): 636*1b3f573fSAndroid Build Coastguard Worker self._check_valid() 637*1b3f573fSAndroid Build Coastguard Worker # pylint: disable=protected-access 638*1b3f573fSAndroid Build Coastguard Worker return self._parent._internal_get(self._index)._wire_type 639*1b3f573fSAndroid Build Coastguard Worker 640*1b3f573fSAndroid Build Coastguard Worker @property 641*1b3f573fSAndroid Build Coastguard Worker def data(self): 642*1b3f573fSAndroid Build Coastguard Worker self._check_valid() 643*1b3f573fSAndroid Build Coastguard Worker # pylint: disable=protected-access 644*1b3f573fSAndroid Build Coastguard Worker return self._parent._internal_get(self._index)._data 645*1b3f573fSAndroid Build Coastguard Worker 646*1b3f573fSAndroid Build Coastguard Worker 647*1b3f573fSAndroid Build Coastguard Workerclass UnknownFieldSet: 648*1b3f573fSAndroid Build Coastguard Worker """UnknownField container""" 649*1b3f573fSAndroid Build Coastguard Worker 650*1b3f573fSAndroid Build Coastguard Worker # Disallows assignment to other attributes. 651*1b3f573fSAndroid Build Coastguard Worker __slots__ = ['_values'] 652*1b3f573fSAndroid Build Coastguard Worker 653*1b3f573fSAndroid Build Coastguard Worker def __init__(self): 654*1b3f573fSAndroid Build Coastguard Worker self._values = [] 655*1b3f573fSAndroid Build Coastguard Worker 656*1b3f573fSAndroid Build Coastguard Worker def __getitem__(self, index): 657*1b3f573fSAndroid Build Coastguard Worker if self._values is None: 658*1b3f573fSAndroid Build Coastguard Worker raise ValueError('UnknownFields does not exist. ' 659*1b3f573fSAndroid Build Coastguard Worker 'The parent message might be cleared.') 660*1b3f573fSAndroid Build Coastguard Worker size = len(self._values) 661*1b3f573fSAndroid Build Coastguard Worker if index < 0: 662*1b3f573fSAndroid Build Coastguard Worker index += size 663*1b3f573fSAndroid Build Coastguard Worker if index < 0 or index >= size: 664*1b3f573fSAndroid Build Coastguard Worker raise IndexError('index %d out of range'.index) 665*1b3f573fSAndroid Build Coastguard Worker 666*1b3f573fSAndroid Build Coastguard Worker return UnknownFieldRef(self, index) 667*1b3f573fSAndroid Build Coastguard Worker 668*1b3f573fSAndroid Build Coastguard Worker def _internal_get(self, index): 669*1b3f573fSAndroid Build Coastguard Worker return self._values[index] 670*1b3f573fSAndroid Build Coastguard Worker 671*1b3f573fSAndroid Build Coastguard Worker def __len__(self): 672*1b3f573fSAndroid Build Coastguard Worker if self._values is None: 673*1b3f573fSAndroid Build Coastguard Worker raise ValueError('UnknownFields does not exist. ' 674*1b3f573fSAndroid Build Coastguard Worker 'The parent message might be cleared.') 675*1b3f573fSAndroid Build Coastguard Worker return len(self._values) 676*1b3f573fSAndroid Build Coastguard Worker 677*1b3f573fSAndroid Build Coastguard Worker def _add(self, field_number, wire_type, data): 678*1b3f573fSAndroid Build Coastguard Worker unknown_field = _UnknownField(field_number, wire_type, data) 679*1b3f573fSAndroid Build Coastguard Worker self._values.append(unknown_field) 680*1b3f573fSAndroid Build Coastguard Worker return unknown_field 681*1b3f573fSAndroid Build Coastguard Worker 682*1b3f573fSAndroid Build Coastguard Worker def __iter__(self): 683*1b3f573fSAndroid Build Coastguard Worker for i in range(len(self)): 684*1b3f573fSAndroid Build Coastguard Worker yield UnknownFieldRef(self, i) 685*1b3f573fSAndroid Build Coastguard Worker 686*1b3f573fSAndroid Build Coastguard Worker def _extend(self, other): 687*1b3f573fSAndroid Build Coastguard Worker if other is None: 688*1b3f573fSAndroid Build Coastguard Worker return 689*1b3f573fSAndroid Build Coastguard Worker # pylint: disable=protected-access 690*1b3f573fSAndroid Build Coastguard Worker self._values.extend(other._values) 691*1b3f573fSAndroid Build Coastguard Worker 692*1b3f573fSAndroid Build Coastguard Worker def __eq__(self, other): 693*1b3f573fSAndroid Build Coastguard Worker if self is other: 694*1b3f573fSAndroid Build Coastguard Worker return True 695*1b3f573fSAndroid Build Coastguard Worker # Sort unknown fields because their order shouldn't 696*1b3f573fSAndroid Build Coastguard Worker # affect equality test. 697*1b3f573fSAndroid Build Coastguard Worker values = list(self._values) 698*1b3f573fSAndroid Build Coastguard Worker if other is None: 699*1b3f573fSAndroid Build Coastguard Worker return not values 700*1b3f573fSAndroid Build Coastguard Worker values.sort() 701*1b3f573fSAndroid Build Coastguard Worker # pylint: disable=protected-access 702*1b3f573fSAndroid Build Coastguard Worker other_values = sorted(other._values) 703*1b3f573fSAndroid Build Coastguard Worker return values == other_values 704*1b3f573fSAndroid Build Coastguard Worker 705*1b3f573fSAndroid Build Coastguard Worker def _clear(self): 706*1b3f573fSAndroid Build Coastguard Worker for value in self._values: 707*1b3f573fSAndroid Build Coastguard Worker # pylint: disable=protected-access 708*1b3f573fSAndroid Build Coastguard Worker if isinstance(value._data, UnknownFieldSet): 709*1b3f573fSAndroid Build Coastguard Worker value._data._clear() # pylint: disable=protected-access 710*1b3f573fSAndroid Build Coastguard Worker self._values = None 711