Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/google/protobuf/internal/containers.py: 30%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

446 statements  

1# Protocol Buffers - Google's data interchange format 

2# Copyright 2008 Google Inc. All rights reserved. 

3# 

4# Use of this source code is governed by a BSD-style 

5# license that can be found in the LICENSE file or at 

6# https://developers.google.com/open-source/licenses/bsd 

7"""Contains container classes to represent different protocol buffer types. 

8 

9This file defines container classes which represent categories of protocol 

10buffer field types which need extra maintenance. Currently these categories 

11are: 

12 

13- Repeated scalar fields - These are all repeated fields which aren't 

14 composite (e.g. they are of simple types like int32, string, etc). 

15- Repeated composite fields - Repeated fields which are composite. This 

16 includes groups and nested messages. 

17""" 

18 

19import collections.abc 

20import copy 

21import pickle 

22import warnings 

23from typing import ( 

24 Any, 

25 Iterable, 

26 Iterator, 

27 List, 

28 MutableMapping, 

29 MutableSequence, 

30 NoReturn, 

31 Optional, 

32 Sequence, 

33 TypeVar, 

34 Union, 

35 overload, 

36) 

37 

38_T = TypeVar('_T') 

39_K = TypeVar('_K') 

40_V = TypeVar('_V') 

41 

42from google.protobuf.descriptor import FieldDescriptor 

43from google.protobuf import message 

44 

45 

46def _CheckFrozen(is_frozen: bool, msg: str) -> None: 

47 if is_frozen: 

48 warnings.warn( 

49 'Mutating messages or containers returned by GetOptions() is' 

50 ' deprecated and will raise an exception in a future release.', 

51 category=FutureWarning, 

52 stacklevel=3, 

53 ) 

54 

55 

56class BaseContainer(Sequence[_T]): 

57 """Base container class.""" 

58 

59 # Minimizes memory usage and disallows assignment to other attributes. 

60 __slots__ = ['_message_listener', '_values', '_frozen'] 

61 

62 def __init__(self, message_listener: Any) -> None: 

63 """Args: 

64 

65 message_listener: A MessageListener implementation. 

66 The RepeatedScalarFieldContainer will call this object's 

67 Modified() method when it is modified. 

68 """ 

69 self._message_listener = message_listener 

70 self._values = [] 

71 self._frozen = False 

72 

73 @overload 

74 def __getitem__(self, key: int) -> _T: 

75 ... 

76 

77 @overload 

78 def __getitem__(self, key: slice) -> List[_T]: 

79 ... 

80 

81 def __getitem__(self, key): 

82 """Retrieves item by the specified key.""" 

83 return self._values[key] 

84 

85 def __len__(self) -> int: 

86 """Returns the number of elements in the container.""" 

87 return len(self._values) 

88 

89 def __ne__(self, other: Any) -> bool: 

90 """Checks if another instance isn't equal to this one.""" 

91 # The concrete classes should define __eq__. 

92 return not self == other 

93 

94 __hash__ = None 

95 

96 def __repr__(self) -> str: 

97 return repr(self._values) 

98 

99 def _SetFrozen(self) -> None: 

100 self._frozen = True 

101 

102 def _AssureWritable(self) -> 'BaseContainer[_T]': 

103 _CheckFrozen(self._frozen, 'Container is immutable') 

104 return self 

105 

106 def sort(self, *args, **kwargs) -> None: 

107 self._AssureWritable() 

108 # Continue to support the old sort_function keyword argument. 

109 # This is expected to be a rare occurrence, so use LBYL to avoid 

110 # the overhead of actually catching KeyError. 

111 if 'sort_function' in kwargs: 

112 kwargs['cmp'] = kwargs.pop('sort_function') 

113 self._values.sort(*args, **kwargs) 

114 

115 def reverse(self) -> None: 

116 self._AssureWritable() 

117 self._values.reverse() 

118 

119 

120# TODO: Remove this. BaseContainer does *not* conform to 

121# MutableSequence, only its subclasses do. 

122collections.abc.MutableSequence.register(BaseContainer) 

123 

124 

125class RepeatedScalarFieldContainer(BaseContainer[_T], MutableSequence[_T]): 

