]> git.notmuchmail.org Git - notmuch/blob - bindings/python-cffi/tests/test_tags.py
Add missing set methods to tagsets
[notmuch] / bindings / python-cffi / tests / test_tags.py
1 """Tests for the behaviour of immutable and mutable tagsets.
2
3 This module tests the Pythonic behaviour of the sets.
4 """
5
6 import collections
7 import subprocess
8 import textwrap
9
10 import pytest
11
12 from notmuch2 import _database as database
13 from notmuch2 import _tags as tags
14
15
16 class TestImmutable:
17
18     @pytest.fixture
19     def tagset(self, maildir, notmuch):
20         """An non-empty immutable tagset.
21
22         This will have the default new mail tags: inbox, unread.
23         """
24         maildir.deliver()
25         notmuch('new')
26         with database.Database(maildir.path) as db:
27             yield db.tags
28
29     def test_type(self, tagset):
30         assert isinstance(tagset, tags.ImmutableTagSet)
31         assert isinstance(tagset, collections.abc.Set)
32
33     def test_hash(self, tagset, maildir, notmuch):
34         h0 = hash(tagset)
35         notmuch('tag', '+foo', '*')
36         with database.Database(maildir.path) as db:
37             h1 = hash(db.tags)
38         assert h0 != h1
39
40     def test_eq(self, tagset):
41         assert tagset == tagset
42
43     def test_neq(self, tagset, maildir, notmuch):
44         notmuch('tag', '+foo', '*')
45         with database.Database(maildir.path) as db:
46             assert tagset != db.tags
47
48     def test_contains(self, tagset):
49         print(tuple(tagset))
50         assert 'unread' in tagset
51         assert 'foo' not in tagset
52
53     def test_isdisjoint(self, tagset):
54         assert tagset.isdisjoint(set(['spam', 'ham']))
55         assert not tagset.isdisjoint(set(['inbox']))
56
57     def test_issubset(self, tagset):
58         assert {'inbox'} <= tagset
59         assert {'inbox'}.issubset(tagset)
60         assert tagset <= {'inbox', 'unread', 'spam'}
61         assert tagset.issubset({'inbox', 'unread', 'spam'})
62
63     def test_issuperset(self, tagset):
64         assert {'inbox', 'unread', 'spam'} >= tagset
65         assert {'inbox', 'unread', 'spam'}.issuperset(tagset)
66         assert tagset >= {'inbox'}
67         assert tagset.issuperset({'inbox'})
68
69     def test_iter(self, tagset):
70         expected = sorted(['unread', 'inbox'])
71         found = []
72         for tag in tagset:
73             assert isinstance(tag, str)
74             found.append(tag)
75         assert expected == sorted(found)
76
77     def test_special_iter(self, tagset):
78         expected = sorted([b'unread', b'inbox'])
79         found = []
80         for tag in tagset.iter():
81             assert isinstance(tag, bytes)
82             found.append(tag)
83         assert expected == sorted(found)
84
85     def test_special_iter_codec(self, tagset):
86         for tag in tagset.iter(encoding='ascii', errors='surrogateescape'):
87             assert isinstance(tag, str)
88
89     def test_len(self, tagset):
90         assert len(tagset) == 2
91
92     def test_and(self, tagset):
93         common = tagset & {'unread'}
94         assert isinstance(common, set)
95         assert isinstance(common, collections.abc.Set)
96         assert common == {'unread'}
97         common = tagset.intersection({'unread'})
98         assert isinstance(common, set)
99         assert isinstance(common, collections.abc.Set)
100         assert common == {'unread'}
101
102     def test_or(self, tagset):
103         res = tagset | {'foo'}
104         assert isinstance(res, set)
105         assert isinstance(res, collections.abc.Set)
106         assert res == {'unread', 'inbox', 'foo'}
107         res = tagset.union({'foo'})
108         assert isinstance(res, set)
109         assert isinstance(res, collections.abc.Set)
110         assert res == {'unread', 'inbox', 'foo'}
111
112     def test_sub(self, tagset):
113         res = tagset - {'unread'}
114         assert isinstance(res, set)
115         assert isinstance(res, collections.abc.Set)
116         assert res == {'inbox'}
117         res = tagset.difference({'unread'})
118         assert isinstance(res, set)
119         assert isinstance(res, collections.abc.Set)
120         assert res == {'inbox'}
121
122     def test_rsub(self, tagset):
123         res = {'foo', 'unread'} - tagset
124         assert isinstance(res, set)
125         assert isinstance(res, collections.abc.Set)
126         assert res == {'foo'}
127
128     def test_xor(self, tagset):
129         res = tagset ^ {'unread', 'foo'}
130         assert isinstance(res, set)
131         assert isinstance(res, collections.abc.Set)
132         assert res == {'inbox', 'foo'}
133         res = tagset.symmetric_difference({'unread', 'foo'})
134         assert isinstance(res, set)
135         assert isinstance(res, collections.abc.Set)
136         assert res == {'inbox', 'foo'}
137
138     def test_rxor(self, tagset):
139         res = {'unread', 'foo'} ^ tagset
140         assert isinstance(res, set)
141         assert isinstance(res, collections.abc.Set)
142         assert res == {'inbox', 'foo'}
143
144     def test_copy(self, tagset):
145         res = tagset.copy()
146         assert isinstance(res, set)
147         assert isinstance(res, collections.abc.Set)
148         assert res == {'inbox', 'unread'}
149
150
151 class TestMutableTagset:
152
153     @pytest.fixture
154     def tagset(self, maildir, notmuch):
155         """An non-empty mutable tagset.
156
157         This will have the default new mail tags: inbox, unread.
158         """
159         _, pathname = maildir.deliver()
160         notmuch('new')
161         with database.Database(maildir.path,
162                                mode=database.Mode.READ_WRITE) as db:
163             msg = db.get(pathname)
164             yield msg.tags
165
166     def test_type(self, tagset):
167         assert isinstance(tagset, collections.abc.MutableSet)
168         assert isinstance(tagset, tags.MutableTagSet)
169
170     def test_hash(self, tagset):
171         assert not isinstance(tagset, collections.abc.Hashable)
172         with pytest.raises(TypeError):
173             hash(tagset)
174
175     def test_add(self, tagset):
176         assert 'foo' not in tagset
177         tagset.add('foo')
178         assert 'foo' in tagset
179
180     def test_discard(self, tagset):
181         assert 'inbox' in tagset
182         tagset.discard('inbox')
183         assert 'inbox' not in tagset
184
185     def test_discard_not_present(self, tagset):
186         assert 'foo' not in tagset
187         tagset.discard('foo')
188
189     def test_clear(self, tagset):
190         assert len(tagset) > 0
191         tagset.clear()
192         assert len(tagset) == 0
193
194     def test_from_maildir_flags(self, maildir, notmuch):
195         _, pathname = maildir.deliver(flagged=True)
196         notmuch('new')
197         with database.Database(maildir.path,
198                                mode=database.Mode.READ_WRITE) as db:
199             msg = db.get(pathname)
200             msg.tags.discard('flagged')
201             msg.tags.from_maildir_flags()
202             assert 'flagged' in msg.tags
203
204     def test_to_maildir_flags(self, maildir, notmuch):
205         _, pathname = maildir.deliver(flagged=True)
206         notmuch('new')
207         with database.Database(maildir.path,
208                                mode=database.Mode.READ_WRITE) as db:
209             msg = db.get(pathname)
210             flags = msg.path.name.split(',')[-1]
211             assert 'F' in flags
212             msg.tags.discard('flagged')
213             msg.tags.to_maildir_flags()
214             flags = msg.path.name.split(',')[-1]
215             assert 'F' not in flags
216
217     def test_isdisjoint(self, tagset):
218         assert tagset.isdisjoint(set(['spam', 'ham']))
219         assert not tagset.isdisjoint(set(['inbox']))
220
221     def test_issubset(self, tagset):
222         assert {'inbox'} <= tagset
223         assert {'inbox'}.issubset(tagset)
224         assert not {'spam'} <= tagset
225         assert not {'spam'}.issubset(tagset)
226         assert tagset <= {'inbox', 'unread', 'spam'}
227         assert tagset.issubset({'inbox', 'unread', 'spam'})
228         assert not {'inbox', 'unread', 'spam'} <= tagset
229         assert not {'inbox', 'unread', 'spam'}.issubset(tagset)
230
231     def test_issuperset(self, tagset):
232         assert {'inbox', 'unread', 'spam'} >= tagset
233         assert {'inbox', 'unread', 'spam'}.issuperset(tagset)
234         assert tagset >= {'inbox'}
235         assert tagset.issuperset({'inbox'})
236
237     def test_union(self, tagset):
238         assert {'spam'}.union(tagset) == {'inbox', 'unread', 'spam'}
239         assert tagset.union({'spam'}) == {'inbox', 'unread', 'spam'}