An ordered map that accepts non-hashable types for keys. It also maintains the insertion order of items, behaving as OrderedDict in that regard. These maps are constructed and read just as normal mapping types, except that they may contain arbitrary collections and other non-hashabl
| 656 | |
| 657 | |
| 658 | class OrderedMap(Mapping): |
| 659 | ''' |
| 660 | An ordered map that accepts non-hashable types for keys. It also maintains the |
| 661 | insertion order of items, behaving as OrderedDict in that regard. These maps |
| 662 | are constructed and read just as normal mapping types, except that they may |
| 663 | contain arbitrary collections and other non-hashable items as keys:: |
| 664 | |
| 665 | >>> od = OrderedMap([({'one': 1, 'two': 2}, 'value'), |
| 666 | ... ({'three': 3, 'four': 4}, 'value2')]) |
| 667 | >>> list(od.keys()) |
| 668 | [{'two': 2, 'one': 1}, {'three': 3, 'four': 4}] |
| 669 | >>> list(od.values()) |
| 670 | ['value', 'value2'] |
| 671 | |
| 672 | These constructs are needed to support nested collections in Cassandra 2.1.3+, |
| 673 | where frozen collections can be specified as parameters to others:: |
| 674 | |
| 675 | CREATE TABLE example ( |
| 676 | ... |
| 677 | value map<frozen<map<int, int>>, double> |
| 678 | ... |
| 679 | ) |
| 680 | |
| 681 | This class derives from the (immutable) Mapping API. Objects in these maps |
| 682 | are not intended be modified. |
| 683 | ''' |
| 684 | |
| 685 | def __init__(self, *args, **kwargs): |
| 686 | if len(args) > 1: |
| 687 | raise TypeError('expected at most 1 arguments, got %d' % len(args)) |
| 688 | |
| 689 | self._items = [] |
| 690 | self._index = {} |
| 691 | if args: |
| 692 | e = args[0] |
| 693 | if callable(getattr(e, 'keys', None)): |
| 694 | for k in e.keys(): |
| 695 | self._insert(k, e[k]) |
| 696 | else: |
| 697 | for k, v in e: |
| 698 | self._insert(k, v) |
| 699 | |
| 700 | for k, v in kwargs.items(): |
| 701 | self._insert(k, v) |
| 702 | |
| 703 | def _insert(self, key, value): |
| 704 | flat_key = self._serialize_key(key) |
| 705 | i = self._index.get(flat_key, -1) |
| 706 | if i >= 0: |
| 707 | self._items[i] = (key, value) |
| 708 | else: |
| 709 | self._items.append((key, value)) |
| 710 | self._index[flat_key] = len(self._items) - 1 |
| 711 | |
| 712 | __setitem__ = _insert |
| 713 | |
| 714 | def __getitem__(self, key): |
| 715 | try: |
no outgoing calls