TweetFollow Us on Twitter

Mac in the Shell-Python on the Mac: PyObjC

Volume Number: 25
Issue Number: 06
Column Tag: Mac in the Shell

Mac in the Shell-Python on the Mac: PyObjC

Writing native Cocoa apps using Python

by Edward Marczak

Introduction

Over the last few months, we've been covering the basics of Python. Aside from a few OS X-specific issues raised in the first article (how to get the built-in docs working, etc.), you could really take the lessons learned anywhere - Linux, Windows, or any platform where you find a Python runtime. We needed those basics - and we have more to cover, certainly. However, this is MacTech. There's plenty that one can do with some very basic Python and Python/Objective-C bridge, letting you tap into Cocoa. Cocoa? Isn't that reserved for Obj-C developers? Nope. While MacTech has covered this concept before (Scott Corely, "Python Cocoa: Delicious," February 2009), I'd like to put together the lessons learned in this column along with a more utilitarian approach.

Read The Fine Manual

Anytime we're working with Cocoa and the technologies in OS X, we'll probably be pouring through the developer references at http://developer.apple.com. You'll need an ADC account to do so. Even the free variety will do, so, go sign up now if you haven't already!

Once you're logged into the Developer Connection, head to the developer docs at http://developer.apple.com/documentation/. More often than not, you'll search on the topic you're after. Sometimes, you find good documentation spread out over several categories. Today, we'll be looking at getting information out of Address Book. True to form, the docs are somewhat spread out. I'll make reference to each as I use it. In short, for now, just search on "address book".

Translating Obj-C

First, why would we want to do this? There are certainly cases when developing for OS X where straight Obj-C is the right choice. However, I'm taking this from a System Administrator's point of view. Often, a System Administrator is already writing basic scripts in bash. I love bash, but there's only so far that it'll get you without becoming painful. If you're writing a script in bash and it passes the 4 functions milestone, it may be time to consider a language more suited to your task. For example, bash isn't really great with databases.

