mirror of
https://git.notmuchmail.org/git/notmuch
synced 2024-12-23 01:44:52 +01:00
9cc026f3da
Existing users of the legacy python bindings use message.get_flags(Message.FLAG.MATCH) to determine which messages in a thread matched. Since the bindings don't provide get_flags anymore, they should provide a property analogous to the existing "excluded" property.
229 lines
6.6 KiB
Python
229 lines
6.6 KiB
Python
import collections.abc
|
|
import time
|
|
import pathlib
|
|
|
|
import pytest
|
|
|
|
import notmuch2
|
|
|
|
|
|
class TestMessage:
|
|
MaildirMsg = collections.namedtuple('MaildirMsg', ['msgid', 'path'])
|
|
|
|
@pytest.fixture
|
|
def maildir_msg(self, maildir):
|
|
msgid, path = maildir.deliver()
|
|
return self.MaildirMsg(msgid, path)
|
|
|
|
@pytest.fixture
|
|
def db(self, maildir):
|
|
with notmuch2.Database.create(maildir.path) as db:
|
|
yield db
|
|
|
|
@pytest.fixture
|
|
def msg(self, db, maildir_msg):
|
|
msg, dup = db.add(maildir_msg.path, sync_flags=False)
|
|
yield msg
|
|
|
|
def test_type(self, msg):
|
|
assert isinstance(msg, notmuch2.NotmuchObject)
|
|
assert isinstance(msg, notmuch2.Message)
|
|
|
|
def test_alive(self, msg):
|
|
assert msg.alive
|
|
|
|
def test_hash(self, msg):
|
|
assert hash(msg)
|
|
|
|
def test_eq(self, db, msg):
|
|
copy = db.get(msg.path)
|
|
assert msg == copy
|
|
|
|
def test_messageid_type(self, msg):
|
|
assert isinstance(msg.messageid, str)
|
|
assert isinstance(msg.messageid, notmuch2.BinString)
|
|
assert isinstance(bytes(msg.messageid), bytes)
|
|
|
|
def test_messageid(self, msg, maildir_msg):
|
|
assert msg.messageid == maildir_msg.msgid
|
|
|
|
def test_messageid_find(self, db, msg):
|
|
copy = db.find(msg.messageid)
|
|
assert msg.messageid == copy.messageid
|
|
|
|
def test_threadid_type(self, msg):
|
|
assert isinstance(msg.threadid, str)
|
|
assert isinstance(msg.threadid, notmuch2.BinString)
|
|
assert isinstance(bytes(msg.threadid), bytes)
|
|
|
|
def test_path_type(self, msg):
|
|
assert isinstance(msg.path, pathlib.Path)
|
|
|
|
def test_path(self, msg, maildir_msg):
|
|
assert msg.path == maildir_msg.path
|
|
|
|
def test_pathb_type(self, msg):
|
|
assert isinstance(msg.pathb, bytes)
|
|
|
|
def test_pathb(self, msg, maildir_msg):
|
|
assert msg.path == maildir_msg.path
|
|
|
|
def test_filenames_type(self, msg):
|
|
ifn = msg.filenames()
|
|
assert isinstance(ifn, collections.abc.Iterator)
|
|
|
|
def test_filenames(self, msg):
|
|
ifn = msg.filenames()
|
|
fn = next(ifn)
|
|
assert fn == msg.path
|
|
assert isinstance(fn, pathlib.Path)
|
|
with pytest.raises(StopIteration):
|
|
next(ifn)
|
|
assert list(msg.filenames()) == [msg.path]
|
|
|
|
def test_filenamesb_type(self, msg):
|
|
ifn = msg.filenamesb()
|
|
assert isinstance(ifn, collections.abc.Iterator)
|
|
|
|
def test_filenamesb(self, msg):
|
|
ifn = msg.filenamesb()
|
|
fn = next(ifn)
|
|
assert fn == msg.pathb
|
|
assert isinstance(fn, bytes)
|
|
with pytest.raises(StopIteration):
|
|
next(ifn)
|
|
assert list(msg.filenamesb()) == [msg.pathb]
|
|
|
|
def test_ghost_no(self, msg):
|
|
assert not msg.ghost
|
|
|
|
def test_matched_no(self,msg):
|
|
assert not msg.matched
|
|
|
|
def test_date(self, msg):
|
|
# XXX Someone seems to treat things as local time instead of
|
|
# UTC or the other way around.
|
|
now = int(time.time())
|
|
assert abs(now - msg.date) < 3600*24
|
|
|
|
def test_header(self, msg):
|
|
assert msg.header('from') == 'src@example.com'
|
|
|
|
def test_header_not_present(self, msg):
|
|
with pytest.raises(LookupError):
|
|
msg.header('foo')
|
|
|
|
def test_freeze(self, msg):
|
|
with msg.frozen():
|
|
msg.tags.add('foo')
|
|
msg.tags.add('bar')
|
|
msg.tags.discard('foo')
|
|
assert 'foo' not in msg.tags
|
|
assert 'bar' in msg.tags
|
|
|
|
def test_freeze_err(self, msg):
|
|
msg.tags.add('foo')
|
|
try:
|
|
with msg.frozen():
|
|
msg.tags.clear()
|
|
raise Exception('oops')
|
|
except Exception:
|
|
assert 'foo' in msg.tags
|
|
else:
|
|
pytest.fail('Context manager did not raise')
|
|
|
|
def test_replies_type(self, msg):
|
|
assert isinstance(msg.replies(), collections.abc.Iterator)
|
|
|
|
def test_replies(self, msg):
|
|
with pytest.raises(StopIteration):
|
|
next(msg.replies())
|
|
|
|
|
|
class TestProperties:
|
|
|
|
@pytest.fixture
|
|
def props(self, maildir):
|
|
msgid, path = maildir.deliver()
|
|
with notmuch2.Database.create(maildir.path) as db:
|
|
msg, dup = db.add(path, sync_flags=False)
|
|
yield msg.properties
|
|
|
|
def test_type(self, props):
|
|
assert isinstance(props, collections.abc.MutableMapping)
|
|
|
|
def test_add_single(self, props):
|
|
props['foo'] = 'bar'
|
|
assert props['foo'] == 'bar'
|
|
props.add('bar', 'baz')
|
|
assert props['bar'] == 'baz'
|
|
|
|
def test_add_dup(self, props):
|
|
props.add('foo', 'bar')
|
|
props.add('foo', 'baz')
|
|
assert props['foo'] == 'bar'
|
|
assert (set(props.getall('foo', exact=True))
|
|
== {('foo', 'bar'), ('foo', 'baz')})
|
|
|
|
def test_len(self, props):
|
|
props.add('foo', 'a')
|
|
props.add('foo', 'b')
|
|
props.add('bar', 'a')
|
|
assert len(props) == 3
|
|
assert len(props.keys()) == 2
|
|
assert len(props.values()) == 2
|
|
assert len(props.items()) == 3
|
|
|
|
def test_del(self, props):
|
|
props.add('foo', 'a')
|
|
props.add('foo', 'b')
|
|
del props['foo']
|
|
with pytest.raises(KeyError):
|
|
props['foo']
|
|
|
|
def test_remove(self, props):
|
|
props.add('foo', 'a')
|
|
props.add('foo', 'b')
|
|
props.remove('foo', 'a')
|
|
assert props['foo'] == 'b'
|
|
|
|
def test_view_abcs(self, props):
|
|
assert isinstance(props.keys(), collections.abc.KeysView)
|
|
assert isinstance(props.values(), collections.abc.ValuesView)
|
|
assert isinstance(props.items(), collections.abc.ItemsView)
|
|
|
|
def test_pop(self, props):
|
|
props.add('foo', 'a')
|
|
props.add('foo', 'b')
|
|
val = props.pop('foo')
|
|
assert val == 'a'
|
|
|
|
def test_pop_default(self, props):
|
|
with pytest.raises(KeyError):
|
|
props.pop('foo')
|
|
assert props.pop('foo', 'default') == 'default'
|
|
|
|
def test_popitem(self, props):
|
|
props.add('foo', 'a')
|
|
assert props.popitem() == ('foo', 'a')
|
|
with pytest.raises(KeyError):
|
|
props.popitem()
|
|
|
|
def test_clear(self, props):
|
|
props.add('foo', 'a')
|
|
props.clear()
|
|
assert len(props) == 0
|
|
|
|
def test_getall(self, props):
|
|
props.add('foo', 'a')
|
|
assert set(props.getall('foo')) == {('foo', 'a')}
|
|
|
|
def test_getall_prefix(self, props):
|
|
props.add('foo', 'a')
|
|
props.add('foobar', 'b')
|
|
assert set(props.getall('foo')) == {('foo', 'a'), ('foobar', 'b')}
|
|
|
|
def test_getall_exact(self, props):
|
|
props.add('foo', 'a')
|
|
props.add('foobar', 'b')
|
|
assert set(props.getall('foo', exact=True)) == {('foo', 'a')}
|