126 """Simple, type-checked, list-like container for holding repeated scalars.""" 

127 

128 # Disallows assignment to other attributes. 

129 __slots__ = ['_type_checker', '_field'] 

130 

131 def __init__( 

132 self, 

133 message_listener: Any, 

134 type_checker: Any, 

135 field: Any = None, 

136 ) -> None: 

137 """Args: 

138 

139 message_listener: A MessageListener implementation. The 

140 RepeatedScalarFieldContainer will call this object's Modified() method 

141 when it is modified. 

142 type_checker: A type_checkers.ValueChecker instance to run on elements 

143 inserted into this container. 

144 """ 

145 super().__init__(message_listener) 

146 self._type_checker = type_checker 

147 self._field = field 

148 

149 def append(self, value: _T) -> None: 

150 """Appends an item to the list. Similar to list.append().""" 

151 self._AssureWritable() 

152 self._values.append(self._type_checker.CheckValue(value)) 

153 if not self._message_listener.dirty: 

154 self._message_listener.Modified() 

155 

156 def insert(self, key: int, value: _T) -> None: 

157 """Inserts the item at the specified position. Similar to list.insert().""" 

158 self._AssureWritable() 

159 self._values.insert(key, self._type_checker.CheckValue(value)) 

160 if not self._message_listener.dirty: 

161 self._message_listener.Modified() 

162 

163 def extend(self, elem_seq: Iterable[_T]) -> None: 

164 """Extends by appending the given iterable. Similar to list.extend().""" 

165 self._AssureWritable() 

166 elem_seq_iter = iter(elem_seq) 

167 new_values = [self._type_checker.CheckValue(elem) for elem in elem_seq_iter] 

168 if new_values: 

169 self._values.extend(new_values) 

170 self._message_listener.Modified() 

171 

172 def MergeFrom( 

173 self, 

174 other: Union['RepeatedScalarFieldContainer[_T]', Iterable[_T]], 

175 ) -> None: 

176 """Appends the contents of another repeated field of the same type to this 

177 

178 one. We do not check the types of the individual fields. 

179 """ 

180 self._AssureWritable() 

181 self._values.extend(other) 

182 self._message_listener.Modified() 

183 

184 def remove(self, elem: _T): 

185 """Removes an item from the list. Similar to list.remove().""" 

186 self._AssureWritable() 

187 self._values.remove(elem) 

188 self._message_listener.Modified() 

189 

190 def pop(self, key: Optional[int] = -1) -> _T: 

191 """Removes and returns an item at a given index. Similar to list.pop().""" 

192 self._AssureWritable() 

193 value = self._values[key] 

194 self.__delitem__(key) 

195 return value 

196 

197 @overload 

198 def __setitem__(self, key: int, value: _T) -> None: 

199 ... 

200 

201 @overload 

202 def __setitem__(self, key: slice, value: Iterable[_T]) -> None: 

203 ... 

204 

205 def __setitem__(self, key, value) -> None: 

206 """Sets the item on the specified position.""" 

207 self._AssureWritable() 

208 if isinstance(key, slice): 

209 if key.step is not None: 

210 raise ValueError('Extended slices not supported') 

211 self._values[key] = map(self._type_checker.CheckValue, value) 

212 self._message_listener.Modified() 

213 else: 

214 self._values[key] = self._type_checker.CheckValue(value) 

215 self._message_listener.Modified() 

216 

217 def __delitem__(self, key: Union[int, slice]) -> None: 

218 """Deletes the item at the specified position.""" 

219 self._AssureWritable() 

220 del self._values[key] 

221 self._message_listener.Modified() 

222 

223 def __eq__(self, other: Any) -> bool: 

224 """Compares the current instance with another one.""" 

225 if self is other: 

226 return True 

227 # Special case for the same type which should be common and fast. 

228 if isinstance(other, self.__class__): 

229 return other._values == self._values 

230 # We are presumably comparing against some other sequence type. 

231 return other == self._values 

232 

233 def __deepcopy__( 

234 self, 

235 unused_memo: Any = None, 

236 ) -> 'RepeatedScalarFieldContainer[_T]': 

