So I'm in the process of trying to implement the BBEdit ODB suite functionality in a PyObjC app, and I've run into some weirdness, and I hope someone here might be able to help me.
I've been hacking on the MiniAEFrame.py module that is distributed with python, and I've had success receiving the BBEdit's response (when a file is saved) through this script. All I did was add a call to the following function, just before the call to the _Test() constructor def openInExternalEditor(_filePath, _lnnum=0, _editor = '/ Applications/BBEdit.app'): from aem.send import Application import struct from Carbon.File import FSSpec SelectionRange = struct.pack('hhllll', 0, int(_lnnum)-1, 1,1,0,0) Application(_editor).event('aevtodoc',{'----':FSSpec (_filePath),'kpos':SelectionRange}).send() BBEdit opens the requested document, and when I save the file, this event prints to the console: AppleEvent ('R*ch', 'FMod') for <Carbon.File.Alias object at 0x3e2b0> Other args: {... which is definitely what I want. However, when I bring all this into my PyObjC app, I no longer seem to receive events properly. Obviously, I had to make some changes, since the MiniApplication class in the MiniAEFrame module also implements event handling for menus, about boxes, etc, and this is already taken care of by the PyObjC app. This is what my event loop looks like now: def eventLoop(): # we poll for apple events here got, event = Evt.WaitNextEvent(Events.highLevelEventMask, 1) if got: print 'got: ' + str(got) + ' event: ' + str(event) what, message, when, where, modifiers = event if what == MiniAEFrame.kHighLevelEvent: AE.AEProcessAppleEvent(event) elif hasattr(MacOS, 'HandleEvent'): MacOS.HandleEvent(event) else: print "Unhandled event:", event # an instance of the twisted python threadedselectreactor reactor.callLater(1, eventLoop) The event registration is taken care of by a trial subclass of MiniAEFrame.AEServer: class EventServer(MiniAEFrame.AEServer): def __init__(self): MiniAEFrame.AEServer.__init__(self) # these are more than necessary, but in an attempt to # mimic MiniAEFrame as much as possible self.installaehandler('aevt', 'oapp', self.other) self.installaehandler('aevt', 'quit', self.other) self.installaehandler('****', '****', self.other) def other(self, _object=None, _class=None, _type=None, **args): print 'AppleEvent', (_class, _type), 'for', _object, 'Other args:', args However, now this gets various events (usually things like the 'rapp' event when the app goes into the background, etc), but definitely nothing from BBEdit. I thought perhaps it was because the ODB specification says you should pass along a 'keyServerID' parameter to the 'odoc' event that signifies a 4-byte char OSType. I wasn't sure about how this works under OS X, but I set the 'CFBundleSignature' property to 'Phil' in the .app bundle's Info.plist, and tried the following when I sent the event: def openInExternalEditor(_filePath, _lnnum=0, _editor = '/ Applications/BBEdit.app'): from aem.send import Application import struct from Carbon.File import FSSpec SelectionRange = struct.pack('hhllll', 0, int(_lnnum)-1, 1,1,0,0) Application(_editor).event('aevtodoc',{'----':FSSpec (_filePath), 'kpos':SelectionRange, 'keyServerID':'Phil'}).send() but this constantly generates the following error: Traceback (most recent call last): [snipped cocoa-related garbage] File "/Users/phil/Workspace/InnerSpace/cocoa/client/dist/ controller.app/Contents/Resources/__boot__.py", line 47, in _run execfile(path, globals(), globals()) File "/Users/phil/Workspace/InnerSpace/cocoa/client/ controller.py", line 167, in ? openInExternalEditor('/tmp/test-12345') File "/Users/phil/Workspace/InnerSpace/cocoa/client/ controller.py", line 162, in openInExternalEditor Application(_editor).event('aevtodoc',{'----':FSSpec (_filePath),'kpos':SelectionRange, 'keyServerID':'Phil'}).send() File "/Library/Frameworks/Python.framework/Versions/2.4/lib/ python2.4/site-packages/aem/send/__init__.py", line 83, in event return self._Event(self._address, event, params, atts, resulttype, self._transaction, returnid, self._codecs) File "/Library/Frameworks/Python.framework/Versions/2.4/lib/ python2.4/site-packages/aem/send/send.py", line 87, in __init__ self._event.AEPutParamDesc(key, codecs.pack(value)) TypeError: OSType arg must be string of 4 chars I've tried everything at this point to get it to accept 'Phil', such as converting it to an int, or packing it into a 4-byte struct, but to no avail. In reality, that shouldn't even be necessary, as I grepped the Python source tree, and found that the only function that generates a TypeError with that string is in mactoolboxglue.c, and it should accept the string 'Phil': /* Convert a 4-char string object argument to an OSType value */ int PyMac_GetOSType(PyObject *v, OSType *pr) { if (!PyString_Check(v) || PyString_Size(v) != 4) { PyErr_SetString(PyExc_TypeError, "OSType arg must be string of 4 chars"); return 0; } memcpy((char *)pr, PyString_AsString(v), 4); return 1; } At any rate, sorry this email is so long, but any help would be appreciated. It'd be really great to get this external editor feature working... Incidentally, here are some relevant links: ODB Suite: http://www.barebones.com/support/develop/odbsuite.shtml MiniAEFrame.py: http://cvs.sourceforge.net/viewcvs.py/python/python/dist/src/Lib/ plat-mac/MiniAEFrame.py?rev=1.5&view=log Thanks in advance, -phil christensen _______________________________________________ Pythonmac-SIG maillist - Pythonmac-SIG@python.org http://mail.python.org/mailman/listinfo/pythonmac-sig