Add missing set methods to tagsets

Even though we use collections.abc.Set which implements all these
methods under their operator names, the actual named variations of
these methods are shockingly missing.  So let's add them manually.
This commit is contained in:
Floris Bruynooghe 2020-06-14 20:33:55 +02:00 committed by David Bremner
parent 963e363a23
commit a00f3a1f7a
2 changed files with 83 additions and 0 deletions

View file

@ -110,6 +110,27 @@ class ImmutableTagSet(base.NotmuchObject, collections.abc.Set):
def __eq__(self, other): def __eq__(self, other):
return tuple(sorted(self.iter())) == tuple(sorted(other.iter())) return tuple(sorted(self.iter())) == tuple(sorted(other.iter()))
def issubset(self, other):
return self <= other
def issuperset(self, other):
return self >= other
def union(self, other):
return self | other
def intersection(self, other):
return self & other
def difference(self, other):
return self - other
def symmetric_difference(self, other):
return self ^ other
def copy(self):
return set(self)
def __hash__(self): def __hash__(self):
return hash(tuple(self.iter())) return hash(tuple(self.iter()))

View file

@ -50,6 +50,22 @@ class TestImmutable:
assert 'unread' in tagset assert 'unread' in tagset
assert 'foo' not in tagset assert 'foo' not in tagset
def test_isdisjoint(self, tagset):
assert tagset.isdisjoint(set(['spam', 'ham']))
assert not tagset.isdisjoint(set(['inbox']))
def test_issubset(self, tagset):
assert {'inbox'} <= tagset
assert {'inbox'}.issubset(tagset)
assert tagset <= {'inbox', 'unread', 'spam'}
assert tagset.issubset({'inbox', 'unread', 'spam'})
def test_issuperset(self, tagset):
assert {'inbox', 'unread', 'spam'} >= tagset
assert {'inbox', 'unread', 'spam'}.issuperset(tagset)
assert tagset >= {'inbox'}
assert tagset.issuperset({'inbox'})
def test_iter(self, tagset): def test_iter(self, tagset):
expected = sorted(['unread', 'inbox']) expected = sorted(['unread', 'inbox'])
found = [] found = []
@ -78,18 +94,30 @@ class TestImmutable:
assert isinstance(common, set) assert isinstance(common, set)
assert isinstance(common, collections.abc.Set) assert isinstance(common, collections.abc.Set)
assert common == {'unread'} assert common == {'unread'}
common = tagset.intersection({'unread'})
assert isinstance(common, set)
assert isinstance(common, collections.abc.Set)
assert common == {'unread'}
def test_or(self, tagset): def test_or(self, tagset):
res = tagset | {'foo'} res = tagset | {'foo'}
assert isinstance(res, set) assert isinstance(res, set)
assert isinstance(res, collections.abc.Set) assert isinstance(res, collections.abc.Set)
assert res == {'unread', 'inbox', 'foo'} assert res == {'unread', 'inbox', 'foo'}
res = tagset.union({'foo'})
assert isinstance(res, set)
assert isinstance(res, collections.abc.Set)
assert res == {'unread', 'inbox', 'foo'}
def test_sub(self, tagset): def test_sub(self, tagset):
res = tagset - {'unread'} res = tagset - {'unread'}
assert isinstance(res, set) assert isinstance(res, set)
assert isinstance(res, collections.abc.Set) assert isinstance(res, collections.abc.Set)
assert res == {'inbox'} assert res == {'inbox'}
res = tagset.difference({'unread'})
assert isinstance(res, set)
assert isinstance(res, collections.abc.Set)
assert res == {'inbox'}
def test_rsub(self, tagset): def test_rsub(self, tagset):
res = {'foo', 'unread'} - tagset res = {'foo', 'unread'} - tagset
@ -102,6 +130,10 @@ class TestImmutable:
assert isinstance(res, set) assert isinstance(res, set)
assert isinstance(res, collections.abc.Set) assert isinstance(res, collections.abc.Set)
assert res == {'inbox', 'foo'} assert res == {'inbox', 'foo'}
res = tagset.symmetric_difference({'unread', 'foo'})
assert isinstance(res, set)
assert isinstance(res, collections.abc.Set)
assert res == {'inbox', 'foo'}
def test_rxor(self, tagset): def test_rxor(self, tagset):
res = {'unread', 'foo'} ^ tagset res = {'unread', 'foo'} ^ tagset
@ -109,6 +141,12 @@ class TestImmutable:
assert isinstance(res, collections.abc.Set) assert isinstance(res, collections.abc.Set)
assert res == {'inbox', 'foo'} assert res == {'inbox', 'foo'}
def test_copy(self, tagset):
res = tagset.copy()
assert isinstance(res, set)
assert isinstance(res, collections.abc.Set)
assert res == {'inbox', 'unread'}
class TestMutableTagset: class TestMutableTagset:
@ -175,3 +213,27 @@ class TestMutableTagset:
msg.tags.to_maildir_flags() msg.tags.to_maildir_flags()
flags = msg.path.name.split(',')[-1] flags = msg.path.name.split(',')[-1]
assert 'F' not in flags assert 'F' not in flags
def test_isdisjoint(self, tagset):
assert tagset.isdisjoint(set(['spam', 'ham']))
assert not tagset.isdisjoint(set(['inbox']))
def test_issubset(self, tagset):
assert {'inbox'} <= tagset
assert {'inbox'}.issubset(tagset)
assert not {'spam'} <= tagset
assert not {'spam'}.issubset(tagset)
assert tagset <= {'inbox', 'unread', 'spam'}
assert tagset.issubset({'inbox', 'unread', 'spam'})
assert not {'inbox', 'unread', 'spam'} <= tagset
assert not {'inbox', 'unread', 'spam'}.issubset(tagset)
def test_issuperset(self, tagset):
assert {'inbox', 'unread', 'spam'} >= tagset
assert {'inbox', 'unread', 'spam'}.issuperset(tagset)
assert tagset >= {'inbox'}
assert tagset.issuperset({'inbox'})
def test_union(self, tagset):
assert {'spam'}.union(tagset) == {'inbox', 'unread', 'spam'}
assert tagset.union({'spam'}) == {'inbox', 'unread', 'spam'}