237 clone = RepeatedScalarFieldContainer( 

238 copy.deepcopy(self._message_listener), self._type_checker, self._field 

239 ) 

240 clone.MergeFrom(self) 

241 return clone 

242 

243 def __reduce__(self, **kwargs) -> NoReturn: 

244 raise pickle.PickleError( 

245 "Can't pickle repeated scalar fields, convert to list first" 

246 ) 

247 

248 def __array__(self, dtype=None, copy=None): 

249 import numpy as np 

250 

251 if dtype is None: 

252 cpp_type = self._field.cpp_type 

253 if cpp_type == FieldDescriptor.CPPTYPE_INT32: 

254 dtype = np.int32 

255 elif cpp_type == FieldDescriptor.CPPTYPE_INT64: 

256 dtype = np.int64 

257 elif cpp_type == FieldDescriptor.CPPTYPE_UINT32: 

258 dtype = np.uint32 

259 elif cpp_type == FieldDescriptor.CPPTYPE_UINT64: 

260 dtype = np.uint64 

261 elif cpp_type == FieldDescriptor.CPPTYPE_DOUBLE: 

262 dtype = np.float64 

263 elif cpp_type == FieldDescriptor.CPPTYPE_FLOAT: 

264 dtype = np.float32 

265 elif cpp_type == FieldDescriptor.CPPTYPE_BOOL: 

266 dtype = np.bool 

267 elif cpp_type == FieldDescriptor.CPPTYPE_ENUM: 

268 dtype = np.int32 

269 elif self._field.type == FieldDescriptor.TYPE_BYTES: 

270 dtype = 'S' 

271 elif self._field.type == FieldDescriptor.TYPE_STRING: 

272 dtype = str 

273 else: 

274 raise SystemError( 

275 'Code should never reach here: message type detected in' 

276 ' RepeatedScalarFieldContainer' 

277 ) 

278 return np.array(self._values, dtype=dtype, copy=True) 

279 

280 

281# TODO: Constrain T to be a subtype of Message. 

282class RepeatedCompositeFieldContainer(BaseContainer[_T], MutableSequence[_T]): 

283 """Simple, list-like container for holding repeated composite fields.""" 

284 

285 # Disallows assignment to other attributes. 

286 __slots__ = ['_message_descriptor'] 

287 

288 def __init__(self, message_listener: Any, message_descriptor: Any) -> None: 

289 """Note that we pass in a descriptor instead of the generated directly, 

290 

291 since at the time we construct a _RepeatedCompositeFieldContainer we 

292 haven't yet necessarily initialized the type that will be contained in the 

293 container. 

294 

295 Args: 

296 message_listener: A MessageListener implementation. The 

297 RepeatedCompositeFieldContainer will call this object's Modified() 

298 method when it is modified. 

299 message_descriptor: A Descriptor instance describing the protocol type 

300 that should be present in this container. We'll use the _concrete_class 

301 field of this descriptor when the client calls add(). 

302 """ 

303 super().__init__(message_listener) 

304 self._message_descriptor = message_descriptor 

305 

306 def _SetFrozen(self) -> None: 

307 super()._SetFrozen() 

308 for val in self._values: 

309 val._SetFrozen() 

310 

311 def add(self, **kwargs: Any) -> _T: 

312 """Adds a new element at the end of the list and returns it. 

313 

314 Keyword arguments may be used to initialize the element. 

315 """ 

316 self._AssureWritable() 

317 new_element = self._message_descriptor._concrete_class(**kwargs) 

318 new_element._SetListener(self._message_listener) 

319 self._values.append(new_element) 

320 if not self._message_listener.dirty: 

321 self._message_listener.Modified() 

322 return new_element 

323 

324 def append(self, value: _T) -> None: 

325 """Appends one element by copying the message.""" 

326 self._AssureWritable() 

327 new_element = self._message_descriptor._concrete_class() 

328 new_element._SetListener(self._message_listener) 

329 new_element.CopyFrom(value) 

330 self._values.append(new_element) 

331 if not self._message_listener.dirty: 

332 self._message_listener.Modified() 

333 

