]> git.notmuchmail.org Git - notmuch/blob - bindings/python-cffi/tests/test_tags.py
emacs: Add new option notmuch-search-hide-excluded
[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, config=database.Database.CONFIG.EMPTY) 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, config=database.Database.CONFIG.EMPTY) 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, config=database.Database.CONFIG.EMPTY) 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,
163                                config=database.Database.CONFIG.EMPTY) as db:
164             msg = db.get(pathname)
165             yield msg.tags
166
167     def test_type(self, tagset):
168         assert isinstance(tagset, collections.abc.MutableSet)
169         assert isinstance(tagset, tags.MutableTagSet)
170
171     def test_hash(self, tagset):
172         assert not isinstance(tagset, collections.abc.Hashable)
173         with pytest.raises(TypeError):
174             hash(tagset)
175
176     def test_add(self, tagset):
177         assert 'foo' not in tagset
178         tagset.add('foo')
179         assert 'foo' in tagset
180
181     def test_discard(self, tagset):
182         assert 'inbox' in tagset
183         tagset.discard('inbox')
184         assert 'inbox' not in tagset
185
186     def test_discard_not_present(self, tagset):
187         assert 'foo' not in tagset
188         tagset.discard('foo')
189
190     def test_clear(self, tagset):
191         assert len(tagset) > 0
192         tagset.clear()
193         assert len(tagset) == 0
194
195     def test_from_maildir_flags(self, maildir, notmuch):
196         _, pathname = maildir.deliver(flagged=True)
197         notmuch('new')
198         with database.Database(maildir.path,
199                                mode=database.Mode.READ_WRITE,
200                                config=database.Database.CONFIG.EMPTY) as db:
201             msg = db.get(pathname)
202             msg.tags.discard('flagged')
203             msg.tags.from_maildir_flags()
204             assert 'flagged' in msg.tags
205
206     def test_to_maildir_flags(self, maildir, notmuch):
207         _, pathname = maildir.deliver(flagged=True)
208         notmuch('new')
209         with database.Database(maildir.path,
210                                mode=database.Mode.READ_WRITE,
211                                config=database.Database.CONFIG.EMPTY) as db:
212             msg = db.get(pathname)
213             flags = msg.path.name.split(',')[-1]
214             assert 'F' in flags
215             msg.tags.discard('flagged')
216             msg.tags.to_maildir_flags()
217             flags = msg.path.name.split(',')[-1]
218             assert 'F' not in flags
219
220     def test_isdisjoint(self, tagset):
221         assert tagset.isdisjoint(set(['spam', 'ham']))
222         assert not tagset.isdisjoint(set(['inbox']))
223
224     def test_issubset(self, tagset):
225         assert {'inbox'} <= tagset
226         assert {'inbox'}.issubset(tagset)
227         assert not {'spam'} <= tagset
228         assert not {'spam'}.issubset(tagset)
229         assert tagset <= {'inbox', 'unread', 'spam'}
230         assert tagset.issubset({'inbox', 'unread', 'spam'})
231         assert not {'inbox', 'unread', 'spam'} <= tagset
232         assert not {'inbox', 'unread', 'spam'}.issubset(tagset)
233
234     def test_issuperset(self, tagset):
235         assert {'inbox', 'unread', 'spam'} >= tagset
236         assert {'inbox', 'unread', 'spam'}.issuperset(tagset)
237         assert tagset >= {'inbox'}
238         assert tagset.issuperset({'inbox'})
239
240     def test_union(self, tagset):
241         assert {'spam'}.union(tagset) == {'inbox', 'unread', 'spam'}
242         assert tagset.union({'spam'}) == {'inbox', 'unread', 'spam'}