Neat PyObjC Trick
I demoed the latest build of PyObjC at the recent CocoaHeads meeting in Cupertino.
The demo concluded with a “show all [most, really] the tricks at once” sequence.
- How py2app, a part of PyObjC, will automatically create an installer package from a standard Python package
- Injecting a live Python interpreter into a running application
- Introspecting the application
- Interacting with Core Data, including dealing with ** style parameters
- Modifying a managed object and having KVO automatically fire on assignment
First, grab the top-of-tree source from the pyobjc repository:
svn co http://svn.red-bean.com/pyobjc/trunk/pyobjc/
Alternatively, you can mount that URL in the finder (click cancel on all the bloody attempts to write .DS_Store files) and cp -r the source to somewhere from the Terminal.
Then:
cd pyobjc python setup.py bdist_mpkg --open
That will build PyObjC and open an Installer package that contains the runtime, documentation, examples, and Xcode templates.
Next, grab the OutlineEdit examples from /Developer/Examples/CoreData/ and run it.
Now, from the PyObjC source directory:
cd Examples/Inject/InjectInterpreter ps aux | grep OutlineEdit ... note the PID ... python test.py PID
The InjectInterpreter will be built and, shortly, you will see a Window pop up in OutlineEdit containing a Python interpreter.
Click on OutlineEdit and add some new Notes in the Untitled document window. Quantity and structure don’t matter.
Now, click on the interpreter window and do:
from AppKit import * from objc import *
At this point, we now have the PyObjC bridge imported into the Python interpreter that is running within the Main Event Loop of OutlineEdit. With that in place, we can now interact with the Cocoa infrastructure to interrogate and manipulate the application. Since this is a Core Data application, we can — of course — interact with all the Core Data goodness within the document.
First, we need to get a hold of all that Core Data goodness:
d = NSDocumentController.sharedDocumentController().documents()[0] mom = d.managedObjectModel() moc = d.managedObjectContext() noteEntity = mom.entitiesByName()['Note'] fr = NSFetchRequest.new() fr.setEntity_(noteEntity)
Now, grab one of the Note objedcts:
notes, error = moc.executeFetchRequest_error_(fr) note = notes[0]
And manipulate:
note.contents = u'Hello, world!'
Note that as soon as you hit return, the UI updates. This happens because PyObjC is smart enough to trigger the KVO/KVC notifications upon assignment to an attribute of an NSObject subclass.
And, of course, if you screw up the state of the document too badly:
moc.undo()


October 19th, 2005 at 3:09 pm
This is really cool… All we need now is an integration of this with PyFIT ( Fitnesse ) so we can write automated acceptance tests for our Cocoa applications. http://agile.unisonis.com/PyFitTutorial.html
If anyone has already done this, please publish a tutorial for the rest of us!
October 19th, 2005 at 9:53 pm
[EDITOR: JC was injecting pyobjc into PyOutlineEdit -- the Python/PyObjC port of OutlineEdit -- it should work, but doesn't. The example was specifically aimed at injecting into a non-PyObjC app. JC has since verified that the instructions work fine w/the regular ObjC OutlineEdit]
arrgh..
everytime I try this I get
(and so on) CRRRASH!
October 20th, 2005 at 3:34 pm
Did anything ever come of ObjectiveEverything from tiptop? I know that PyObjC, CamelBones, RubyCocoa et al are now at least at the same point if not superior to it, but it did provide a nice little environment…
October 20th, 2005 at 5:55 pm
Leeg,
Pedja hasn’t been doing anything with Objective-Everything for many years now. The last time I saw him was at WWDC at least four years ago, and he told me then that he really can’t afford the time away from his consulting business to work on the TipTop products.
-jcr
November 20th, 2005 at 12:09 pm
I tried the above but running “python test.py PID” did not work out as expected.
I realised I built the PyObjC package (and installed it) using the DarwinPorts
distribution of python 2.4. This is the end of the Xcode Run Log output:
I ran
findon Apple’s Python framework as well as DarwinPorts’and sure enough, there’s a
./lib/python2.3/lib-dynload/_File.soin Apple’s framework, but not in DarwinPorts.
Any clue if this can be fixed somehow (I mean in DarwinPorts)?
Perhaps I shouldn’t try to run PyObjC apps on OS X against DP?
February 25th, 2006 at 2:21 am
Yeah, don’t use DP’s python for developing Mac OS X specific stuff. Nobody on the PyObjC, py2app, etc. teams use anything but a bog standard framework build of Python, and nobody from the DP or Fink teams care enough about this stuff to test and contribute patches.