6 import util.coroutines as coroutines
7 import util.misc as misc_utils
10 _moduleLogger = logging.getLogger("gvoice.addressbook")
13 class Addressbook(object):
18 def __init__(self, backend):
19 self._backend = backend
22 self.updateSignalHandler = coroutines.CoTee()
24 def update(self, force=False):
25 if not force and self._numbers:
27 oldContacts = self._numbers
28 oldContactNumbers = set(self.get_numbers())
31 self._populate_contacts()
32 newContactNumbers = set(self.get_numbers())
34 addedContacts = newContactNumbers - oldContactNumbers
35 removedContacts = oldContactNumbers - newContactNumbers
36 changedContacts = set(
38 for contactNumber in newContactNumbers.intersection(oldContactNumbers)
39 if self._numbers[contactNumber] != oldContacts[contactNumber]
42 if addedContacts or removedContacts or changedContacts:
43 message = self, addedContacts, removedContacts, changedContacts
44 self.updateSignalHandler.stage.send(message)
46 def get_numbers(self):
47 return self._numbers.iterkeys()
49 def get_contact_name(self, strippedNumber):
51 @throws KeyError if contact not in list (so client can choose what to display)
53 return self._numbers[strippedNumber][0]
55 def get_phone_type(self, strippedNumber):
57 return self._numbers[strippedNumber][1]
61 def is_blocked(self, strippedNumber):
63 return self._numbers[strippedNumber][2]["response"] == self._RESPONSE_BLOCKED
67 def _populate_contacts(self):
70 contacts = self._backend.get_contacts()
71 for contactId, contactDetails in contacts:
72 contactName = contactDetails["name"]
75 misc_utils.normalize_number(numberDetails["phoneNumber"]),
76 numberDetails.get("phoneType", "Mobile"),
78 for numberDetails in contactDetails["numbers"]
81 (number, (contactName, phoneType, contactDetails))
82 for (number, phoneType) in contactNumbers