diff --git a/src/sortedcontainers/sorteddict.py b/src/sortedcontainers/sorteddict.py index 273c9ce..4e37615 100644 --- a/src/sortedcontainers/sorteddict.py +++ b/src/sortedcontainers/sorteddict.py @@ -497,16 +497,16 @@ def update(self, *args, **kwargs): :param kwargs: keyword arguments mapping """ - if not self: - dict.update(self, *args, **kwargs) - self._list_update(dict.__iter__(self)) - return - if not kwargs and len(args) == 1 and isinstance(args[0], dict): pairs = args[0] else: pairs = dict(*args, **kwargs) + if not self: + dict.update(self, pairs) + self._list_update(dict.__iter__(self)) + return + if (10 * len(pairs)) > len(self): dict.update(self, pairs) self._list_clear() diff --git a/tests/test_coverage_sorteddict.py b/tests/test_coverage_sorteddict.py index ad59290..1206686 100644 --- a/tests/test_coverage_sorteddict.py +++ b/tests/test_coverage_sorteddict.py @@ -582,3 +582,29 @@ def test_ior(): temp2 = SortedDict(mapping[13:]) temp1 |= temp2 assert temp1 == dict(mapping) + + +@pytest.mark.parametrize('initial', [{}, {'existing': 0}]) +@pytest.mark.parametrize('key', [None, len]) +def test_update_malformed_pairs_preserves_index(initial, key): + temp = SortedDict(key, initial) + with pytest.raises(ValueError): + temp.update([('valid', 1), ('invalid',)]) + temp._check() + assert dict(temp.items()) == initial + temp['next'] = 2 + temp._check() + assert temp.pop('next') == 2 + + +@pytest.mark.parametrize('initial', [{}, {'existing': 0}]) +def test_update_failing_iterator_preserves_index(initial): + def pairs(): + yield 'valid', 1 + raise RuntimeError('source failed') + + temp = SortedDict(initial) + with pytest.raises(RuntimeError, match='source failed'): + temp.update(pairs()) + temp._check() + assert dict(temp.items()) == initial