OLD | NEW |
1 # Protocol Buffers - Google's data interchange format | 1 # Protocol Buffers - Google's data interchange format |
2 # Copyright 2008 Google Inc. All rights reserved. | 2 # Copyright 2008 Google Inc. All rights reserved. |
3 # https://developers.google.com/protocol-buffers/ | 3 # https://developers.google.com/protocol-buffers/ |
4 # | 4 # |
5 # Redistribution and use in source and binary forms, with or without | 5 # Redistribution and use in source and binary forms, with or without |
6 # modification, are permitted provided that the following conditions are | 6 # modification, are permitted provided that the following conditions are |
7 # met: | 7 # met: |
8 # | 8 # |
9 # * Redistributions of source code must retain the above copyright | 9 # * Redistributions of source code must retain the above copyright |
10 # notice, this list of conditions and the following disclaimer. | 10 # notice, this list of conditions and the following disclaimer. |
(...skipping 418 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
429 raise TypeError('Can only compare repeated composite fields against ' | 429 raise TypeError('Can only compare repeated composite fields against ' |
430 'other repeated composite fields.') | 430 'other repeated composite fields.') |
431 return self._values == other._values | 431 return self._values == other._values |
432 | 432 |
433 | 433 |
434 class ScalarMap(MutableMapping): | 434 class ScalarMap(MutableMapping): |
435 | 435 |
436 """Simple, type-checked, dict-like container for holding repeated scalars.""" | 436 """Simple, type-checked, dict-like container for holding repeated scalars.""" |
437 | 437 |
438 # Disallows assignment to other attributes. | 438 # Disallows assignment to other attributes. |
439 __slots__ = ['_key_checker', '_value_checker', '_values', '_message_listener'] | 439 __slots__ = ['_key_checker', '_value_checker', '_values', '_message_listener', |
| 440 '_entry_descriptor'] |
440 | 441 |
441 def __init__(self, message_listener, key_checker, value_checker): | 442 def __init__(self, message_listener, key_checker, value_checker, |
| 443 entry_descriptor): |
442 """ | 444 """ |
443 Args: | 445 Args: |
444 message_listener: A MessageListener implementation. | 446 message_listener: A MessageListener implementation. |
445 The ScalarMap will call this object's Modified() method when it | 447 The ScalarMap will call this object's Modified() method when it |
446 is modified. | 448 is modified. |
447 key_checker: A type_checkers.ValueChecker instance to run on keys | 449 key_checker: A type_checkers.ValueChecker instance to run on keys |
448 inserted into this container. | 450 inserted into this container. |
449 value_checker: A type_checkers.ValueChecker instance to run on values | 451 value_checker: A type_checkers.ValueChecker instance to run on values |
450 inserted into this container. | 452 inserted into this container. |
| 453 entry_descriptor: The MessageDescriptor of a map entry: key and value. |
451 """ | 454 """ |
452 self._message_listener = message_listener | 455 self._message_listener = message_listener |
453 self._key_checker = key_checker | 456 self._key_checker = key_checker |
454 self._value_checker = value_checker | 457 self._value_checker = value_checker |
| 458 self._entry_descriptor = entry_descriptor |
455 self._values = {} | 459 self._values = {} |
456 | 460 |
457 def __getitem__(self, key): | 461 def __getitem__(self, key): |
458 try: | 462 try: |
459 return self._values[key] | 463 return self._values[key] |
460 except KeyError: | 464 except KeyError: |
461 key = self._key_checker.CheckValue(key) | 465 key = self._key_checker.CheckValue(key) |
462 val = self._value_checker.DefaultValue() | 466 val = self._value_checker.DefaultValue() |
463 self._values[key] = val | 467 self._values[key] = val |
464 return val | 468 return val |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
506 # self._values is to ensure that its size changes. | 510 # self._values is to ensure that its size changes. |
507 original = self._values | 511 original = self._values |
508 self._values = original.copy() | 512 self._values = original.copy() |
509 original[None] = None | 513 original[None] = None |
510 | 514 |
511 # This is defined in the abstract base, but we can do it much more cheaply. | 515 # This is defined in the abstract base, but we can do it much more cheaply. |
512 def clear(self): | 516 def clear(self): |
513 self._values.clear() | 517 self._values.clear() |
514 self._message_listener.Modified() | 518 self._message_listener.Modified() |
515 | 519 |
| 520 def GetEntryClass(self): |
| 521 return self._entry_descriptor._concrete_class |
| 522 |
516 | 523 |
517 class MessageMap(MutableMapping): | 524 class MessageMap(MutableMapping): |
518 | 525 |
519 """Simple, type-checked, dict-like container for with submessage values.""" | 526 """Simple, type-checked, dict-like container for with submessage values.""" |
520 | 527 |
521 # Disallows assignment to other attributes. | 528 # Disallows assignment to other attributes. |
522 __slots__ = ['_key_checker', '_values', '_message_listener', | 529 __slots__ = ['_key_checker', '_values', '_message_listener', |
523 '_message_descriptor'] | 530 '_message_descriptor', '_entry_descriptor'] |
524 | 531 |
525 def __init__(self, message_listener, message_descriptor, key_checker): | 532 def __init__(self, message_listener, message_descriptor, key_checker, |
| 533 entry_descriptor): |
526 """ | 534 """ |
527 Args: | 535 Args: |
528 message_listener: A MessageListener implementation. | 536 message_listener: A MessageListener implementation. |
529 The ScalarMap will call this object's Modified() method when it | 537 The ScalarMap will call this object's Modified() method when it |
530 is modified. | 538 is modified. |
531 key_checker: A type_checkers.ValueChecker instance to run on keys | 539 key_checker: A type_checkers.ValueChecker instance to run on keys |
532 inserted into this container. | 540 inserted into this container. |
533 value_checker: A type_checkers.ValueChecker instance to run on values | 541 value_checker: A type_checkers.ValueChecker instance to run on values |
534 inserted into this container. | 542 inserted into this container. |
| 543 entry_descriptor: The MessageDescriptor of a map entry: key and value. |
535 """ | 544 """ |
536 self._message_listener = message_listener | 545 self._message_listener = message_listener |
537 self._message_descriptor = message_descriptor | 546 self._message_descriptor = message_descriptor |
538 self._key_checker = key_checker | 547 self._key_checker = key_checker |
| 548 self._entry_descriptor = entry_descriptor |
539 self._values = {} | 549 self._values = {} |
540 | 550 |
541 def __getitem__(self, key): | 551 def __getitem__(self, key): |
542 try: | 552 try: |
543 return self._values[key] | 553 return self._values[key] |
544 except KeyError: | 554 except KeyError: |
545 key = self._key_checker.CheckValue(key) | 555 key = self._key_checker.CheckValue(key) |
546 new_element = self._message_descriptor._concrete_class() | 556 new_element = self._message_descriptor._concrete_class() |
547 new_element._SetListener(self._message_listener) | 557 new_element._SetListener(self._message_listener) |
548 self._values[key] = new_element | 558 self._values[key] = new_element |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
587 return len(self._values) | 597 return len(self._values) |
588 | 598 |
589 def __iter__(self): | 599 def __iter__(self): |
590 return iter(self._values) | 600 return iter(self._values) |
591 | 601 |
592 def __repr__(self): | 602 def __repr__(self): |
593 return repr(self._values) | 603 return repr(self._values) |
594 | 604 |
595 def MergeFrom(self, other): | 605 def MergeFrom(self, other): |
596 for key in other: | 606 for key in other: |
597 self[key].MergeFrom(other[key]) | 607 # According to documentation: "When parsing from the wire or when merging, |
| 608 # if there are duplicate map keys the last key seen is used". |
| 609 if key in self: |
| 610 del self[key] |
| 611 self[key].CopyFrom(other[key]) |
598 # self._message_listener.Modified() not required here, because | 612 # self._message_listener.Modified() not required here, because |
599 # mutations to submessages already propagate. | 613 # mutations to submessages already propagate. |
600 | 614 |
601 def InvalidateIterators(self): | 615 def InvalidateIterators(self): |
602 # It appears that the only way to reliably invalidate iterators to | 616 # It appears that the only way to reliably invalidate iterators to |
603 # self._values is to ensure that its size changes. | 617 # self._values is to ensure that its size changes. |
604 original = self._values | 618 original = self._values |
605 self._values = original.copy() | 619 self._values = original.copy() |
606 original[None] = None | 620 original[None] = None |
607 | 621 |
608 # This is defined in the abstract base, but we can do it much more cheaply. | 622 # This is defined in the abstract base, but we can do it much more cheaply. |
609 def clear(self): | 623 def clear(self): |
610 self._values.clear() | 624 self._values.clear() |
611 self._message_listener.Modified() | 625 self._message_listener.Modified() |
| 626 |
| 627 def GetEntryClass(self): |
| 628 return self._entry_descriptor._concrete_class |
OLD | NEW |