pyobjc-dev Mailing List for PyObjC (Page 271)
Brought to you by:
ronaldoussoren
You can subscribe to this list here.
2000 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(9) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2001 |
Jan
(1) |
Feb
(2) |
Mar
(3) |
Apr
(30) |
May
(18) |
Jun
|
Jul
(4) |
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2002 |
Jan
(7) |
Feb
(2) |
Mar
(1) |
Apr
|
May
|
Jun
(3) |
Jul
(13) |
Aug
|
Sep
(23) |
Oct
(180) |
Nov
(291) |
Dec
(95) |
2003 |
Jan
(338) |
Feb
(352) |
Mar
(97) |
Apr
(46) |
May
(226) |
Jun
(184) |
Jul
(145) |
Aug
(141) |
Sep
(69) |
Oct
(161) |
Nov
(96) |
Dec
(90) |
2004 |
Jan
(66) |
Feb
(87) |
Mar
(98) |
Apr
(132) |
May
(115) |
Jun
(68) |
Jul
(150) |
Aug
(92) |
Sep
(59) |
Oct
(52) |
Nov
(17) |
Dec
(75) |
2005 |
Jan
(84) |
Feb
(191) |
Mar
(133) |
Apr
(114) |
May
(158) |
Jun
(185) |
Jul
(62) |
Aug
(28) |
Sep
(36) |
Oct
(88) |
Nov
(65) |
Dec
(43) |
2006 |
Jan
(85) |
Feb
(62) |
Mar
(92) |
Apr
(75) |
May
(68) |
Jun
(101) |
Jul
(73) |
Aug
(37) |
Sep
(91) |
Oct
(65) |
Nov
(30) |
Dec
(39) |
2007 |
Jan
(24) |
Feb
(28) |
Mar
(10) |
Apr
(2) |
May
(18) |
Jun
(16) |
Jul
(21) |
Aug
(6) |
Sep
(30) |
Oct
(31) |
Nov
(153) |
Dec
(31) |
2008 |
Jan
(63) |
Feb
(70) |
Mar
(47) |
Apr
(24) |
May
(59) |
Jun
(22) |
Jul
(12) |
Aug
(7) |
Sep
(14) |
Oct
(26) |
Nov
(5) |
Dec
(5) |
2009 |
Jan
(10) |
Feb
(41) |
Mar
(70) |
Apr
(88) |
May
(49) |
Jun
(62) |
Jul
(34) |
Aug
(15) |
Sep
(55) |
Oct
(40) |
Nov
(67) |
Dec
(21) |
2010 |
Jan
(60) |
Feb
(17) |
Mar
(26) |
Apr
(26) |
May
(29) |
Jun
(4) |
Jul
(21) |
Aug
(21) |
Sep
(10) |
Oct
(12) |
Nov
(3) |
Dec
(19) |
2011 |
Jan
(3) |
Feb
(13) |
Mar
(8) |
Apr
(8) |
May
(17) |
Jun
(20) |
Jul
(21) |
Aug
(7) |
Sep
|
Oct
|
Nov
(9) |
Dec
(11) |
2012 |
Jan
(3) |
Feb
|
Mar
|
Apr
(5) |
May
(4) |
Jun
(14) |
Jul
(5) |
Aug
(2) |
Sep
(15) |
Oct
(2) |
Nov
(23) |
Dec
(1) |
2013 |
Jan
(8) |
Feb
(1) |
Mar
|
Apr
|
May
(5) |
Jun
(1) |
Jul
(5) |
Aug
(4) |
Sep
|
Oct
(12) |
Nov
(10) |
Dec
(3) |
2014 |
Jan
(7) |
Feb
(14) |
Mar
(2) |
Apr
|
May
(2) |
Jun
(11) |
Jul
(10) |
Aug
(4) |
Sep
|
Oct
(8) |
Nov
(1) |
Dec
(2) |
2015 |
Jan
(9) |
Feb
(7) |
Mar
(1) |
Apr
|
May
(7) |
Jun
|
Jul
(5) |
Aug
(6) |
Sep
|
Oct
(1) |
Nov
(4) |
Dec
|
2016 |
Jan
(1) |
Feb
(1) |
Mar
(4) |
Apr
(2) |
May
(1) |
Jun
|
Jul
(6) |
Aug
(8) |
Sep
(21) |
Oct
(17) |
Nov
|
Dec
(36) |
2017 |
Jan
(6) |
Feb
(2) |
Mar
(4) |
Apr
(2) |
May
|
Jun
|
Jul
(1) |
Aug
|
Sep
(1) |
Oct
|
Nov
(1) |
Dec
(6) |
2018 |
Jan
(2) |
Feb
(3) |
Mar
(3) |
Apr
(14) |
May
(2) |
Jun
(2) |
Jul
(4) |
Aug
(3) |
Sep
(6) |
Oct
(16) |
Nov
(1) |
Dec
(6) |
2019 |
Jan
(3) |
Feb
(1) |
Mar
|
Apr
|
May
|
Jun
|
Jul
(2) |
Aug
|
Sep
|
Oct
(6) |
Nov
|
Dec
|
2020 |
Jan
|
Feb
|
Mar
(1) |
Apr
|
May
(2) |
Jun
(1) |
Jul
(7) |
Aug
(1) |
Sep
(1) |
Oct
|
Nov
(2) |
Dec
(1) |
2021 |
Jan
(1) |
Feb
|
Mar
|
Apr
|
May
|
Jun
(2) |
Jul
|
Aug
(5) |
Sep
(1) |
Oct
|
Nov
(1) |
Dec
|
2023 |
Jan
|
Feb
|
Mar
|
Apr
(1) |
May
|
Jun
|
Jul
|
Aug
|
Sep
(2) |
Oct
|
Nov
|
Dec
|
2025 |
Jan
(2) |
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: Bill B. <bb...@co...> - 2003-01-14 21:07:49
|
Nothing so complex -- it is just a bug in NSApplicationMain(). NSApplicationMain() ignores the array of arguments passed to it and uses [[NSProcessInfo processInfo] arguments] instead. Since the first 'argument' that NSApplicationMain() sees is the __main__.py script in the app wrapper and the app knows nothing about the .py type, the app assumes that it is openeing a document, but that the document type is uknown. End result: nothing happens on launch -- no blank window. It was easy to fix and the fix has been committed -- the multiple document app template now works just like the Cocoa-ObjC counterpart. However, the fix is very evil. The following can be found in _AppKit.m in the NSApplicationMain() wrapper: { typedef struct { @defs(NSProcessInfo) } NSProcessInfoStruct; // everything in this scope is evil and wrong. It leaks, too. NSMutableArray *args = [[NSMutableArray alloc] init]; NSProcessInfo *processInfo = [NSProcessInfo processInfo]; char **anArg = argv; while(*anArg) { [args addObject: [NSString stringWithUTF8String: *anArg]]; anArg++; } ((NSProcessInfoStruct *)processInfo)->arguments = args; } res = NSApplicationMain(argc, argv); Evil and wrong, but works. When Apple fixes the bug in NSApplicationMain(), this can be removed. (What is really happening is that NSApplicationMain() ends up with the command line that was passed *to the python interpreter* when it should end up with the command line passed *to the script*...) b.bum |
From: Jack J. <Jac...@or...> - 2003-01-14 20:58:34
|
I've thought about what you see for a long time, but I can't figure out what is going on, it doesn't make sense. Let me first explain what I thought was going on when Bob mentioned the missing Apple event. My reasoning was that what causes the untitled window to open in an ObjC application is the "open application" event that the finder sends when you double-click the app. If this is the case then your PyObjC application will indeed not open an untitled window, because the "open application" Apple Event will be sent to the stub application which fires up Python, not to Python (and, hence, it will be lost to your PyObjC code). It should be simple to test whether this reasoning is correct: if you start an ObjC application from the Terminal window with ..../xxx.app/Contents/MacOS/xxx it will not open an untitled window. But your findings makes things more complicated. The only thing I can imagine is that NSApplicationMain() looks at argv and if argv isn't the -psn_xxxx magic option it knows it has been started from the command line, and uses argv to construct either an Open Application message (argv empty) or an Open Doc message (argv non-empty). Again, this is easy to test: if it's true then the test above failed (an untitled window was opened), but if you start from the Terminal with a -psn_xxxx option the window will not be opened. And if you pass a filename that file will be opened. On dinsdag, jan 14, 2003, at 17:10 Europe/Amsterdam, Bill Bumgarner wrote: > On Tuesday, Jan 14, 2003, at 10:46 US/Eastern, Bob Ippolito wrote: >> Well the only thing I can think of off the top of my head is that >> there could be some apple event magic happening that causes the new >> untitled document event, and the apple event just isn't being >> handled? > > Damn. Figured it out. Yuck. > > If I add... > > def application_openFile_(self, sender, path): > NSLog("application_openFile_() %s %s" % (sender, path)) > return YES > > ... to the app delegate, this is logged: > > 2003-01-14 10:59:53.731 doctest[17445] application_openFile_() > <NSApplication objective-c instance 0x2c0cb0> > /tmp/bbum-products/doctest.app/Contents/Resources/__main__.py > > In other words, the command line that is passed into python needs to > be massaged before NSApplicationMain() is called. Specifically, the > path to the main.py file needs to be stripped and it needs to be done > from the C side because NSApplicationMain() ignores the argv argument > passed into it. > > Fun, fun. > > Will look into this later today when I have some time... > > b.bum > > > > ------------------------------------------------------- > This SF.NET email is sponsored by: FREE SSL Guide from Thawte > are you planning your Web Server Security? Click here to get a FREE > Thawte SSL guide and find the answers to all your SSL security issues. > http://ads.sourceforge.net/cgi-bin/redirect.pl?thaw0026en > _______________________________________________ > Pyobjc-dev mailing list > Pyo...@li... > https://lists.sourceforge.net/lists/listinfo/pyobjc-dev > -- - Jack Jansen <Jac...@or...> http://www.cwi.nl/~jack - - If I can't dance I don't want to be part of your revolution -- Emma Goldman - |
From: <bb...@ma...> - 2003-01-14 19:55:30
|
On Tuesday, Jan 14, 2003, at 14:46 US/Eastern, Just van Rossum wrote: >> There are cases where this will not work -- Ronald has already had to >> special case around a number of them. NSData, NSArray, and NSCell (I >> think) are examples. Not because of bugs in Foundation/AppKit, but >> because of the implementation pattern used. > > So how _do_ you instantiate these classes? Very carefully. :-) Have a look at the alloc hack stuff in the source... b.bum |
From: Just v. R. <ju...@le...> - 2003-01-14 19:49:44
|
bb...@ma... wrote: > There are cases where this will not work -- Ronald has already had to > special case around a number of them. NSData, NSArray, and NSCell (I > think) are examples. Not because of bugs in Foundation/AppKit, but > because of the implementation pattern used. So how _do_ you instantiate these classes? Just |
From: <bb...@ma...> - 2003-01-14 19:39:54
|
On Tuesday, Jan 14, 2003, at 14:24 US/Eastern, Just van Rossum wrote: > bb...@ma... wrote: > >>> self = cls.alloc() >>> self.release() # ownership transferred to the Python > wrapper >>> return self >> >> This code is lacking the call to the -init method -- problematic. > > I was thinking of this pattern, which is not 100% Pythonic, yet 100% > better than having to do a release() "by hand": > > inst = ASubclassOfNSObject().init() > > So basically "i = cls()" is equivalent to "i = cls.alloc(); > i.release()". There are cases where this will not work -- Ronald has already had to special case around a number of them. NSData, NSArray, and NSCell (I think) are examples. Not because of bugs in Foundation/AppKit, but because of the implementation pattern used. It would have to be something like.... i = cls.alloc() i.autorelease() ... anyway. (but won't work because of the reasons noted above) >> What about arguments to the constructor? We can handle the no >> argument case transparently, but what about-- say-- NSView's >> -initWithFrame: designated initializer? > > aView = NSView().initWithFrame(...) Makes sense. >> Also, keep in mind that -init* methods return an object reference for >> a reason; a number of intializers return a different instance than >> the one that was called for a number of [valid] reasons. > > Solved above ;-) Except manipulating the retain count on the return value from +alloc* leads to really nasty crashes (of which, some *are* bugs in the Foundation/AppKit -- Ronald has reported a couple, I believe). >>> This doesn't touch the alloc() semantics, yet provides a much more >>> Pythonic way to create instances. Heck, this will even call >>> __init__() for you! ;-) >> >> But __init__() is not generally the designated intiailizer for ObjC >> classes-- even Python implemented subclasses of ObjC classes. >> >> When subclassing ObjC from Python, it makes more sense to follow the >> ObjC semantics than the Python semantics -- at least, it does to me. > > Sure, but calling __init__ won't hurt either if you're writing an > NSObject subclass solely to be instantiated from Python. But I'm afraid > this behavior is implicit in the Python object protocol (since 2.2). I > _think_ it's this: > > inst = cls.__new__(cls, *args, **kwargs) > if isinstance(inst, cls): > inst.__init__(*args, **kwargs) > > (I also think it's identical for tp_new/tp_init on the C side.) True. And I'm all for anything that can make the Python side of the bridge more pythonic -- as long as it can be done consistently and without introducing instability. b.bum |
From: Just v. R. <ju...@le...> - 2003-01-14 19:24:04
|
bb...@ma... wrote: > > self = cls.alloc() > > self.release() # ownership transferred to the Python wrapper > > return self > > This code is lacking the call to the -init method -- problematic. I was thinking of this pattern, which is not 100% Pythonic, yet 100% better than having to do a release() "by hand": inst = ASubclassOfNSObject().init() So basically "i = cls()" is equivalent to "i = cls.alloc(); i.release()". > What about arguments to the constructor? We can handle the no > argument case transparently, but what about-- say-- NSView's > -initWithFrame: designated initializer? aView = NSView().initWithFrame(...) > Also, keep in mind that -init* methods return an object reference for > a reason; a number of intializers return a different instance than > the one that was called for a number of [valid] reasons. Solved above ;-) > > This doesn't touch the alloc() semantics, yet provides a much more > > Pythonic way to create instances. Heck, this will even call > > __init__() for you! ;-) > > But __init__() is not generally the designated intiailizer for ObjC > classes-- even Python implemented subclasses of ObjC classes. > > When subclassing ObjC from Python, it makes more sense to follow the > ObjC semantics than the Python semantics -- at least, it does to me. Sure, but calling __init__ won't hurt either if you're writing an NSObject subclass solely to be instantiated from Python. But I'm afraid this behavior is implicit in the Python object protocol (since 2.2). I _think_ it's this: inst = cls.__new__(cls, *args, **kwargs) if isinstance(inst, cls): inst.__init__(*args, **kwargs) (I also think it's identical for tp_new/tp_init on the C side.) Just |
From: <bb...@ma...> - 2003-01-14 19:12:44
|
On Tuesday, Jan 14, 2003, at 13:57 US/Eastern, Just van Rossum wrote: > Ugh, this is depressing :-(. (So you _can_ find out the return type of > a > method at runtime but not whether it returns a new or a borrowed > reference. Great.) Correct. There is no concept of 'new vs. borrowed' at anything but the object level. This isn't a problem from the Objective-C side of the fence -- it is only a problem in that Python and ObjC take different approaches to solving the memory management problem. I like Python's a lot better, but I have to live with ObjC's because I'm leveraging ObjC frameworks-- even when writing PyObJC code. > Here's a quick idea to work around the most common (I think) > irritation: > instead of raising an exception when calling a (subclass of) NSObject > ("TypeError: Use class methods to instantiate new Objective-C objects") > have objc-object.m::object_new() do this: > > self = cls.alloc() > self.release() # ownership transferred to the Python wrapper > return self This code is lacking the call to the -init method -- problematic. What about arguments to the constructor? We can handle the no argument case transparently, but what about-- say-- NSView's -initWithFrame: designated initializer? Also, keep in mind that -init* methods return an object reference for a reason; a number of intializers return a different instance than the one that was called for a number of [valid] reasons. > This doesn't touch the alloc() semantics, yet provides a much more > Pythonic way to create instances. Heck, this will even call __init__() > for you! ;-) But __init__() is not generally the designated intiailizer for ObjC classes-- even Python implemented subclasses of ObjC classes. When subclassing ObjC from Python, it makes more sense to follow the ObjC semantics than the Python semantics -- at least, it does to me. > What I still don't understand is how pyobjc manages the refcount of > Python objects passed to objc: the Python object can't have a reference > to it, so when will the wrapper be released? Is it an autorelease > object? Ronald can better answer this question. b.bum |
From: Just v. R. <ju...@le...> - 2003-01-14 18:57:28
|
bb...@ma... wrote: > Thread starts here: > > http://sourceforge.net/mailarchive/message.php?msg_id=2347617 > > But this particular response [of mine] contains the most detailed > explanation on why I don't believe it is possible to eliminate > retain/release/autorelease entirely from the Python side of the > bridge: > > http://sourceforge.net/mailarchive/message.php?msg_id=2349810 > > And another thread that may also be illuminating: > > http://sourceforge.net/mailarchive/message.php?msg_id=2342178 > > And another thread: > > http://sourceforge.net/mailarchive/message.php?msg_id=2331515 Ugh, this is depressing :-(. (So you _can_ find out the return type of a method at runtime but not whether it returns a new or a borrowed reference. Great.) Here's a quick idea to work around the most common (I think) irritation: instead of raising an exception when calling a (subclass of) NSObject ("TypeError: Use class methods to instantiate new Objective-C objects") have objc-object.m::object_new() do this: self = cls.alloc() self.release() # ownership transferred to the Python wrapper return self This doesn't touch the alloc() semantics, yet provides a much more Pythonic way to create instances. Heck, this will even call __init__() for you! ;-) What I still don't understand is how pyobjc manages the refcount of Python objects passed to objc: the Python object can't have a reference to it, so when will the wrapper be released? Is it an autorelease object? Just |
From: <bb...@ma...> - 2003-01-14 17:12:58
|
On Tuesday, Jan 14, 2003, at 11:51 US/Eastern, Just van Rossum wrote: ... interesting stuff deleted ... > I searched, to no avail. Any specific pointers or google keywords? Basically, it boils down to the same reason why we don't do name mangling -- it is easy to do something that works 90% of the time, impossible to do something that works 100% of the time and that 10% of the time is a real serious pain in the butt to debug/deal with. When using PyObjC, you cannot ignore the fact that you are effectively using Objective-C from Python. The memory management semantics of ObjC *will* leak through the bridge due to inconsistencies and idiosyncracies within the implementation of classes -- known and unknown (i.e. third party) -- on the ObjC side. Thread starts here: http://sourceforge.net/mailarchive/message.php?msg_id=2347617 But this particular response [of mine] contains the most detailed explanation on why I don't believe it is possible to eliminate retain/release/autorelease entirely from the Python side of the bridge: http://sourceforge.net/mailarchive/message.php?msg_id=2349810 And another thread that may also be illuminating: http://sourceforge.net/mailarchive/message.php?msg_id=2342178 And another thread: http://sourceforge.net/mailarchive/message.php?msg_id=2331515 b.bum |
From: Just v. R. <ju...@le...> - 2003-01-14 16:51:16
|
bb...@ma... wrote: > On Tuesday, Jan 14, 2003, at 05:00 US/Eastern, Just van Rossum wrote: > > Hm, I just discovered .release() returns None. If I do the > > release() separately it works just fine. I still don't understand > > why cls.alloc().init() would result in a retainCount of 2, though. > > Every time I see a retain() or release() call in Python code I > > can't help but think there's something terribly wrong :-( > > It has to do with the way the retain/release mechanism works. In > any case, you have one -retain for alloc() and one for the assignment > in python. Why? The caller of alloc() becomes the owner, and I don't see why the Python wrapper *wouldn't* become the owner. > I agree that it would be very, very nice NOT to have to ever deal > with retain/release/autorelease on the Python side of the PyObjC > bridge. Unfortunately, it appears to be impossible [AFAICT] to > automate the management of retain/release/autorelease with 100% > reliability. Anything that makes assumptions regarding retain counts > and adjusts the count downwards automatically will lead to situations > where the app blows up. I don't see why it's a bad "assumption" that the Python wrapper becomes the owner of the reference, IMHO it's only natural. I've tried to read the implementation (class-object.m) but I can't follow it at all because of the complexity. I seem to see that it attempts to synchronize the objc retainCount and the Python ob_refcnt. Why is that? I would think the Python wrapper for an objc object only needs to own one reference and vice versa for an objc wrapper for a Python object. I'm sure I'm missing something subtle, but now is as good a time to learn about how it works as any ;-) When creating a Python wrapper, there should be a difference between "wrap an existing ref" and "wrap a new ref". > Ronald and I discussed this at length some time ago-- I believe it > was before you had become active on the project. There is actually > code to maintain the release counts automatically, it is currently > commented out. Check the archives for more information.... I searched, to no avail. Any specific pointers or google keywords? Just |
From: Bill B. <bb...@co...> - 2003-01-14 16:49:17
|
.... and filed. Bummer. b.bum |
From: Bill B. <bb...@co...> - 2003-01-14 16:11:06
|
On Tuesday, Jan 14, 2003, at 10:46 US/Eastern, Bob Ippolito wrote: > Well the only thing I can think of off the top of my head is that > there could be some apple event magic happening that causes the new > untitled document event, and the apple event just isn't being handled? Damn. Figured it out. Yuck. If I add... def application_openFile_(self, sender, path): NSLog("application_openFile_() %s %s" % (sender, path)) return YES ... to the app delegate, this is logged: 2003-01-14 10:59:53.731 doctest[17445] application_openFile_() <NSApplication objective-c instance 0x2c0cb0> /tmp/bbum-products/doctest.app/Contents/Resources/__main__.py In other words, the command line that is passed into python needs to be massaged before NSApplicationMain() is called. Specifically, the path to the main.py file needs to be stripped and it needs to be done from the C side because NSApplicationMain() ignores the argv argument passed into it. Fun, fun. Will look into this later today when I have some time... b.bum |
From: Bob I. <bo...@ma...> - 2003-01-14 15:46:36
|
Well the only thing I can think of off the top of my head is that there could be some apple event magic happening that causes the new untitled document event, and the apple event just isn't being handled? On Tuesday, Jan 14, 2003, at 10:03 America/New_York, Bill Bumgarner wrote: > I have it basically done, but am running into the same problem we ran > into ages ago. > > Specifically, when the app launches it does not create a new, > untitled, document. > > I have no clue why. There should be no difference between my > template and the Apple template save for the use of the PyObjC bridge. > > But something is either different or broken. > > Anyone have any ideas??? > > I'm going to clean up the template a bit and commit it to CVS later > today -- hopefully I'll find the problem, but... > > (If anyone wants to beat their head on this wall, I'll send you a > sample project resulting from the template -- the template doesn't > quite work, I just need to integrate my changes to the sample project > back into the template) |
From: Bill B. <bb...@co...> - 2003-01-14 15:38:39
|
I have it basically done, but am running into the same problem we ran into ages ago. Specifically, when the app launches it does not create a new, untitled, document. I have no clue why. There should be no difference between my template and the Apple template save for the use of the PyObjC bridge. But something is either different or broken. Anyone have any ideas??? I'm going to clean up the template a bit and commit it to CVS later today -- hopefully I'll find the problem, but... (If anyone wants to beat their head on this wall, I'll send you a sample project resulting from the template -- the template doesn't quite work, I just need to integrate my changes to the sample project back into the template) b.bum |
From: Dinu G. <gh...@da...> - 2003-01-14 13:07:22
|
Just van Rossum: > I've attached a little Python Object browser using an NSOutlineView I > recently hacked up. The attached is slightly newer than what I posted > here before. Thanks, this looks very promising and useful for a future Cocoa Python IDE! ;-) Ronald, thanks for your comemnts as well! Moving to dedicated item class subclassed from NSObject finally did the job! This is a current state screenshot: http://python.net/~gherman/tmp/XMLTreeView1.png Now, I'll need to move from displaying to editing XML, possibly with auto-validation as you go... Dinu -- Dinu C. Gherman ...................................................................... "I can't understand why people are frightened of new ideas. I'm frightened of the old ones." (John Cage) |
From: <bb...@ma...> - 2003-01-14 13:05:13
|
On Tuesday, Jan 14, 2003, at 05:00 US/Eastern, Just van Rossum wrote: >>> PythonItem.__new__ should return cls.alloc().init().release(). > > Hm, I just discovered .release() returns None. If I do the release() > separately it works just fine. I still don't understand why > cls.alloc().init() would result in a retainCount of 2, though. Every > time I see a retain() or release() call in Python code I can't help but > think there's something terribly wrong :-( It has to do with the way the retain/release mechanism works. In any case, you have one -retain for alloc() and one for the assignment in python. I agree that it would be very, very nice NOT to have to ever deal with retain/release/autorelease on the Python side of the PyObjC bridge. Unfortunately, it appears to be impossible [AFAICT] to automate the management of retain/release/autorelease with 100% reliability. Anything that makes assumptions regarding retain counts and adjusts the count downwards automatically will lead to situations where the app blows up. Ronald and I discussed this at length some time ago-- I believe it was before you had become active on the project. There is actually code to maintain the release counts automatically, it is currently commented out. Check the archives for more information.... b.bum |
From: Just v. R. <ju...@le...> - 2003-01-14 10:00:08
|
Just van Rossum wrote: > > PythonItem.__new__ should return cls.alloc().init().release(). Hm, I just discovered .release() returns None. If I do the release() separately it works just fine. I still don't understand why cls.alloc().init() would result in a retainCount of 2, though. Every time I see a retain() or release() call in Python code I can't help but think there's something terribly wrong :-( Just |
From: <bb...@ma...> - 2003-01-13 22:42:13
|
I had thought enumerators should "just work" in PyObjC? I should be able to do... for x in array.objectEnumerator(): print x ... and it'll just work. Oh, wait, that's 'for x in array:'. We need to be able to do 'for x in anObject.objectEnumerator():', as well. Specifically, for table view: for x in aTableView.rowEnumerator(): ... manipulate x ... rowEnumerator() returns an enumerator that enumerates the selected row indices. Very handy. (Trivial change in the bridge, I have zero time to do it now... I'll get to this sometime soon unless someone [hopefully] beats me to it. :-) b.bum |
From: Just v. R. <ju...@le...> - 2003-01-13 22:16:36
|
Btw. here's the version of PythonBrowser.py that keeps child references. Just |
From: Just v. R. <ju...@le...> - 2003-01-13 22:11:15
|
Ronald Oussoren wrote: > On Monday, Jan 13, 2003, at 21:27 Europe/Amsterdam, Just van Rossum > wrote: > > > Btw. there's in interesting thing going on in this app: if the > > PythonItem class is a subclass of NSObject everything works fine, > > but if it isn't (a pure Python class), the app crashes as soon as > > you click inside the tree widget. Maybe there's some refcount > > problem for Python objects passed to objc? > > This is a feature(*) of NSOutlineView. The outline view does not call > retain on the objects you return from methods like > outlineView:child:ofItem:, but it does keep around references to > those objects. This is documented in 'Using an Outline View Data > Source' in Apple's developer documents. Aha, I'll try to find that document. > The reason your code is crashing when PythonItem is not subclassed > from NSObject and runs correctly when it is twofold. > > First of all 'normal' python objects are brigded to Objective-C using > autoreleased proxy objects. Because the outline-view doesn't call > retain these will be released 'soon'. And because the outline-view > does actually use the pointer later your program crashes... > > If you subclass from NSObject your object is bridged as itself (more > or less). And if you keep around a reference to the objects you > return these objects won't go away before the outline-view uses the > pointer it stashed away. Which brings me to your second problem: You > code is leaking memory. > > PythonItem.__new__ should return cls.alloc().init().release(). Ha, when I make that change the app crashes right away ;-) But the reason is now more clear: I didn't keep any child references around at all, so the instances NSObject subclass would be alive just long enough (due to the autorelease pool magic I assume) and the non-NSObject subclass instances weren't. Or they indeed leaked. I changed the code to keep references to the children and everything works just fine as a non-NSObject subclass. But now it *does* crash when subclassing NSObject if I add .release() to the __new__ method, so something isn't right, most likely in my understanding of things... > (*) Actually I think this is not a feature but a bug. I've filed a > bug for this at Apple, but did not receive a response for this yet. I > hope Apple changes this, especially because adding the proper calls > to retain and release should be backward compatible (although I have > no idea what effect this would have on the performance of > NSOutlineView) It's at least a lousy feature :-( Just |
From: Ronald O. <ous...@ci...> - 2003-01-13 21:46:27
|
On Monday, Jan 13, 2003, at 21:27 Europe/Amsterdam, Just van Rossum wrote: > I wrote: > >> I've attached a little Python Object browser using an NSOutlineView I >> recently hacked up. The attached is slightly newer than what I posted >> here before. > > Btw. there's in interesting thing going on in this app: if the > PythonItem class is a subclass of NSObject everything works fine, but > if > it isn't (a pure Python class), the app crashes as soon as you click > inside the tree widget. Maybe there's some refcount problem for Python > objects passed to objc? This is a feature(*) of NSOutlineView. The outline view does not call retain on the objects you return from methods like outlineView:child:ofItem:, but it does keep around references to those objects. This is documented in 'Using an Outline View Data Source' in Apple's developer documents. The reason your code is crashing when PythonItem is not subclassed from NSObject and runs correctly when it is twofold. First of all 'normal' python objects are brigded to Objective-C using autoreleased proxy objects. Because the outline-view doesn't call retain these will be released 'soon'. And because the outline-view does actually use the pointer later your program crashes... If you subclass from NSObject your object is bridged as itself (more or less). And if you keep around a reference to the objects you return these objects won't go away before the outline-view uses the pointer it stashed away. Which brings me to your second problem: You code is leaking memory. PythonItem.__new__ should return cls.alloc().init().release(). The call to release is necessary to adjust the reference count. The problem is that alloc is one of a few methods that returns a object that is owned by the caller, almost all other methods that return an object require that you call retain if you want to keep the object around. The bridge contains code to deal with this, but I didn't manage to convince Bill that automaticly adjusting the reference is a good idea. The mailinglist archive should contain more information. I still think that automaticly adjusting the references would be a good idea, and will get back to this later... Ronald (*) Actually I think this is not a feature but a bug. I've filed a bug for this at Apple, but did not receive a response for this yet. I hope Apple changes this, especially because adding the proper calls to retain and release should be backward compatible (although I have no idea what effect this would have on the performance of NSOutlineView) |
From: Just v. R. <ju...@le...> - 2003-01-13 20:27:53
|
I wrote: > I've attached a little Python Object browser using an NSOutlineView I > recently hacked up. The attached is slightly newer than what I posted > here before. Btw. there's in interesting thing going on in this app: if the PythonItem class is a subclass of NSObject everything works fine, but if it isn't (a pure Python class), the app crashes as soon as you click inside the tree widget. Maybe there's some refcount problem for Python objects passed to objc? Just |
From: Bill B. <bb...@co...> - 2003-01-13 16:28:10
|
On Sunday, Jan 12, 2003, at 12:20 US/Eastern, Dinu Gherman wrote: > Well, I'm trying to follow what is mandates for running an install > build on a different (10.1) box with Python in /usr/local/bin. So > far I tried skipping some of the environment variables, but with no > luck. In any case, I think I can't assume a non-Python user to go > through the list in order to run any pyobjc app. OS X 10.1 doesn't ship with Python, so the user will have to have installed some kind of a Python distribution (or the app will need to ship with Python in the app wrapper). In either case, such a distribution will very likely be 'embeddable'. That is, will have a library, framework or dynamic-lib such that the interpreter can be embedded directly and the app won't have to hunt down the python distribution to be used. As such, you would probably want to use the 'Cocoa-Python Application (Embedded Interpreter)' template, which doesn't yet exist (but will soon, depending on the answer to the question I posed earlier today). PyObjC doesn't currently support OS X 10.1 anyway. It would not be hard to add -- easier now that GNUstep support has caused the 'build this version vs. that version' question to be answered with a concrete implementation. Because one of PyObjC's requirements is to support the build of Python that Apple ships with OS X, the default is to go after the python binary and do the execve() garbage. The assumption is also made that a python binary exists in /usr/bin/python and that most developers/users will never need to change it. > Could they maybe bootstrap themselves using a shell script that de- > termines the location of the current Python interpreter and does > the rest magically before kicking off the app itself? Yes. The bin-python-main.m could do exactly that. It is simply a matter of invoking `env python` via popen(), I believe. Of course, that will not pick up a python executable that only appears in the user's path in a Terminal environment. If that fails, a very simple binary could be provided that pops an Open Panel and asks the user to identify their python binary. Would not be hard to write, could be standardized and could be an added copy phase on the existing app projects (or a single source file).... b.bum |
From: <bb...@ma...> - 2003-01-13 16:25:52
|
On Sunday, Jan 12, 2003, at 16:53 US/Eastern, Ronald Oussoren wrote: >> Hmm, another wild idea: would this mean that by declaring a category >> on the metaclass you could influence creation of all ObjC objects? > You probably could, but: the metaclass has the same name as the normal > class which makes it hard to define a category on it. But is guess > defining a category containing class-mehods on a normal class would do > what you want. Adding methods to a class via a category works just like instance methods; the methods will be added and all of the inheritance based method dispatch rules will be followed. You can add methods in a category to NSObject to influence all classes rooted at NSObject (ObjC does not require you to use NSObject as the root class or even have a superclasss at all). Keep in mind that categories that override existing functionality are generally evil in any context but in an application-- even then, they are dangerous. Overriding existing functionality means that you are changing the behavior of the overridden API in a fashion where people using that API have no way of accessing the original functionality. -- Posing allows one to access the original implementation. That is, I could override NSObject's -description (or +description) method in a subclass, tell that subclass to pose as NSObject, and my functionality would override NSObject's implementation. Unlike categories, I could still invoke the original implementation by calling [super description] in my description method. -- Method swizzling involves directly editing the objective-c runtime to change the behavior of an existing object. A very handy tool. For example, if the following class is loaded into an application, it will cause NSUserDefaults to print every default and its value as the application accesses the defaults: @interface NoisyDefaults:NSUserDefaults @end @implementation NoisyDefaults static IMP ofk; id objectForKey(self, _cmd, defaultName) { id v = ofk(self, _cmd, defaultName); fprintf(stdout, "%s ==> %s\n", [defaultName cString], [[v description] cString]); return v; } +(void) load { Method origM; origM = class_getInstanceMethod([NSUserDefaults class], @selector(objectForKey:)); ofk = origM->method_imp; origM->method_imp = objectForKey; } @end Swizzling is a handy debugging tool, but should be avoided in real world situations. -- ObjC also provides lower level tools for manipulating the behavior of the runtime. PyObjC uses these APIs to build classes on the fly (and-- someday-- categories, too). OBJC_EXPORT void objc_setClassHandler(int (*)(const char *)); /* overriding the default object allocation and error handling routines */ OBJC_EXPORT id (*_alloc)(Class, unsigned int); OBJC_EXPORT id (*_copy)(id, unsigned int); OBJC_EXPORT id (*_realloc)(id, unsigned int); OBJC_EXPORT id (*_dealloc)(id); OBJC_EXPORT id (*_zoneAlloc)(Class, unsigned int, void *); OBJC_EXPORT id (*_zoneRealloc)(id, unsigned int, void *); OBJC_EXPORT id (*_zoneCopy)(id, unsigned int, void *); OBJC_EXPORT void (*_error)(id, const char *, va_list); |
From: Just v. R. <ju...@le...> - 2003-01-13 16:25:00
|
Dinu Gherman wrote: > Hi, I'm banging my head against NSOutlineView's dataSource methods, > trying to hack a little XML editor, and I'm not sure if it's just > my sillyness or some bad surprises of PyObjC type conversion, sigh! > > In any case these methods don't seem to work as expected passing > None as an item value far more often than I'd expect, so I wonder > if anybody here has some simple code to share? I'd be glad to pro- > vide the little test code I'm running myself... I've attached a little Python Object browser using an NSOutlineView I recently hacked up. The attached is slightly newer than what I posted here before. Just |