334 def insert(self, key: int, value: _T) -> None: 

335 """Inserts the item at the specified position by copying.""" 

336 self._AssureWritable() 

337 new_element = self._message_descriptor._concrete_class() 

338 new_element._SetListener(self._message_listener) 

339 new_element.CopyFrom(value) 

340 self._values.insert(key, new_element) 

341 if not self._message_listener.dirty: 

342 self._message_listener.Modified() 

343 

344 def extend(self, elem_seq: Iterable[_T]) -> None: 

345 """Extends by appending the given sequence of elements of the same type 

346 

347 as this one, copying each individual message. 

348 """ 

349 self._AssureWritable() 

350 message_class = self._message_descriptor._concrete_class 

351 listener = self._message_listener 

352 values = self._values 

353 for message in elem_seq: 

354 new_element = message_class() 

355 new_element._SetListener(listener) 

356 new_element.MergeFrom(message) 

357 values.append(new_element) 

358 listener.Modified() 

359 

360 def MergeFrom( 

361 self, 

362 other: Union['RepeatedCompositeFieldContainer[_T]', Iterable[_T]], 

363 ) -> None: 

364 """Appends the contents of another repeated field of the same type to this 

365 

366 one, copying each individual message. 

367 """ 

368 self._AssureWritable() 

369 self.extend(other) 

370 

371 def remove(self, elem: _T) -> None: 

372 """Removes an item from the list. Similar to list.remove().""" 

373 self._AssureWritable() 

374 self._values.remove(elem) 

375 self._message_listener.Modified() 

376 

377 def pop(self, key: Optional[int] = -1) -> _T: 

378 """Removes and returns an item at a given index. Similar to list.pop().""" 

379 self._AssureWritable() 

380 value = self._values[key] 

381 self.__delitem__(key) 

382 return value 

383 

384 @overload 

385 def __setitem__(self, key: int, value: _T) -> None: 

386 ... 

387 

388 @overload 

389 def __setitem__(self, key: slice, value: Iterable[_T]) -> None: 

390 ... 

391 

392 def __setitem__(self, key, value): 

393 # This method is implemented to make RepeatedCompositeFieldContainer 

394 # structurally compatible with typing.MutableSequence. It is 

395 # otherwise unsupported and will always raise an error. 

396 raise TypeError( 

397 f'{self.__class__.__name__} object does not support item assignment' 

398 ) 

399 

400 def __delitem__(self, key: Union[int, slice]) -> None: 

401 """Deletes the item at the specified position.""" 

402 self._AssureWritable() 

403 del self._values[key] 

404 self._message_listener.Modified() 

405 

406 def __eq__(self, other: Any) -> bool: 

407 """Compares the current instance with another one.""" 

408 if self is other: 

409 return True 

410 if not isinstance(other, self.__class__): 

411 raise TypeError( 

412 'Can only compare repeated composite fields against ' 

413 'other repeated composite fields.' 

414 ) 

415 return self._values == other._values 

416 

417 

418class ScalarMap(MutableMapping[_K, _V]): 

419 """Simple, type-checked, dict-like container for holding repeated scalars.""" 

420 

421 # Disallows assignment to other attributes. 

422 __slots__ = [ 

423 '_key_checker', 

424 '_value_checker', 

425 '_values', 

426 '_message_listener', 

427 '_entry_descriptor', 

428 '_frozen', 

429 ] 

430 

431 def __init__( 

432 self, 

433 message_listener: Any, 

434 key_checker: Any, 

435 value_checker: Any, 

436 entry_descriptor: Any, 

437 ) -> None: 

438 """Args: 

439 

440 message_listener: A MessageListener implementation. 

441 The ScalarMap will call this object's Modified() method when it 

442 is modified. 

443 key_checker: A type_checkers.ValueChecker instance to run on keys 

444 inserted into this container. 

445 value_checker: A type_checkers.ValueChecker instance to run on values 

446 inserted into this container. 

447 entry_descriptor: The MessageDescriptor of a map entry: key and value. 

448 """ 

449 self._message_listener = message_listener 

450 self._key_checker = key_checker 

451 self._value_checker = value_checker 

