Thread: [Pyobjc-dev] exception handling design pattern
Brought to you by:
ronaldoussoren
From: Bill B. <bb...@co...> - 2002-10-16 00:03:30
|
If I implement something like... def foo(self): try: serverAPIVersion = int( versionInfo['currentXmlRpcVersion'] ) serverAppVersion = int( versionInfo['applicationVersion'] ) except KeyError, aKey: NSException.raise_format_(NSInternalInconsistencyException, " ** %s key not found in getVersionInfo() response>" % aKey) ... and am calling this code from ObjC (i.e. objc->python->objc exception), I would expect that the raised NSException would be transparently passed back through to ObjC. That is: NS_DURING [instanceOfPythonObject foo]; NS_HANDLER ... handle the raised NSException here ... NS_ENDHANDLER This would seem to be consistent with the ObjC implementation pattern. That is, it wouldn't matter if -foo is implemented in Python or in the ObjC parent class of the python class, the behavior would be consistent. Looking at the implementation, it looks like the problem lies in the behavior of the ObjC->Python part of the bridge in that it leaves the NSException in a wrapped up state? I'm not sure how this would influence the relatively complex situation of, say, ObjC->Python->ObjC->Python->Objc exception raised... I.e. in the 'ObjC' parts of the stack, you want to raise the exception and let the next level up's interface between Python->ObjC catch it, convert it into the appropriate Python exception, then convert it back into an NSException at the next ObjC->Python extension (keeping in mind that the exception goes from right to left). b.bum |
From: Ronald O. <ous...@ci...> - 2002-10-16 06:42:12
|
On Tuesday, Oct 15, 2002, at 23:53 Europe/Amsterdam, Bill Bumgarner wrote: > Looking at the implementation, it looks like the problem lies in the > behavior of the ObjC->Python part of the bridge in that it leaves the > NSException in a wrapped up state? That's right. I never got around to implement this, adding this code should be relatively straightforward. I'll look into it. BTW. I've been playing with libffi and I'm pretty sure it can be used to remove the need for the register.m file. I already have a function that returns an 'IMP' for in the Objective-C method dispatch table (given a method signature). I can't test this at the moment because libffi refused to build into a shared library... Ronald |
From: Bill B. <bb...@co...> - 2002-10-16 15:31:56
|
On Wednesday, October 16, 2002, at 02:42 AM, Ronald Oussoren wrote: > On Tuesday, Oct 15, 2002, at 23:53 Europe/Amsterdam, Bill Bumgarner > wrote: >> Looking at the implementation, it looks like the problem lies in the >> behavior of the ObjC->Python part of the bridge in that it leaves the >> NSException in a wrapped up state? > That's right. I never got around to implement this, adding this code > should be relatively straightforward. I'll look into it. Thanks. It isn't a huge issue, but anything that makes the bridge more transparent is definitely a boon. BTW: The bridge is working *really* well. I'm using it in a production development setting and have had 0 problems other than of my own making (the exception issue wasn't a big deal). > BTW. I've been playing with libffi and I'm pretty sure it can be used > to remove the need for the register.m file. I already have a function > that returns an 'IMP' for in the Objective-C method dispatch table > (given a method signature). I can't test this at the moment because > libffi refused to build into a shared library... If the inclusion of a shared library requires end users of standalone applications to go through some kind of installation process to have the shlib dumped off in the proper location, I will be very strongly against the inclusion of features that require a shared library. The value of the PyObjC bridge is primarily that it can be used so transparently within the X environment. At this point, the PyObJC is considerably more straightforward to use than the Java-ObjC bridge and is easier to use than the AppleScript Studio bridge. Anything that takes away from that transparency must have a huge return on investment to be worth it. With all that said, eliminating the register.m based dispatch would certainly be a win. Did you receive my earlier message regarding method dispatch within the Java<->ObjC bridge? It was able to do its thing without requiring a mapping for every method and without something like the register.m functionality. I really need to dig more deeply into this particular problem. b.bum |
From: Ronald O. <ous...@ci...> - 2002-10-16 19:31:36
|
On Wednesday, Oct 16, 2002, at 16:27 Europe/Amsterdam, Bill Bumgarner wrote: > On Wednesday, October 16, 2002, at 02:42 AM, Ronald Oussoren wrote: >> On Tuesday, Oct 15, 2002, at 23:53 Europe/Amsterdam, Bill Bumgarner >> wrote: >>> Looking at the implementation, it looks like the problem lies in the >>> behavior of the ObjC->Python part of the bridge in that it leaves >>> the NSException in a wrapped up state? >> That's right. I never got around to implement this, adding this code >> should be relatively straightforward. I'll look into it. > > Thanks. It isn't a huge issue, but anything that makes the bridge > more transparent is definitely a boon. I've just checked in a fix. Forwarding exceptions in the 'other' runtime is now cleaner, and when the exception travels back into its own runtime it regains its original identity. There is one thing I have not really looked into yet: What is the normal way of processing exceptions in Objective-C, do you use '==' or 'isEqual' to check if the exception is one you can handle? If it is the former some additional work is necessary: NSString objects are transparently translated into Python strings and Python strings are translated in (freshly allocated) NSStrings. Thus when you trow NSSomeException from Python it is 'isEqual' on the Objective-C side but not '=='. > BTW: The bridge is working *really* well. I'm using it in a > production development setting and have had 0 problems other than of > my own making (the exception issue wasn't a big deal). Wow, I can debug without a real testsuite :-) > >> BTW. I've been playing with libffi and I'm pretty sure it can be used >> to remove the need for the register.m file. I already have a function >> that returns an 'IMP' for in the Objective-C method dispatch table >> (given a method signature). I can't test this at the moment because >> libffi refused to build into a shared library... > > If the inclusion of a shared library requires end users of standalone > applications to go through some kind of installation process to have > the shlib dumped off in the proper location, I will be very strongly > against the inclusion of features that require a shared library. I agree, if I get this into a usable shape libffi should be linked into the objc._objc module (no seperate shared library). An external library should also never be required for using PyObjC, we should keep the current mechanism. The problem I'm currently having is that one of the source files won't compile into an object file that can be used in a dynamicly loaded object. > > The value of the PyObjC bridge is primarily that it can be used so > transparently within the X environment. At this point, the PyObJC > is considerably more straightforward to use than the Java-ObjC bridge > and is easier to use than the AppleScript Studio bridge. > > Anything that takes away from that transparency must have a huge > return on investment to be worth it. > <nod> > With all that said, eliminating the register.m based dispatch would > certainly be a win. Did you receive my earlier message regarding > method dispatch within the Java<->ObjC bridge? It was able to do its > thing without requiring a mapping for every method and without > something like the register.m functionality. I did receive you earlier message, but didn't use that information at the time. The description in your mail sounds a bit like OC_PythonObject in PyObjC, but not quite. You wouldn't have a pointer to more information, would you? I ran 'bridget' on '/Developer/Java/Jobs/Foundation.jobs' and looked at the results. This tool generates java classes with lots of 'native' methods. The implementation of these methods call into Objective-C using objc_msgSendSuper (like the super_N functions in register.m). At least this explains why you can do 'super.method()' in subclasses of Java proxies. From what I see in the header files, message passing from Objective-C to Java is done through an NSProxy-style class, like you already wrote. This is a bit like I expected. The problem with 'objc_msgSendSuper' is that there is no version of it that accepts a 'va_list' type argument (like objc_msgSendv) which means you can only generate calls to objc_msgSendSuper by manually building a stack-frame (or by using a library that does this for you). BTW. Whoever wrote bridget is quite fond of CPP, making sense of the layers of macros was quite an adventure :-) Ronald |
From: Bill B. <bb...@co...> - 2002-10-16 20:43:30
|
On Wednesday, October 16, 2002, at 03:31 PM, Ronald Oussoren wrote: > On Wednesday, Oct 16, 2002, at 16:27 Europe/Amsterdam, Bill Bumgarner > wrote: >> On Wednesday, October 16, 2002, at 02:42 AM, Ronald Oussoren wrote: >>> On Tuesday, Oct 15, 2002, at 23:53 Europe/Amsterdam, Bill Bumgarner >>> wrote: >>>> Looking at the implementation, it looks like the problem lies in >>>> the behavior of the ObjC->Python part of the bridge in that it >>>> leaves the NSException in a wrapped up state? >>> That's right. I never got around to implement this, adding this code >>> should be relatively straightforward. I'll look into it. >> >> Thanks. It isn't a huge issue, but anything that makes the bridge >> more transparent is definitely a boon. > I've just checked in a fix. Forwarding exceptions in the 'other' > runtime is now cleaner, and when the exception travels back into its > own runtime it regains its original identity. Excellent!! > There is one thing I have not really looked into yet: What is the > normal way of processing exceptions in Objective-C, do you use '==' or > 'isEqual' to check if the exception is one you can handle? If it is > the former some additional work is necessary: NSString objects are > transparently translated into Python strings and Python strings are > translated in (freshly allocated) NSStrings. Thus when you trow > NSSomeException from Python it is 'isEqual' on the Objective-C side > but not '=='. It is generally done via isEqualToString: on the -name and, as such, shouldn't be a problem in properly written code. > >> BTW: The bridge is working *really* well. I'm using it in a >> production development setting and have had 0 problems other than of >> my own making (the exception issue wasn't a big deal). > Wow, I can debug without a real testsuite :-) Speaking of: I would eventually like to toss together a python-esque test suite for PyObjC that is included with the distribution. In the case of exceptions, I simply switched to using: raise NSInternalInconsistencyException, "Something really, really bad happened." Other than the lack of a userInfo dictionary into which I occasionally carry along some meta info, this works fine. Now that I can toss proper Obj-C exceptions, this limitation can go away, as well. Though -- thinking it through -- likely continuing with the raise style pure-python exception is the way to go if the bridge converts it correctly. I just wish there was a way to carry along meta info. >>> BTW. I've been playing with libffi and I'm pretty sure it can be >>> used to remove the need for the register.m file. I already have a >>> function that returns an 'IMP' for in the Objective-C method >>> dispatch table (given a method signature). I can't test this at the >>> moment because libffi refused to build into a shared library... >> >> If the inclusion of a shared library requires end users of standalone >> applications to go through some kind of installation process to have >> the shlib dumped off in the proper location, I will be very strongly >> against the inclusion of features that require a shared library. > > I agree, if I get this into a usable shape libffi should be linked > into the objc._objc module (no seperate shared library). An external > library should also never be required for using PyObjC, we should keep > the current mechanism. Definitely on the same page there! Good! > The problem I'm currently having is that one of the source files won't > compile into an object file that can be used in a dynamicly loaded > object. What is the problem? I have tangled with these issues in the past. b.bum |