...so that google can help organize my head.

2005-5-1

Using Core Data from Python

Update #1: Putting this at the top, because it is really important. The example changed since yesterday and this now requires top-of-tree [TOT] PyObjC. In particular, all of the methods that take NSError ** parameters now take one less argument, omitting the error argument, and return a tuple where the first element of the tuple is method's normal return value and the second element is the resulting NSError, if any.

In other words, you will either receive a tuple of the form (result, None) or a tuple of the form (None, result), but never one that has both items set or both items set to None unless there is a bug in the underlying API.

The current TOT of PyObjC adds support for automatically adjusting the signatures of any methods that take NSError ** arguments. It is less than optimal in that there is no way to pass NULL for the error argument and, therefore, no way to indicate to the underlying framework that it should not pay the potentially expensive price of instantiating and composing the contents of an NSError* instance.

Someday, that will change. But it will be a hard change to make. So, for now, we have a working solution that supports everything needed to build full featured applications with a relatively minor performance penalty in relatively odd situations (it isn't often that you would want to call one of these methods without collecting the error information).

These changes will be in PyObjC 1.3.1.


Via PyObjC, you can write Python applications that fully take advantage of Core Data.

PyObjC fully supports KVC, KVO, and subclassing of Objective-C from Python, so use of NSManagedObject is fully enabled.

One caveat: models edited in Xcode are saved in a "source" format that is "compiled" into a binary representation as a part of building a project. A compiler is provided to do exactly that and it is called via a standard build rule as a part of Xcode's build process.

An example would best illustrate how to manually use Core Data from Python, including compiling a model. In this example, we compile the model from the EventManager Core Data example.

First, link momc to somewhere easily accessed (this is all one line and assumes that ~/bin/ exists):

ln -s /Library/Application\ Support/Apple/Developer\ Tools/Plug-ins/XDCoreDataModel.xdplugin/Contents/Resources/momc ~/bin/momc

Then, compile the sample model and copy the CranberryFestival sample data to someplace useful:

mkdir test
cd test
momc /Developer/Examples/CoreData/EventManager/MyDocument.xcdatamodel em.mom
cp /Developer/Examples/CoreData/EventManager/Sample\ Event\ Files/CranberryFestival.events .

Now, to fire up python and work with Core Data. This assumes top of tree of PyObjC or the next production release. I ripped out the '>>>' characters for copy/paste convenience. Anywhere Python normally spews something, the output shows up in italics.

First, create the managed object model (and spew a little information about an entity within):

from CoreData import *
momURL = NSURL.fileURLWithPath_("em.mom")
mom = NSManagedObjectModel.alloc().initWithContentsOfURL_(momURL)
mom.entities().valueForKey_("name")
(Event, EventParticipant, Location, Occasion, Person)
eventEntity = mom.entitiesByName()['Event']
eventEntity.attributesByName().keys()
(eventID, detailDescription, endTime, name, startTime, date)

Now, set up the persistent store coordinator and managed object context:

dataURL = NSURL.fileURLWithPath_("CranberryFestival.events")
psc = NSPersistentStoreCoordinator.alloc().initWithManagedObjectModel_(mom)
psc.addPersistentStoreWithType_configuration_URL_options_error_(None, None, dataURL, None)
(, None)
moc = NSManagedObjectContext.new()
moc.setPersistentStoreCoordinator_(psc)

Finally, fetch some Events and display some information:

fetch = NSFetchRequest.new()
fetch.setEntity_(eventEntity)
events, error = moc.executeFetchRequest_error_(fetch)
len(e)
5
for anEvent in events:
  print anEvent.valueForKey_(u'name')
Opening Ceremony
Registration
Lunch by the Bog
Pick your own Cranberries
Educational Workshop

Of course, you can always take the same approach as the Core Data Document Based Application and do everything via Interface Builder and Xcode, thus automating all of this per NSPersistentDocument.

Comment on this post [ so far] ... more like this: [CoreData, Mac OS X, PyObjC, Technology] ... topic exchange: [CoreData, Mac OS X, PyObjC, Technology]