452 self._entry_descriptor = entry_descriptor 

453 self._values = {} 

454 self._frozen = False 

455 

456 def _SetFrozen(self) -> None: 

457 self._frozen = True 

458 

459 def _AssureWritable(self) -> 'ScalarMap[_K, _V]': 

460 _CheckFrozen(self._frozen, 'Map is immutable') 

461 return self 

462 

463 def __getitem__(self, key: _K) -> _V: 

464 key = self._key_checker.CheckValue(key) 

465 try: 

466 return self._values[key] 

467 except KeyError: 

468 self._AssureWritable() 

469 val = self._value_checker.DefaultValue() 

470 self._values[key] = val 

471 return val 

472 

473 def __contains__(self, item: _K) -> bool: 

474 # We check the key's type to match the strong-typing flavor of the API. 

475 # Also this makes it easier to match the behavior of the C++ implementation. 

476 item = self._key_checker.CheckValue(item) 

477 return item in self._values 

478 

479 @overload 

480 def get(self, key: _K) -> Optional[_V]: 

481 ... 

482 

483 @overload 

484 def get(self, key: _K, default: _T) -> Union[_V, _T]: 

485 ... 

486 

487 # We need to override this explicitly, because our defaultdict-like behavior 

488 # will make the default implementation (from our base class) always insert 

489 # the key. 

490 def get(self, key, default=None): 

491 checked_key = self._key_checker.CheckValue(key) 

492 if checked_key in self._values: 

493 return self[checked_key] 

494 else: 

495 return default 

496 

497 def __setitem__(self, key: _K, value: _V) -> _T: 

498 self._AssureWritable() 

499 checked_key = self._key_checker.CheckValue(key) 

500 checked_value = self._value_checker.CheckValue(value) 

501 self._values[checked_key] = checked_value 

502 self._message_listener.Modified() 

503 

504 def __delitem__(self, key: _K) -> None: 

505 self._AssureWritable() 

506 checked_key = self._key_checker.CheckValue(key) 

507 del self._values[checked_key] 

508 self._message_listener.Modified() 

509 

510 def __len__(self) -> int: 

511 return len(self._values) 

512 

513 def __iter__(self) -> Iterator[_K]: 

514 return iter(self._values) 

515 

516 def __repr__(self) -> str: 

517 return repr(self._values) 

518 

519 def setdefault(self, key: _K, value: Optional[_V] = None) -> _V: 

520 self._AssureWritable() 

521 checked_key = self._key_checker.CheckValue(key) 

522 if value == None: 

523 raise ValueError('The value for scalar map setdefault must be set.') 

524 if checked_key not in self._values: 

525 self.__setitem__(checked_key, value) 

526 return self[key] 

527 

528 def MergeFrom(self, other: 'ScalarMap[_K, _V]') -> None: 

529 self._AssureWritable() 

530 self._values.update(other._values) 

531 self._message_listener.Modified() 

532 

533 def InvalidateIterators(self) -> None: 

534 # It appears that the only way to reliably invalidate iterators to 

535 # self._values is to ensure that its size changes. 

536 original = self._values 

537 self._values = original.copy() 

538 original[None] = None 

539 

540 # This is defined in the abstract base, but we can do it much more cheaply. 

541 def clear(self) -> None: 

542 self._AssureWritable() 

543 self._values.clear() 

544 self._message_listener.Modified() 

545 

546 def GetEntryClass(self) -> Any: 

547 return self._entry_descriptor._concrete_class 

548 

549 

550class MessageMap(MutableMapping[_K, _V]): 

551 """Simple, type-checked, dict-like container for with submessage values.""" 

552 

553 # Disallows assignment to other attributes. 

554 __slots__ = [ 

555 '_key_checker', 

556 '_values', 

557 '_message_listener', 

558 '_message_descriptor', 

559 '_entry_descriptor', 

560 '_frozen', 

561 ] 

562 

563 def __init__( 

564 self, 

565 message_listener: Any, 

566 message_descriptor: Any, 

567 key_checker: Any, 

568 entry_descriptor: Any, 

569 ) -> None: 

