1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
|
# Copyright (C) 2011-2012 Patrick Totzke <patricktotzke@gmail.com>
# This file is released under the GNU GPL, version 3 or a later revision.
# For further details see the COPYING file
import re
import os
from alot.settings.utils import read_config
from helper import call_cmd
from alot.helper import split_commandstring
class AddressbookError(Exception):
pass
class AddressBook(object):
"""can look up email addresses and realnames for contacts.
.. note::
This is an abstract class that leaves :meth:`get_contacts`
unspecified. See :class:`AbookAddressBook` and
:class:`MatchSdtoutAddressbook` for implementations.
"""
def __init__(self, ignorecase=True):
self.reflags = re.IGNORECASE if ignorecase else 0
def get_contacts(self):
"""list all contacts tuples in this abook as (name, email) tuples"""
return []
def lookup(self, query=''):
"""looks up all contacts where name or address match query"""
res = []
query = '.*%s.*' % query
for name, email in self.get_contacts():
try:
if re.match(query, name, self.reflags) or \
re.match(query, email, self.reflags):
res.append((name, email))
except:
pass
return res
class AbookAddressBook(AddressBook):
""":class:`AddressBook` that parses abook's config/database files"""
def __init__(self, path='~/.abook/addressbook', **kwargs):
"""
:param path: path to theme file
:type path: str
"""
AddressBook.__init__(self, **kwargs)
DEFAULTSPATH = os.path.join(os.path.dirname(__file__), 'defaults')
self._spec = os.path.join(DEFAULTSPATH, 'abook_contacts.spec')
path = os.path.expanduser(path)
self._config = read_config(path, self._spec)
del(self._config['format'])
def get_contacts(self):
c = self._config
res = []
for id in c.sections:
for email in c[id]['email']:
if email:
res.append((c[id]['name'], email))
return res
class MatchSdtoutAddressbook(AddressBook):
""":class:`AddressBook` that parses a shell command's output for lookups"""
def __init__(self, command, match=None, **kwargs):
"""
:param command: lookup command
:type command: str
:param match: regular expression used to match contacts in `commands`
output to stdout. Must define subparts named "email" and
"name". Defaults to
:regexp:`^(?P<email>[^@]+@[^\t]+)\t+(?P<name>[^\t]+)`.
:type match: str
"""
AddressBook.__init__(self, **kwargs)
self.command = command
if not match:
self.match = '^(?P<email>[^@]+@[^\t]+)\t+(?P<name>[^\t]+)'
else:
self.match = match
def get_contacts(self):
return self.lookup('\'\'')
def lookup(self, prefix):
cmdlist = split_commandstring(self.command)
resultstring, errmsg, retval = call_cmd(cmdlist + [prefix])
if retval != 0:
msg = 'abook command "%s" returned with ' % self.command
msg += 'return code %d' % retval
if errmsg:
msg += ':\n%s' % errmsg
raise AddressbookError(msg)
if not resultstring:
return []
lines = resultstring.splitlines()
res = []
for l in lines:
m = re.match(self.match, l, self.reflags)
if m:
info = m.groupdict()
if 'email' and 'name' in info:
email = info['email'].strip()
name = info['name']
res.append((name, email))
return res
|