diff options
author | Yury Selivanov <yury@magic.io> | 2018-12-13 12:48:29 -0500 |
---|---|---|
committer | Yury Selivanov <yury@magic.io> | 2018-12-13 12:55:50 -0500 |
commit | 7642044a0c6dd484e259933fce976b2725f9ac59 (patch) | |
tree | 87864a69b3b78beb30a3ec9d4242e82f13b14738 /immutables/map.py | |
parent | 5a9c2fa8131819523403a6b7a92ad0918f1c595d (diff) | |
download | immutables-7642044a0c6dd484e259933fce976b2725f9ac59.tar.gz immutables-7642044a0c6dd484e259933fce976b2725f9ac59.zip |
Add MapMutation.update(); make creating Map from a Map faster; fix bugs
* Add new MapMutation.update() method that behaves like
MutableMapping.update()
* Make it faster to create a Map() from another Map() -- it's now an
O(1) operation.
* update() method had a bug that could cause the update Map object to
have a wrong number of elements.
Diffstat (limited to 'immutables/map.py')
-rw-r--r-- | immutables/map.py | 61 |
1 files changed, 61 insertions, 0 deletions
diff --git a/immutables/map.py b/immutables/map.py index fc40ac8..7b230dd 100644 --- a/immutables/map.py +++ b/immutables/map.py @@ -438,6 +438,14 @@ class Map: self.__root = BitmapNode(0, 0, [], 0) self.__hash = -1 + if isinstance(col, Map): + self.__count = col.__count + self.__root = col.__root + self.__hash = col.__hash + col = None + elif isinstance(col, MapMutation): + raise TypeError('cannot create Maps from MapMutations') + if col or kw: init = self.update(col, **kw) self.__count = init.__count @@ -640,6 +648,9 @@ class MapMutation: self.finish() return False + def __iter__(self): + raise TypeError('{} is not iterable'.format(type(self))) + def __delitem__(self, key): if self.__mutid == 0: raise ValueError('mutation {!r} has been finished'.format(self)) @@ -707,6 +718,56 @@ class MapMutation: else: return True + def update(self, col=None, **kw): + it = None + if col is not None: + if hasattr(col, 'items'): + it = iter(col.items()) + else: + it = iter(col) + + if it is not None: + if kw: + it = iter(itertools.chain(it, kw.items())) + else: + if kw: + it = iter(kw.items()) + + if it is None: + + return self + + root = self.__root + count = self.__count + + i = 0 + while True: + try: + tup = next(it) + except StopIteration: + break + + try: + tup = tuple(tup) + except TypeError: + raise TypeError( + 'cannot convert map update ' + 'sequence element #{} to a sequence'.format(i)) from None + key, val, *r = tup + if r: + raise ValueError( + 'map update sequence element #{} has length ' + '{}; 2 is required'.format(i, len(r) + 2)) + + root, added = root.assoc(0, map_hash(key), key, val, self.__mutid) + if added: + count += 1 + + i += 1 + + self.__root = root + self.__count = count + def finish(self): self.__mutid = 0 return Map._new(self.__count, self.__root) |