570 """Args: 

571 

572 message_listener: A MessageListener implementation. 

573 The ScalarMap will call this object's Modified() method when it 

574 is modified. 

575 key_checker: A type_checkers.ValueChecker instance to run on keys 

576 inserted into this container. 

577 value_checker: A type_checkers.ValueChecker instance to run on values 

578 inserted into this container. 

579 entry_descriptor: The MessageDescriptor of a map entry: key and value. 

580 """ 

581 self._message_listener = message_listener 

582 self._message_descriptor = message_descriptor 

583 self._key_checker = key_checker 

584 self._entry_descriptor = entry_descriptor 

585 self._values = {} 

586 self._frozen = False 

587 

588 def _SetFrozen(self) -> None: 

589 self._frozen = True 

590 for val in self._values.values(): 

591 val._SetFrozen() 

592 

593 def _AssureWritable(self) -> 'MessageMap[_K, _V]': 

594 _CheckFrozen(self._frozen, 'Map is immutable') 

595 return self 

596 

597 def __getitem__(self, key: _K) -> _V: 

598 key = self._key_checker.CheckValue(key) 

599 try: 

600 return self._values[key] 

601 except KeyError: 

602 self._AssureWritable() 

603 new_element = self._message_descriptor._concrete_class() 

604 new_element._SetListener(self._message_listener) 

605 self._values[key] = new_element 

606 self._message_listener.Modified() 

607 return new_element 

608 

609 def get_or_create(self, key: _K) -> _V: 

610 """get_or_create() is an alias for getitem (ie. map[key]). 

611 

612 Args: 

613 key: The key to get or create in the map. 

614 

615 This is useful in cases where you want to be explicit that the call is 

616 mutating the map. This can avoid lint errors for statements like this 

617 that otherwise would appear to be pointless statements: 

618 

619 msg.my_map[key] 

620 """ 

621 return self[key] 

622 

623 @overload 

624 def get(self, key: _K) -> Optional[_V]: 

625 ... 

626 

627 @overload 

628 def get(self, key: _K, default: _T) -> Union[_V, _T]: 

629 ... 

630 

631 # We need to override this explicitly, because our defaultdict-like behavior 

632 # will make the default implementation (from our base class) always insert 

633 # the key. 

634 def get(self, key, default=None): 

635 if key in self: 

636 return self[key] 

637 else: 

638 return default 

639 

640 def __contains__(self, item: _K) -> bool: 

641 item = self._key_checker.CheckValue(item) 

642 return item in self._values 

643 

644 def __setitem__(self, key: _K, value: _V) -> NoReturn: 

645 self._AssureWritable() 

646 raise ValueError('May not set values directly, call my_map[key].foo = 5') 

647 

648 def __delitem__(self, key: _K) -> None: 

649 self._AssureWritable() 

650 key = self._key_checker.CheckValue(key) 

651 del self._values[key] 

652 self._message_listener.Modified() 

653 

654 def __len__(self) -> int: 

655 return len(self._values) 

656 

657 def __iter__(self) -> Iterator[_K]: 

658 return iter(self._values) 

659 

660 def __repr__(self) -> str: 

661 return repr(self._values) 

662 

663 def setdefault(self, key: _K, value: Optional[_V] = None) -> _V: 

664 self._AssureWritable() 

665 raise NotImplementedError( 

666 'Set message map value directly is not supported, call' 

667 ' my_map[key].foo = 5' 

668 ) 

669 

670 def MergeFrom(self, other: 'MessageMap[_K, _V]') -> None: 

671 self._AssureWritable() 

672 # pylint: disable=protected-access 

673 for key in other._values: 

674 # According to documentation: "When parsing from the wire or when merging, 

675 # if there are duplicate map keys the last key seen is used". 

676 if key in self: 

677 del self[key] 

678 self[key].CopyFrom(other[key]) 

679 # self._message_listener.Modified() not required here, because 

680 # mutations to submessages already propagate. 

681 

682 def InvalidateIterators(self) -> None: 

683 # It appears that the only way to reliably invalidate iterators to 

684 # self._values is to ensure that its size changes. 

685 original = self._values 

686 self._values = original.copy() 

687 original[None] = None 

