Thread: [Pyobjc-dev] issues with NSURL and NSWindow?
Brought to you by:
ronaldoussoren
From: James E. <ea...@ba...> - 2004-04-05 03:19:01
|
I've been doing more with PyObjC lately, and I've been having a few weird issues creep up.... The first one's probably the easiest to demonstrate: Python 2.3 (#1, Sep 13 2003, 00:49:11) [GCC 3.3 20030304 (Apple Computer, Inc. build 1495)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> from Foundation import * >>> u = NSURL.alloc().initWithString('http://pyobjc.sf.net') Bus error % That's the behaviour that I get with PyObjC 1.0 and with the version checked out from CVS last night. Am I just being stupid in how I'm using NSURL, or is that a bug? Also, it appears that the NSWindow doesn't implement the -isKeyWindow and -isMainWindow methods: 'objc.native_selector' object has no attribute 'isMainWindow' That error occurs when I call MyAppController.window.isMainWindow() where MyAppController.window is an IBOutlet of type NSWindow. Any help would be greatly appreciated... I love the work that you folks are doing! Cheers, James -- I can't give you a brain, but I can give you a diploma. -- The Wizard of Oz |
From: b.bum <bb...@ma...> - 2004-04-05 03:37:43
|
On Apr 4, 2004, at 8:18 PM, James Eagan wrote: > I've been doing more with PyObjC lately, and I've been having a few > weird issues creep up.... The first one's probably the easiest to > demonstrate: > > Python 2.3 (#1, Sep 13 2003, 00:49:11) > [GCC 3.3 20030304 (Apple Computer, Inc. build 1495)] on darwin > Type "help", "copyright", "credits" or "license" for more information. > >>> from Foundation import * > >>> u = NSURL.alloc().initWithString('http://pyobjc.sf.net') > Bus error > % That should be: >>> from Foundation import * >>> u = NSURL.alloc().initWithString_('http://pyobjc.sf.net') But the incorrect form shouldn't bus error, either... > Also, it appears that the NSWindow doesn't implement the -isKeyWindow > and -isMainWindow methods: 'objc.native_selector' object has no > attribute 'isMainWindow' > > That error occurs when I call MyAppController.window.isMainWindow() > where MyAppController.window is an IBOutlet of type NSWindow. Do you mean that 'window' is an outlet of type NSWindow? The error message indicates that whatever is found via the '.window' is a method, not a reference to a window object. So, MyAppController.window().isMainWindow() might "just work", but I'm still confused. What is MyWindowController? The naming implies that it is a class of some kind... b.bum |
From: Bob I. <bo...@re...> - 2004-04-05 03:55:41
|
On Apr 4, 2004, at 11:37 PM, b.bum wrote: > On Apr 4, 2004, at 8:18 PM, James Eagan wrote: >> I've been doing more with PyObjC lately, and I've been having a few >> weird issues creep up.... The first one's probably the easiest to >> demonstrate: >> >> Python 2.3 (#1, Sep 13 2003, 00:49:11) >> [GCC 3.3 20030304 (Apple Computer, Inc. build 1495)] on darwin >> Type "help", "copyright", "credits" or "license" for more information. >> >>> from Foundation import * >> >>> u = NSURL.alloc().initWithString('http://pyobjc.sf.net') >> Bus error >> % > > That should be: > > >>> from Foundation import * > >>> u = NSURL.alloc().initWithString_('http://pyobjc.sf.net') > > But the incorrect form shouldn't bus error, either... It's releasing something that was alloc'ed but not init'ed. It probably should bus error. I'm not sure how we are supposed to catch that anyway? I guess we would have to keep track to see if it was alloc'ed but not initialized, and then send it dealloc instead of release. This gets a bus error too, btw: #import <Foundation/Foundation.h> int main (int argc, char **argv) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSURL *url; url = [NSURL alloc]; [url release]; [pool release]; } In any case, you are far better off using NSURL.URLWithString_(u'http://pyobjc.sf.net/') .. in general I would recommend avoiding alloc/init from PyObjC in exchange for the autoreleased classmethod version, if for no other reason than aesthetics. Surely the amount of code you have to type is proportional to the number of mistakes you can make :) -bob |
From: b.bum <bb...@ma...> - 2004-04-05 04:05:40
|
On Apr 4, 2004, at 8:59 PM, Bob Ippolito wrote: > It's releasing something that was alloc'ed but not init'ed. It > probably should bus error. I'm not sure how we are supposed to catch > that anyway? I guess we would have to keep track to see if it was > alloc'ed but not initialized, and then send it dealloc instead of > release. > > This gets a bus error too, btw: > #import <Foundation/Foundation.h> > > int main (int argc, char **argv) { > NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; > NSURL *url; > url = [NSURL alloc]; > [url release]; > [pool release]; > } That is a symptom of an earlier failure. The fact the PyObjC is attempting to send initWithString instead of initWithString: is the root cause (or else initWithString: wouldn't work, would it?). Can we catch the attempt to invoke a method that does not exist? b.bum |
From: Bob I. <bo...@re...> - 2004-04-05 04:27:35
|
On Apr 5, 2004, at 12:05 AM, b.bum wrote: > On Apr 4, 2004, at 8:59 PM, Bob Ippolito wrote: >> It's releasing something that was alloc'ed but not init'ed. It >> probably should bus error. I'm not sure how we are supposed to catch >> that anyway? I guess we would have to keep track to see if it was >> alloc'ed but not initialized, and then send it dealloc instead of >> release. >> >> This gets a bus error too, btw: >> #import <Foundation/Foundation.h> >> >> int main (int argc, char **argv) { >> NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; >> NSURL *url; >> url = [NSURL alloc]; >> [url release]; >> [pool release]; >> } > > That is a symptom of an earlier failure. The fact the PyObjC is > attempting to send initWithString instead of initWithString: is the > root cause (or else initWithString: wouldn't work, would it?). > > Can we catch the attempt to invoke a method that does not exist? That's not the correct way of looking at it. The problem is precisely that it is sending the release message to an object that is not prepared to receive it. It actually does try and throw an exception due to the incorrect selector, you just don't see it because it does some garbage collection in the process and the world ends before it gets a chance to let you know what went wrong. >>> a = NSURL.alloc() >>> del a Bus error -bob |
From: Bob I. <bo...@re...> - 2004-04-05 04:50:19
|
On Apr 5, 2004, at 12:31 AM, Bob Ippolito wrote: > > On Apr 5, 2004, at 12:05 AM, b.bum wrote: > >> On Apr 4, 2004, at 8:59 PM, Bob Ippolito wrote: >>> It's releasing something that was alloc'ed but not init'ed. It >>> probably should bus error. I'm not sure how we are supposed to >>> catch that anyway? I guess we would have to keep track to see if it >>> was alloc'ed but not initialized, and then send it dealloc instead >>> of release. >>> >>> This gets a bus error too, btw: >>> #import <Foundation/Foundation.h> >>> >>> int main (int argc, char **argv) { >>> NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; >>> NSURL *url; >>> url = [NSURL alloc]; >>> [url release]; >>> [pool release]; >>> } >> >> That is a symptom of an earlier failure. The fact the PyObjC is >> attempting to send initWithString instead of initWithString: is the >> root cause (or else initWithString: wouldn't work, would it?). >> >> Can we catch the attempt to invoke a method that does not exist? > > That's not the correct way of looking at it. The problem is precisely > that it is sending the release message to an object that is not > prepared to receive it. It actually does try and throw an exception > due to the incorrect selector, you just don't see it because it does > some garbage collection in the process and the world ends before it > gets a chance to let you know what went wrong. > > >>> a = NSURL.alloc() > >>> del a > Bus error I just fixed this in CVS.. apparently the code already knew about this situation (reaping an uninitialized object), it was just handling it incorrectly. >>> from Foundation import * >>> url = NSURL.alloc().initWithString(u'http://pyobjc.sf.net') Traceback (most recent call last): File "<stdin>", line 1, in ? AttributeError: 'NSURL' object has no attribute 'initWithString' -bob |
From: b.bum <bb...@ma...> - 2004-04-05 05:31:14
|
On Apr 4, 2004, at 9:31 PM, Bob Ippolito wrote: > That's not the correct way of looking at it. The problem is precisely > that it is sending the release message to an object that is not > prepared to receive it. It actually does try and throw an exception > due to the incorrect selector, you just don't see it because it does > some garbage collection in the process and the world ends before it > gets a chance to let you know what went wrong. I disagree. Regardless of the state of the underlying object or the bridge between, the user is attempting to send a method to an object where that method does not exist. If I do the following from ObjC... [[NSURL alloc] initWithString]; ... the runtime responds with... 2004-04-04 22:28:02.775 asdfasdf[6043] *** -[NSURL initWithString]: selector not recognized 2004-04-04 22:28:02.777 asdfasdf[6043] *** Uncaught exception: <NSInvalidArgumentException> *** -[NSURL initWithString]: selector not recognized ... as I would expect. That PyObjC crashes in, effectively, the same situation without a useful warning message means that there is a bug in PyObjC. And now it is fixed. That rocks. Thanks, Bob! :-) b.bum |
From: Ronald O. <ous...@ci...> - 2004-04-05 06:18:15
|
On 5-apr-04, at 7:31, b.bum wrote: > On Apr 4, 2004, at 9:31 PM, Bob Ippolito wrote: >> That's not the correct way of looking at it. The problem is >> precisely that it is sending the release message to an object that is >> not prepared to receive it. It actually does try and throw an >> exception due to the incorrect selector, you just don't see it >> because it does some garbage collection in the process and the world >> ends before it gets a chance to let you know what went wrong. > > I disagree. > > Regardless of the state of the underlying object or the bridge > between, the user is attempting to send a method to an object where > that method does not exist. > > If I do the following from ObjC... > > [[NSURL alloc] initWithString]; > > ... the runtime responds with... > > 2004-04-04 22:28:02.775 asdfasdf[6043] *** -[NSURL initWithString]: > selector not recognized > 2004-04-04 22:28:02.777 asdfasdf[6043] *** Uncaught exception: > <NSInvalidArgumentException> *** -[NSURL initWithString]: selector not > recognized You get the same error with PyObjC. The only problem is that the bridge crashes before you see the exception :-(. The bridge crashes because it tries to -release an object that is not initialized, which causes serious errors for some classes (such as NSURL). Ronald -- X|support bv http://www.xsupport.nl/ T: +31 610271479 F: +31 204416173 |
From: Bob I. <bo...@re...> - 2004-04-05 06:27:49
|
On Apr 5, 2004, at 2:18 AM, Ronald Oussoren wrote: > > On 5-apr-04, at 7:31, b.bum wrote: > >> On Apr 4, 2004, at 9:31 PM, Bob Ippolito wrote: >>> That's not the correct way of looking at it. The problem is >>> precisely that it is sending the release message to an object that >>> is not prepared to receive it. It actually does try and throw an >>> exception due to the incorrect selector, you just don't see it >>> because it does some garbage collection in the process and the world >>> ends before it gets a chance to let you know what went wrong. >> >> I disagree. >> >> Regardless of the state of the underlying object or the bridge >> between, the user is attempting to send a method to an object where >> that method does not exist. >> >> If I do the following from ObjC... >> >> [[NSURL alloc] initWithString]; >> >> ... the runtime responds with... >> >> 2004-04-04 22:28:02.775 asdfasdf[6043] *** -[NSURL initWithString]: >> selector not recognized >> 2004-04-04 22:28:02.777 asdfasdf[6043] *** Uncaught exception: >> <NSInvalidArgumentException> *** -[NSURL initWithString]: selector >> not recognized > > You get the same error with PyObjC. The only problem is that the > bridge crashes before you see the exception :-(. The bridge crashes > because it tries to -release an object that is not initialized, which > causes serious errors for some classes (such as NSURL). Yeah, I tried to explain that.. it uses dealloc now, which seems to work much better, especially for NSURL ;) -bob |
From: Ronald O. <ous...@ci...> - 2004-04-05 09:25:41
|
On 5-apr-04, at 8:31, Bob Ippolito wrote: >> >> You get the same error with PyObjC. The only problem is that the >> bridge crashes before you see the exception :-(. The bridge crashes >> because it tries to -release an object that is not initialized, which >> causes serious errors for some classes (such as NSURL). > > Yeah, I tried to explain that.. it uses dealloc now, which seems to > work much better, especially for NSURL ;) I'm checking in a version that leaks such objects, dealloc doesn't work with NSArray. I've also added a unittest for this. Ronald -- X|support bv http://www.xsupport.nl/ T: +31 610271479 F: +31 204416173 |
From: Ronald O. <ous...@ci...> - 2004-04-05 06:13:21
|
On 5-apr-04, at 6:05, b.bum wrote: > On Apr 4, 2004, at 8:59 PM, Bob Ippolito wrote: >> It's releasing something that was alloc'ed but not init'ed. It >> probably should bus error. I'm not sure how we are supposed to catch >> that anyway? I guess we would have to keep track to see if it was >> alloc'ed but not initialized, and then send it dealloc instead of >> release. >> >> This gets a bus error too, btw: >> #import <Foundation/Foundation.h> >> >> int main (int argc, char **argv) { >> NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; >> NSURL *url; >> url = [NSURL alloc]; >> [url release]; >> [pool release]; >> } > > That is a symptom of an earlier failure. The fact the PyObjC is > attempting to send initWithString instead of initWithString: is the > root cause (or else initWithString: wouldn't work, would it?). > > Can we catch the attempt to invoke a method that does not exist? We do that. As bob noted the problem is that we release an uninitialized object. I try to do the right thing when this happens, but that's obviously not good enough. It's probably better to just leak when this happens (and log/warn about this) Ronald -- X|support bv http://www.xsupport.nl/ T: +31 610271479 F: +31 204416173 |
From: James E. <ea...@ba...> - 2004-04-05 04:07:43
|
On 4 Apr 2004, at 23:37, b.bum wrote: > That should be: > > >>> from Foundation import * > >>> u = NSURL.alloc().initWithString_('http://pyobjc.sf.net') Ahhh, it's good to see that that was just a case of me being stupid (with more practice with pyobjc I expect that sort of thing will become blatantly obvious to me) ;-) >> That error occurs when I call MyAppController.window.isMainWindow() >> where MyAppController.window is an IBOutlet of type NSWindow. > > Do you mean that 'window' is an outlet of type NSWindow? > > The error message indicates that whatever is found via the '.window' > is a method, not a reference to a window object. > > So, MyAppController.window().isMainWindow() might "just work", but I'm > still confused. What is MyWindowController? The naming implies > that it is a class of some kind... Now I'm really confused. I tried your trick of invoking MyAppController.window as a method instead of a variable and that seems to have worked. MyAppController is a class that I've defined in python and is the File's Owner in the nib that constructs the particular window at issue here (I probably confused you with the code fragment above since the fragment should use an instance, not the class). That controller specifies, among others, and outlet named window, which is connected to the NSWindow instance in the nib. Which is why I would have thought that I'd use something like: myAppControllerInstance.window.isMainWindow() just like I use in other places myAppControllerInstance.textField.stringValue(). So why is window suddenly a method? (since myAppControllerInstance.window().isMainWindow() works where I would have expected an error) Thanks! James -- There is no spoo. |
From: Ronald O. <ous...@ci...> - 2004-04-05 06:15:20
|
On 5-apr-04, at 6:07, James Eagan wrote: > > MyAppController is a class that I've defined in python and is the > File's Owner in the nib that constructs the particular window at issue > here (I probably confused you with the code fragment above since the > fragment should use an instance, not the class). That controller > specifies, among others, and outlet named window, which is connected > to the NSWindow instance in the nib. Which is why I would have > thought that I'd use something like: > myAppControllerInstance.window.isMainWindow() just like I use in other > places myAppControllerInstance.textField.stringValue(). So why is > window suddenly a method? (since > myAppControllerInstance.window().isMainWindow() works where I would > have expected an error) What's the superclass of MyAppController? Does that have a method named 'window'? Ronald -- X|support bv http://www.xsupport.nl/ T: +31 610271479 F: +31 204416173 |