Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions src/sortedcontainers/sortedset.py
Original file line number Diff line number Diff line change
Expand Up @@ -599,9 +599,15 @@ def symmetric_difference_update(self, other):
"""
_set = self._set
_list = self._list
_set.symmetric_difference_update(other)
_list.clear()
_list.update(_set)
candidate_set = _set.symmetric_difference(other)
candidate_list = SortedList(key=self._key)
candidate_list._reset(_list._load)
candidate_list.update(candidate_set)
# Validate keys and comparisons before changing either backing container.
# Preserve their identities because public methods are bound to them.
_set.clear()
_set.update(candidate_set)
_list.__dict__.update(candidate_list.__dict__)
return self

__ixor__ = symmetric_difference_update
Expand Down
33 changes: 33 additions & 0 deletions tests/test_sortedset_symmetric_difference_failure.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import pytest

from sortedcontainers import SortedSet


@pytest.mark.parametrize('key', [None, int])
@pytest.mark.parametrize('operation', ['method', 'ixor'])
def test_failed_symmetric_difference_preserves_membership_and_index(key, operation):
values = SortedSet([1, 2, 3], key=key)
values._reset(7)
bisect_left = values.bisect_left
isdisjoint = values.isdisjoint
incoming = iter([2, 4, 'invalid'])

with pytest.raises((TypeError, ValueError)):
if operation == 'method':
values.symmetric_difference_update(incoming)
else:
values ^= incoming

assert list(values) == [1, 2, 3]
assert len(values) == 3
assert 'invalid' not in values
assert bisect_left(2) == 1
assert isdisjoint([4])
values._check()

assert values.symmetric_difference_update(iter([2, 4])) is values
assert list(values) == [1, 3, 4]
assert bisect_left(4) == 2
assert not isdisjoint([4])
assert values._list._load == 7
values._check()