688 

689 # This is defined in the abstract base, but we can do it much more cheaply. 

690 def clear(self) -> None: 

691 self._AssureWritable() 

692 self._values.clear() 

693 self._message_listener.Modified() 

694 

695 def GetEntryClass(self) -> Any: 

696 return self._entry_descriptor._concrete_class 

697 

698 

699class _UnknownField: 

700 """A parsed unknown field.""" 

701 

702 # Disallows assignment to other attributes. 

703 __slots__ = ['_field_number', '_wire_type', '_data'] 

704 

705 def __init__(self, field_number, wire_type, data): 

706 self._field_number = field_number 

707 self._wire_type = wire_type 

708 self._data = data 

709 return 

710 

711 def __lt__(self, other): 

712 # pylint: disable=protected-access 

713 return self._field_number < other._field_number 

714 

715 def __eq__(self, other): 

716 if self is other: 

717 return True 

718 # pylint: disable=protected-access 

719 return ( 

720 self._field_number == other._field_number 

721 and self._wire_type == other._wire_type 

722 and self._data == other._data 

723 ) 

724 

725 

726class UnknownFieldRef: # pylint: disable=missing-class-docstring 

727 

728 def __init__(self, parent, index): 

729 self._parent = parent 

730 self._index = index 

731 

732 def _check_valid(self): 

733 if not self._parent: 

734 raise ValueError( 

735 'UnknownField does not exist. The parent message might be cleared.' 

736 ) 

737 if self._index >= len(self._parent): 

738 raise ValueError( 

739 'UnknownField does not exist. The parent message might be cleared.' 

740 ) 

741 

742 @property 

743 def field_number(self): 

744 self._check_valid() 

745 # pylint: disable=protected-access 

746 return self._parent._internal_get(self._index)._field_number 

747 

748 @property 

749 def wire_type(self): 

750 self._check_valid() 

751 # pylint: disable=protected-access 

752 return self._parent._internal_get(self._index)._wire_type 

753 

754 @property 

755 def data(self): 

756 self._check_valid() 

757 # pylint: disable=protected-access 

758 return self._parent._internal_get(self._index)._data 

759 

760 

761class UnknownFieldSet: 

762 """UnknownField container""" 

763 

764 # Disallows assignment to other attributes. 

765 __slots__ = ['_values'] 

766 

767 def __init__(self): 

768 self._values = [] 

769 

770 def __getitem__(self, index): 

771 if self._values is None: 

772 raise ValueError( 

773 'UnknownFields does not exist. The parent message might be cleared.' 

774 ) 

775 size = len(self._values) 

776 if index < 0: 

777 index += size 

778 if index < 0 or index >= size: 

779 raise IndexError('index %d out of range'.index) 

780 

781 return UnknownFieldRef(self, index) 

782 

783 def _internal_get(self, index): 

784 return self._values[index] 

785 

786 def __len__(self): 

787 if self._values is None: 

788 raise ValueError( 

789 'UnknownFields does not exist. The parent message might be cleared.' 

790 ) 

791 return len(self._values) 

792 

793 def _add(self, field_number, wire_type, data): 

794 unknown_field = _UnknownField(field_number, wire_type, data) 

795 self._values.append(unknown_field) 

796 return unknown_field 

797 

798 def __iter__(self): 

799 for i in range(len(self)): 

800 yield UnknownFieldRef(self, i) 

801 

802 def _extend(self, other): 

803 if other is None: 

804 return 

805 # pylint: disable=protected-access 

806 self._values.extend(other._values) 

807 

808 def __eq__(self, other): 

809 if self is other: 

810 return True 

811 # Sort unknown fields because their order shouldn't 

812 # affect equality test. 

813 values = list(self._values) 

814 if other is None: 

815 return not values 

816 values.sort() 

817 # pylint: disable=protected-access 

818 other_values = sorted(other._values) 

819 return values == other_values 

820 

821 def _clear(self): 

822 for value in self._values: 

823 # pylint: disable=protected-access 

824 if isinstance(value._data, UnknownFieldSet): 

825 value._data._clear() # pylint: disable=protected-access 

826 self._values = None