6 import util.coroutines as coroutines
7 import util.misc as misc_utils
10 _moduleLogger = logging.getLogger(__name__)
13 class Addressbook(object):
18 def __init__(self, backend, asyncPool):
19 self._backend = backend
21 self._asyncPool = asyncPool
23 self.updateSignalHandler = coroutines.CoTee()
25 def update(self, force=False):
26 if not force and self._numbers:
28 self._asyncPool.add_task(
29 self._backend.get_contacts,
32 self._on_get_contacts,
33 self._on_get_contacts_failed,
36 def _on_get_contacts(self, contacts):
37 oldContacts = self._numbers
38 oldContactNumbers = set(self.get_numbers())
40 self._numbers = self._populate_contacts(contacts)
41 newContactNumbers = set(self.get_numbers())
43 addedContacts = newContactNumbers - oldContactNumbers
44 removedContacts = oldContactNumbers - newContactNumbers
45 changedContacts = set(
47 for contactNumber in newContactNumbers.intersection(oldContactNumbers)
48 if self._numbers[contactNumber] != oldContacts[contactNumber]
51 if addedContacts or removedContacts or changedContacts:
52 message = self, addedContacts, removedContacts, changedContacts
53 self.updateSignalHandler.stage.send(message)
55 @misc_utils.log_exception(_moduleLogger)
56 def _on_get_contacts_failed(self, error):
57 _moduleLogger.error(error)
59 def get_numbers(self):
60 return self._numbers.iterkeys()
62 def get_contact_name(self, strippedNumber):
64 @throws KeyError if contact not in list (so client can choose what to display)
66 return self._numbers[strippedNumber][0]
68 def get_phone_type(self, strippedNumber):
70 return self._numbers[strippedNumber][1]
74 def is_blocked(self, strippedNumber):
76 return self._numbers[strippedNumber][2]["response"] == self._RESPONSE_BLOCKED
80 def _populate_contacts(self, contacts):
82 for contactId, contactDetails in contacts:
83 contactName = contactDetails["name"]
86 misc_utils.normalize_number(numberDetails["phoneNumber"]),
87 numberDetails.get("phoneType", "Mobile"),
89 for numberDetails in contactDetails["numbers"]
92 (number, (contactName, phoneType, contactDetails))
93 for (number, phoneType) in contactNumbers