Sure, you can use the mysql binary, pipe the output to awk, and manipulate results from there. But is that the best use of your time and talent? Ever deal with arrays in bash? Pain. While I may recommend Python or Ruby as a step up in general, these languages are made even more special under OS X thanks to Apple's inclusion of an Obj-C bridge. BridgeSupport opens up OS X's native APIs to Python, Ruby and JavaScript. This is available and standard on every Mac running 10.5 or higher. (10.4 support is available, but you'll need to install it yourself, which is outside the scope of this article). BridgeSupport deals with all of the behind-the-scenes work of converting between Python and the native frameworks. The first challenge to this technique is interpreting the documentation. We're going to code all of this in Python, and the docs are directed at people writing in C and Objective-C. Anyone remember having to translate Mac Toolbox API calls from Pascal to C? I digress...

Now that we've covered Python classes, you know about sending a message to an object using dot notation. In last month's column, the BankClass example class contained deposit and withdraw methods. A new class could be created and a method called in the following manner:

acct = Account('Joan', 'Smith')    # Create new account
acct1.Deposit(50)       # Note use of class method here

However, if we got this information from Apple's developer documentation, you'd see something like this:

[acct1 Deposit:50]

This was covered in depth in the "Python Cocoa: Delicious" article referenced earlier, but I'll cover the basic rules here.

As you can see, Obj-C uses square brackets to send messages to objects. The easiest call to translate is a simple message with no parameters. This:

[object message];

in Python becomes:

object.message()

When a method takes parameters, Obj-C places them in-line:

[object message:40 key:50];

Python keeps its usual format here, separating the method name and parameters. Each message and parameter gains a trailing underscore character:

object.message_key_(40,50)

Essentially, each colon is replaced by an underscore - even if there's only one parameter. For example:

object.message_(40)

To instantiate an objective-c class in the first place is fairly straightforward.

object = NSObject.alloc().init()

Let's see all of this in action.

Reading the Address Book

The beauty of using a language like Python is that you can author in any editor you like, save and run. This skips the compile/link phase so familiar to Obj-C developers. So, pull up your favorite editor-remember, too, that most editors will be able to recognize Python code and syntax color, indent properly and so on, for you-and let's go.

Contained in /System/Library/Frameworks/Python.frame-work/ are the modules that Python uses for BridgeSupport. These can simply be imported into Python. First thing is first, our magic shebang line:

#!/usr/bin/env python

(Remember, if you have multiple versions of python on your system for some reason, under 10.5, the built-in BridgeSupport only works with Python 2.5. If you need you need to explicitly call that version, then do so). From here, we'll import the AddressBook framework:

from AddressBook import *

It's rare that I like or use the 'from blah import *' style, but there are times when it makes perfect sense. This, I feel, is one of them. We talked extensively about imports and namespaces in previous articles.

Let's create a new instance of an address book object:

aBook = ABAddressBook.sharedAddressBook()

Painless, right? This returns the address book for the logged-in user. Keeping this simple, let's grab the 'me' card for the logged in user and print it out:

myRecord = aBook.me()
print myRecord

That's it! In 3 lines of code, we get a good amount of information. Here's the output:

ABPerson (0x1ab0a40) {
   ABPersonFlags  : 0
   ABRelatedNames : {
      *  child  Edward R Marczak
}
   Address       : {
      *  work  {
    City = Anytown;
    Country = USA;
    CountryCode = us;
    State = AA;
    Street = "555 Any Street";
    ZIP = 11111;
}
}
   AIMInstant     : {
      *  home  myaim
}
   Creation       : 2005-10-28 09:45:40 -0400
   Email          : {
      *  work  marczak@radiotope.com
}
   First          : Edward
   JobTitle       : Owner
   Last           : Marczak
   Middle         : R
   Modification   : 2009-01-14 11:11:25 -0500
   Organization   : Radiotope
   Phone          : {
      *  mobile  555-555-5185
        home    555 555-5370
        main    555-555-5489
}
   Title          : Mr.
   Unique ID      : B3AD0F6B-4AB8-4E84-82C4-BF1EB7475659:ABPerson
}

Each of the properties in the record can be accessed and iterated over individually. Each property has a unique name used for this purpose. An illuminating method of discovering this, besides the Apple documentation is to use the dir() function that we've seen previously. Save your work and open a new document that contains this simple code:

#!/usr/bin/env python
import AddressBook
x = dir(AddressBook)
for i in x:
  print i

When you run it, you'll get an absolute ton of output, so pipe it through less or use a GUI editor that can run the code in its own window. It'll look like this:

ABACE
ABACL
ABAccessibilityMockUIElement
ABAddPropertiesAndTypes
ABAddRecord
ABAddToGroupCommand
ABAddressAttributedString
ABAddressBook
...
kABAIMHomeLabel
kABAIMInstantProperty
kABAIMWorkLabel
kABAddressCityKey
kABAddressCountryCodeKey
kABAddressCountryKey
kABAddressHomeLabel
kABAddressProperty
kABAddressStateKey
...
kCFXMLTreeErrorLocation
kCFXMLTreeErrorStatusCode
kEventABPeoplePickerDisplayedPropertyChanged
kEventABPeoplePickerGroupDoubleClicked
kEventABPeoplePickerGroupSelectionChanged
kEventABPeoplePickerNameDoubleClicked
kEventABPeoplePickerNameSelectionChanged
kEventABPeoplePickerValueSelectionChanged
kEventClassABPeoplePicker
kEventParamABPickerRef
objc
protocols
super

This lists every function and constant definition in the framework. In this case, we're interested in the block where each constant has the 'kAB' prefix. Each of these properties represents a potential field in the address book record - not all must be present. So, how can we tell which fields are present in a given record? We can ask. Back to our original code!

Here's a complete Python solution to dumping the current user's Address Book, I'll explain the parts not yet covered after this code listing.

Listing 1: dumpAB.py

#!/usr/bin/env python
from AddressBook import *
aBook = ABAddressBook.sharedAddressBook()
for person in aBook.people():
  properties = person.allProperties()
  for prop in properties:
    if prop == "com.apple.ABPersonMeProperty":
      continue
    elif prop == "com.apple.ABImageData":
      continue
    print prop, ":", person.valueForProperty_(prop)
  print '-'*60
  print

The people() method returns an array (an NSArray, specifically-the Obj-C Bridge deals with converting between the Obj-C types and Python types). We've previously covered Python for loops, and this one is no different. This loop iterates over each entry returned by the people() method, assigning it to person in each iteration.

With each person, we use the allProperties() method to determine the properties contained in that record. Then, we use another for loop to print only those properties. Note the if statement in this block: there are two properties present in each record that we're really not going to do anything with. Using a continue statement lets us restart the loop at the top.

Now, this isn't going to win any coding competitions, but look at how simple it is. No compiler or special IDE was needed to generate or run any of this.

What Happened? (Maybe)

Some of you may have seen an error pop up while running this program. Something about a "UnicodeDecodeError". What happened? This, partially, is the old-school Unix ASCII-ness colliding with modern sensibilities. You'll only see this error if one of your address book entries has Unicode characters in it (accent marks, Asian/Hebrew/Russian character sets and so on). Well, OS X is built to deal with this. Now, this depends on the environment in which you ran this. Terminal.app should actually have no problem as it's Unicode compliant. Surprisingly, some GUI text editors still don't handle Unicode properly, or, just need a little help. One thing you can do is give the interpreter a little hint: immediately following the magic shebang line (#!/usr/bin/env python), include the following:

# encoding: utf-8

This explicitly sets the encoding of the document. Additionally, Python itself has built-in support for Unicode strings. When printing a string, prefix it with 'u' to specify Unicode output. Like this:

print u'This is a Unicode string'

If you're printing a variable, it's similarly easy:

print u'%s' % (variable)

This is just one of those things that OS X users expect, and script authors need to bear in mind. Kind of like spaces in filenames...

Conclusion

There are actually a few more things we can cover about the Obj-C Bridge and its use in Python. However, we accomplished our goal for this month, and I hope you can see how easy some of these basic tasks are. You'll find that there are often several ways of approaching the code when using BridgeSupport. The methods used in this article are the most appropriate for the task at hand. See the References section below for the specific AddressBook documentation that I used to determine the bulk of this.

If we were more ambitious here, we could certainly do more with the data returned. Like write it out as a CSV file. AddressBook also supports group information, which I actually use fairy often, but that's a topic for next month.

Media of the month: I know, I usually suggest a good book, movie or music CD here, but this month is a little different. This month's suggestion is the outdoors - don't forget about it! Seriously, I'm not really a 'sun person,' but it is nice to take a walk with no laptop/phone/electronic device. Take a bike ride. Have a picnic. Take a (real) hike. Experience it. Just don't forget that there's a world outside of the LCD that we often sit a foot or two away from.

Hopefully, you're reading this at Apple's (sold out, again!) WWDC. Most of us from MacTech are here too (and you may have received this issue while on line for the Keynote - welcome!). Ping us, stop us in the halls - just say hello! See you next month.

References

"Address Book Programming Guide for Mac OS X," http://developer.apple.com/documentation/userexperience/Conceptual/AddressBook/AddressBook.pdf

"ABAddressBook Class Objective-C Reference," hhttp://developer.apple.com/documentation/UserExperience/Reference/AddressBook/Classes/ABAddressBook_Class/ABAddressBook_Class.pdf

"ABPerson C Reference," http://developer.apple.com/documentation/UserExperience/Reference/AddressBook/C/ABPersonRef/ABPersonRef.pdf


Ed Marczak is the Executive Editor for MacTech Magazine, and has been lucky enough to have ridden the computing and technology wave from early on. From teletype computing to MVS to Netware to modern OS X, his interest was piqued. He has also been fortunate enough to come into contact with some of the best minds in the business. Ed spends his non-compute time with his wife and two daughters.

 

Community Search:
MacTech Search:

Software Updates via MacUpdate

WhatsApp 0.2.8000 - Desktop client for W...
WhatsApp is the desktop client for WhatsApp Messenger, a cross-platform mobile messaging app which allows you to exchange messages without having to pay for SMS. WhatsApp Messenger is available for... Read more
TunnelBear 3.5.1 - Subscription-based pr...
TunnelBear is a subscription-based virtual private network (VPN) service and companion app, enabling you to browse the internet privately and securely. Features Browse privately - Secure your data... Read more
Typinator 7.4 - Speedy and reliable text...
Typinator turbo-charges your typing productivity. Type a little. Typinator does the rest. We've all faced projects that require repetitive typing tasks. With Typinator, you can store commonly used... Read more
Monosnap 3.4.9 - Versatile screenshot ut...
Monosnap lets you capture screenshots, share files, and record video and .gifs! Features Capture Capture full screen, just part of the screen, or a selected window Make your crop area pixel... Read more
Fantastical 2.4.5 - Create calendar even...
Fantastical 2 is the Mac calendar you'll actually enjoy using. Creating an event with Fantastical is quick, easy, and fun: Open Fantastical with a single click or keystroke Type in your event... Read more
TunnelBear 3.5.1 - Subscription-based pr...
TunnelBear is a subscription-based virtual private network (VPN) service and companion app, enabling you to browse the internet privately and securely. Features Browse privately - Secure your data... Read more
Typinator 7.4 - Speedy and reliable text...
Typinator turbo-charges your typing productivity. Type a little. Typinator does the rest. We've all faced projects that require repetitive typing tasks. With Typinator, you can store commonly used... Read more
Fantastical 2.4.5 - Create calendar even...
Fantastical 2 is the Mac calendar you'll actually enjoy using. Creating an event with Fantastical is quick, easy, and fun: Open Fantastical with a single click or keystroke Type in your event... Read more
Monosnap 3.4.9 - Versatile screenshot ut...
Monosnap lets you capture screenshots, share files, and record video and .gifs! Features Capture Capture full screen, just part of the screen, or a selected window Make your crop area pixel... Read more
Skim 1.4.32 - PDF reader and note-taker...
Skim is a PDF reader and note-taker for OS X. It is designed to help you read and annotate scientific papers in PDF, but is also great for viewing any PDF file. Skim includes many features and has a... Read more

Latest Forum Discussions

See All

Everything about Hero Academy 2 - The co...
It's fair to say we've spent a good deal of time on Hero Academy 2. So much so, that we think we're probably in a really good place to give you some advice about how to get the most out of the game. And in this guide, that's exactly what you're... | Read more »
Everything about Hero Academy 2: Part 3...
In the third part of our Hero Academy 2 guide we're going to take a look at the different modes you can play in the game. We'll explain what you need to do in each of them, and tell you why it's important that you do. [Read more] | Read more »
Everything about Hero Academy 2: Part 2...
In this second part of our guide to Hero Academy 2, we're going to have a look at the different card types that you're going to be using in the game. We'll split them up into different sections too, to make sure you're getting the most information... | Read more »
Everything about Hero Academy 2: Part 1...
So you've started playing Hero Academy 2, and you're feeling a little bit lost. Don't worry, we've got your back. So we've come up with a series of guides that are going to help you get to grips with everything that's going on in the game. [Read... | Read more »
What mobile gaming can learn from the Ni...
While Nintendo might not have had things all its own way since it began developing for mobile, one thing it has got right is the release of the Switch. After the disappointment of the WiiU, which I still can't really explain, the Switch felt a... | Read more »
Programmer of Sonic The Hedgehog launche...
Japanese programmer Yuji Naka is best known for leading the team that created the original Sonic The Hedgehog. He’s moved on from the speedy blue hero since then, launching his own company based in Tokyo – Prope Games. Legend of Coin is the... | Read more »
Why doesn't mobile gaming have its...
The Overwatch League is a pretty big deal. It's an attempt to really push eSports into the mainstream, by turning them into, well, regular sports. But slightly less sweaty. It's a lavish affair with teams from all around the world, and more... | Read more »
Give Webzen’s new billiard game PoolTime...
Best known for producing hugely popular MMO titles, South Korean publisher Webzen is now taking aim at a different genre altogether. PoolTime is a realistic eight ball pool simulator, allowing you to compete in real-time matches against players... | Read more »
Let Them Come Guide - How to survive aga...
Let Them Come is all about making it as far as possible against overwhelming odds. Check out some of these tips to help you last a little longer in your unwinnable fight: [Read more] | Read more »
All the best games on sale for iPhone an...
Happy last day of the week. I hope you've been having a good one. I have. I saw ten doggos today. So because I'm in a good mood, I thought I'd round up all of the best games that are currently on sale on the App Store. [Read more] | Read more »

Price Scanner via MacPrices.net

Apple now offering Certified Refurbished 2017...
Apple has Certified Refurbished 9.7″ WiFi iPads available for $50-$80 off the cost of new models. An Apple one-year warranty is included with each iPad, and shipping is free: – 9″ 32GB WiFi iPad: $... Read more
10″ iPad Pros on sale for $50-$75 off MSRP, n...
B&H Photo has 10″ and #Apple #iPad Pros on sale for up to $75 off MSRP. Shipping is free, and B&H charges sales tax in NY & NJ only. Note that some sale prices are restricted to certain... Read more
Apple refurbished Mac minis available startin...
Apple has restocked Certified Refurbished Mac minis starting at $419. Apple’s one-year warranty is included with each mini, and shipping is free: – 1.4GHz Mac mini: $419 $80 off MSRP – 2.6GHz Mac... Read more
Amazon offers Silver 13″ Apple MacBook Pros f...
Amazon has new Silver 2017 13″ #Apple #MacBook Pros on sale today for up to $150 off MSRP, each including free shipping: – 13″ 2.3GHz/128GB Silver MacBook Pro (MPXR2LL/A): $1199.99 $100 off MSRP – 13... Read more
Sale: 12″ 1.3GHz MacBooks on sale for $1499,...
B&H Photo has Space Gray and Rose Gold 12″ 1.3GHz #Apple MacBooks on sale for $100 off MSRP. Shipping is free, and B&H charges sales tax for NY & NJ residents only: – 12″ 1.3GHz Space... Read more
Apple offers Certified Refurbished 2017 iMacs...
Apple has a full line of Certified Refurbished iMacs available for up to $350 off original MSRP. Apple’s one-year warranty is standard, and shipping is free. The following models are available: – 27... Read more
13″ MacBook Airs on sale for $120-$100 off MS...
B&H Photo has 2017 13″ 128GB MacBook Airs on sale for $120 off MSRP. Shipping is free, and B&H charges sales tax for NY & NJ residents only: – 13″ 1.8GHz/128GB MacBook Air (MQD32LL/A): $... Read more
15″ Touch Bar MacBook Pros on sale for up to...
Adorama has Space Gray 15″ MacBook Pros on sale for $200 off MSRP. Shipping is free, and Adorama charges sales tax in NJ and NY only: – 15″ 2.8GHz MacBook Pro Space Gray (MPTR2LL/A): $2199, $200 off... Read more
21″ 3.4GHz 4K iMac on sale for $1399, $100 of...
Adorama has the 21″ 3.4GHz 4K #Apple #iMac on sale today for $1399. Their price is $100 off MSRP. Shipping is free, and Adorama charges sales tax in NJ and NY only: – 21″ 3.4GHz 4K iMac (MNE02LL/A... Read more
B&H offering 13″ Apple MacBook Pros for u...
B&H Photo has 13″ MacBook Pros on sale for up to $75-$120 off MSRP. Shipping is free, and B&H charges sales tax for NY & NJ residents only: – 13-inch 2.3GHz/128GB Space Gray MacBook Pro (... Read more

Jobs Board

Commerce Engineer, *Apple* Media Products -...
# Commerce Engineer, Apple Media Products Job Number: 113161479 Santa Clara Valley, California, United States Posted: 01-Nov-2017 Weekly Hours: 40.00 **Job Summary** Read more
*Apple* Retail - Multiple Positions - Apple,...
Job Description:SalesSpecialist - Retail Customer Service and SalesTransform Apple Store visitors into loyal Apple customers. When customers enter the store, Read more
Site Reliability Engineer, *Apple* Pay - Ap...
# Site Reliability Engineer, Apple Pay Job Number: 113356036 Santa Clara Valley, California, United States Posted: 12-Jan-2018 Weekly Hours: 40.00 **Job Summary** Read more
UI Tools and Automation Engineer, *Apple* M...
# UI Tools and Automation Engineer, Apple Media Products Job Number: 86351939 Santa Clara Valley, California, United States Posted: 11-Jan-2018 Weekly Hours: 40.00 Read more
*Apple* Retail - Multiple Positions - Apple,...
Job Description: Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.