Skip to content

Instantly share code, notes, and snippets.

@deanishe
Created December 3, 2013 16:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save deanishe/7772540 to your computer and use it in GitHub Desktop.
Save deanishe/7772540 to your computer and use it in GitHub Desktop.
Search Mac Address Book with Python via the Scripting Bridge
#!/usr/bin/python
# -*- coding: utf-8 -*-
# vim: fileencoding=utf-8
"""
Search Mac Address Book contacts via official API
"""
from __future__ import print_function, unicode_literals
import sys
from time import time
from collections import defaultdict
import AddressBook as ab
def _make_list(cdw):
"""Make a list from CoreDataWrapper"""
if not cdw:
return []
values = []
for i in range(cdw.count()):
values.append(unicode(cdw.valueAtIndex_(i)))
return values
# map dict keys to AB properties and conversion funcs
_text_property_map = {
# output key : (property, conversion func)
'first_name': (ab.kABFirstNameProperty, None),
'last_name': (ab.kABLastNameProperty, None),
'company': (ab.kABOrganizationProperty, None),
'emails': (ab.kABEmailProperty, _make_list),
}
def ab_person_to_dict(person):
"""Convert ABPerson to Python dict"""
d = {}
d['emails'] = []
for key in _text_property_map:
prop, func = _text_property_map[key]
value = person.valueForProperty_(prop)
if func:
value = func(value)
if not value:
value = ''
d[key] = value
return d
def search(query):
"""Search Mac Address Book and return pythonified results"""
address_book = ab.ABAddressBook.sharedAddressBook()
# build search criteria
criteria = []
for key in _text_property_map:
prop, func = _text_property_map[key]
criteria.append(
ab.ABPerson.searchElementForProperty_label_key_value_comparison_(
prop,
None, None,
query,
ab.kABContainsSubStringCaseInsensitive)
)
search = ab.ABSearchElement.searchElementForConjunction_children_(
ab.kABSearchOr, criteria)
# search Address Book
people = address_book.recordsMatchingSearchElement_(search)
results = defaultdict(set)
for person in [ab_person_to_dict(person) for person in people]:
key = '{} {}'.format(person.get('first_name', ''),
person.get('last_name', '')).strip()
for addr in person['emails']:
results[key].add(addr)
return results
def main():
if len(sys.argv) < 2:
print('Usage : ABSearch.py <query> [<query> ...]')
return 1
for query in sys.argv[1:]:
s = time()
people = search(query)
print("{} results for '{}' in {:.4f} seconds".format(len(people),
query,
time() - s))
print('-' * 40)
for name, addrs in people.items():
print('{} : {}'.format(name, list(addrs)))
print()
if __name__ == '__main__':
sys.exit(main())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment