pyobjc-dev Mailing List for PyObjC (Page 270)
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: Just v. R. <ju...@le...> - 2003-01-18 14:48:41
|
Just van Rossum wrote: > bb...@ma... wrote: > > > I don't believe NSApplicationMain() ever returns in any > > circumstances. It calls exit() directly. > > > > NSApplicationMain's declaration is a big lie. It ignores its > > inbound arguments and the outbound arguments. > > > > At least, I think it exit()s directly. > > Ah, as it now turns out: it indeed _doesn't_ return, yet you can > succesfully wrap it in an NS_HANDLER/NS_ETC. construct. It's extremely rude what NSApplicationMain does, a finally clause as below will _only_ be called if there was an exception: try: sys.exit(AppKit.NSApplicationMain(sys.argv)) finally: print "XXX exiting!" Blech! One for the phrase book... Just |
From: Just v. R. <ju...@le...> - 2003-01-18 14:44:30
|
bb...@ma... wrote: > I don't believe NSApplicationMain() ever returns in any circumstances. > It calls exit() directly. > > NSApplicationMain's declaration is a big lie. It ignores its inbound > arguments and the outbound arguments. > > At least, I think it exit()s directly. Ah, as it now turns out: it indeed _doesn't_ return, yet you can succesfully wrap it in an NS_HANDLER/NS_ETC. construct. Just |
From: Just v. R. <ju...@le...> - 2003-01-18 14:41:44
|
Bill Bumgarner wrote: > Did the change to wrapping NSApplicationMain() work as expected? Yup, works like a charm, so it does indeed return as (I) expected. Just |
From: <bb...@ma...> - 2003-01-18 14:16:22
|
On Saturday, Jan 18, 2003, at 08:50 US/Eastern, Just van Rossum wrote: >>> Additionally, if the exception is OC_PythonException, the >>> _original_ Python exception should be reraised, resulting in a >>> decent traceback. >> The support-code for exceptions in objc_util.m should do that, but >> I'm not entirely sure if we raise the same exception or a copy of it. > > I've had a look, and adding the proper handlers to the > NSApplicationMain > wrapper is straightforward. However, I'm not getting what I expected: > the traceback only shows the part in the main program. I'll investigate > and patch what I can. I don't believe NSApplicationMain() ever returns in any circumstances. It calls exit() directly. NSApplicationMain's declaration is a big lie. It ignores its inbound arguments and the outbound arguments. At least, I think it exit()s directly. b.bum |
From: Just v. R. <ju...@le...> - 2003-01-18 13:51:41
|
Ronald Oussoren wrote: > How usefull ;-(. I thought this checked if an object implements a > sequence. I did wonder how the code could detect if a __getitem__ > method is sequence-like instead of dict-like, but never thought the > check would be this lame. It's not generally possible: __getitem__ could also mean the object implements the mapping protocol. > I'll convert to check to PyList_Check || PyTuple_Check. I think this is a fine restriction. Good luck debugging... Just |
From: Just v. R. <ju...@le...> - 2003-01-18 13:50:28
|
Ronald Oussoren wrote: > > On Saturday, Jan 18, 2003, at 13:06 Europe/Amsterdam, Just van Rossum > wrote: > > > I'm wondering about ObjC exceptions: if an app throws an exception, > > could it be caught by the code that invokes the event loop? Hm, > > considering the call stack, I would think so. If this is indeed so, > > I would suggest to catch all exceptions in the > > AppKit.NSApplicationMain wrapper and convert it to a Python > > exception. Since the main program is a Python program, it makes > > sense for it to end as a real Python program instead of "crashing". > > Your right. Somehow I forgot to add a try-block around the call to > NSApplicationMain. The core module already does this for methodcalls. > > > Additionally, if the exception is OC_PythonException, the > > _original_ Python exception should be reraised, resulting in a > > decent traceback. > The support-code for exceptions in objc_util.m should do that, but > I'm not entirely sure if we raise the same exception or a copy of it. I've had a look, and adding the proper handlers to the NSApplicationMain wrapper is straightforward. However, I'm not getting what I expected: the traceback only shows the part in the main program. I'll investigate and patch what I can. Just |
From: Ronald O. <ous...@ci...> - 2003-01-18 12:54:34
|
On Wednesday, Jan 15, 2003, at 23:13 Europe/Amsterdam, Just van Rossum wrote: > I just noticed that my PythonBrowser application doesn't work > correctly after > all if I don't subclass PythonItem from NSObject. I was getting > strange messages > in the log if I tried to unpack certain items: > > 2003-01-15 21:48:37.838 python[13055] PythonItem instance has no > attribute '__getitem__' > > but I was sure *I* didn't do any subscripting on PythonItem instances. > It > appears Cocoa is calling it (*), through PyObjC, and while trying to > find what's > wrong I came across this snippet in Modules/objc/objc_support.m: > > else if (PySequence_Check(argument)) > *(id *) datum = [OC_PythonArray > newWithPythonObject:argument]; > > PySequence_Check() is a lame check, it always returns true for simple > instances. How usefull ;-(. I thought this checked if an object implements a sequence. I did wonder how the code could detect if a __getitem__ method is sequence-like instead of dict-like, but never thought the check would be this lame. I'll convert to check to PyList_Check || PyTuple_Check. > But since there's a PyDict_Check() below (which really checks > isinstance(x, > dict)), I think the following would be better/safer: > > else if (PyList_Check(argument) || PyTuple_Check(argument)) > *(id *) datum = [OC_PythonArray > newWithPythonObject:argument]; > > However, if I make that change, PythonBrowser doesn't run at all > anymore: it > crashes before any window is shown. ... And after this conversion I'll have to do some debugging. Ronald |
From: Ronald O. <ous...@ci...> - 2003-01-18 12:49:58
|
On Saturday, Jan 18, 2003, at 13:06 Europe/Amsterdam, Just van Rossum wrote: > I'm wondering about ObjC exceptions: if an app throws an exception, > could it be caught by the code that invokes the event loop? Hm, > considering the call stack, I would think so. If this is indeed so, I > would suggest to catch all exceptions in the AppKit.NSApplicationMain > wrapper and convert it to a Python exception. Since the main program is > a Python program, it makes sense for it to end as a real Python program > instead of "crashing". Your right. Somehow I forgot to add a try-block around the call to NSApplicationMain. The core module already does this for methodcalls. > > Additionally, if the exception is OC_PythonException, the _original_ > Python exception should be reraised, resulting in a decent traceback. The support-code for exceptions in objc_util.m should do that, but I'm not entirely sure if we raise the same exception or a copy of it. Ronald |
From: Just v. R. <ju...@le...> - 2003-01-18 12:06:17
|
I'm wondering about ObjC exceptions: if an app throws an exception, could it be caught by the code that invokes the event loop? Hm, considering the call stack, I would think so. If this is indeed so, I would suggest to catch all exceptions in the AppKit.NSApplicationMain wrapper and convert it to a Python exception. Since the main program is a Python program, it makes sense for it to end as a real Python program instead of "crashing". Additionally, if the exception is OC_PythonException, the _original_ Python exception should be reraised, resulting in a decent traceback. It would also allow us to catch exceptions raised by the event loop, and simply continue if it wasn't fatal enough (whatever that means ;-). Just |
From: Just v. R. <ju...@le...> - 2003-01-18 10:16:14
|
Ronald Oussoren wrote: > > Hm, I was also thinking it would have to be something different. I > > added some print statements to a simple app (the pyDotView example > > that was posted recently): > > Could you elaborate a little: > * What's the version of PyObjC Current CVS. > * The type and speed of the CPU TiBook, 400 Mhz G4. > * Do these print-statements print times from the start of the program, > or the time from the previous print statement? >From the start of the program. Sorry for being so imprecise... Just |
From: Ronald O. <ous...@ci...> - 2003-01-18 07:57:46
|
On Saturday, Jan 18, 2003, at 01:52 Europe/Amsterdam, bb...@ma... wrote: > I committed a test case that tests if poseAsClass: allows a Python > implemented subclass of an Objective-C object to pose as the > Objective-C superclass. > > It currently doesn't because Python based subclasses of Objective-C > classes *always* add at least one instance variable. Causes a fatal > error. > > Specifically (from class-builder.m): > > /* We add 1 instance variable to hybrid objective-C/Python classes, > this > * contains the reference to the python half of the class. Name should > be > * not be used by Objective-C classes that are not managed by PyObjC... > */ > static char pyobj_ivar[] = "__pyobjc_obj__"; > > I'm going to try modifying the way this all works a bit. Specifically: > > - add the method +(BOOL)__pyobjc__hasPythonImplementation to > NSObject; returns NO. A -(PyObject*)__pyobjc_pythonImplementation is probably more usefull in the long run (return NULL in NSObject, the equivalent of the current self.__pyobjc_objc__ in mixed classes and the bridged python object in OC_PythonObject and friends) Ronald |
From: Ronald O. <ous...@ci...> - 2003-01-18 07:29:05
|
On Friday, Jan 17, 2003, at 23:02 Europe/Amsterdam, Just van Rossum wrote: > [this started as a private conversation, I guess it makes more sense on > the list now] > > Bill Bumgarner wrote: > >> Yes -- I'd like to know why it is so bloody slow, as well. I guess this is because we do too much work... >> >> I'm going to have to run it through the profiler sometime soon and see >> what the deal is. >> >> Part of the problem is certainly the bridging of *all* classes. >> I.e. 'from AppKit import *' has to do a lot of work to make all of >> the classes available in the Python module, but I don't think that >> explains *all* of the slowdown. That shouldn't be too much of a problem. In the CVS version we lazily build the class __dict__, before that we did have a real problem (unnecessarily building class dictionaries for classes that don't need one). > > Hm, I was also thinking it would have to be something different. I > added > some print statements to a simple app (the pyDotView example that was > posted recently): Could you elaborate a little: * What's the version of PyObjC * The type and speed of the CPU * Do these print-statements print times from the start of the program, or the time from the previous print statement? > > (first run) > after importing objc: 0.330672979355 > after importing Foundation: 0.997979998589 > after importing AppKit: 3.49985897541 > after importing MyAppDelegate: 3.72730898857 > (starting the event loop) > initializing DotView: 11.8096979856 > > (second run) > after importing objc: 0.102402925491 > after importing Foundation: 0.417948961258 > after importing AppKit: 1.14622688293 > after importing MyAppDelegate: 1.30699288845 > (starting the event loop) > initializing DotView: 8.59571492672 > > Times in seconds from the top of __main__. The "initializing" line is > from the DotView.initWithFrame_() method. Much time is spent between > starting the event loop and setting up the window. Weird. > > This was with 2.2, however, with 2.3 I get a different number at the > end: > > (first run) > after importing objc: 0.306917071342 > after importing Foundation: 0.843237996101 > after importing AppKit: 1.79104101658 > after importing MyAppDelegate: 1.98914909363 > (starting the event loop) > initializing DotView: 3.40978002548 > > (second run) > after importing objc: 0.118615984917 > after importing Foundation: 0.377791047096 > after importing AppKit: 1.09300804138 > after importing MyAppDelegate: 1.22211098671 > (starting the event loop) > initializing DotView: 2.63563001156 > > Still very slow for a trivial app, but quite a bit better. But why? Good question. Does anyone know how to do profiling on a python extention? If all else failes I'll hack the build procedure of Python and build a python that has PyObjC as a builtin extension. I've written a simple benchmark for method dispatching and this shows that that is also sluggish. I've done my testing with python 2.3 and haven't yet checked if 2.2 is worse. I also see inconsistent results from various runs of my testscript: on some runs the difference between 'normal' python dispatching and dispatching to Objective-C is twice as large as on other runs. Ronald |
From: <bb...@ma...> - 2003-01-18 01:15:04
|
I committed a test case that tests if poseAsClass: allows a Python implemented subclass of an Objective-C object to pose as the Objective-C superclass. It currently doesn't because Python based subclasses of Objective-C classes *always* add at least one instance variable. Causes a fatal error. Specifically (from class-builder.m): /* We add 1 instance variable to hybrid objective-C/Python classes, this * contains the reference to the python half of the class. Name should be * not be used by Objective-C classes that are not managed by PyObjC... */ static char pyobj_ivar[] = "__pyobjc_obj__"; I'm going to try modifying the way this all works a bit. Specifically: - add the method +(BOOL)__pyobjc__hasPythonImplementation to NSObject; returns NO. - add the same method to all "mixed" classes as the class is created in class-builder.m It will return YES. - eliminate pyobj_ivar from class-builder.m entirely End result; no additional ivar in Python subclasses of ObjC classes. This *should* be enough to make posing work. It will likely also be a step in the right direction for categories. b.bum |
From: Just v. R. <ju...@le...> - 2003-01-17 23:42:22
|
Jack Jansen wrote: > If running the profiler is difficult you could start with a ktrace > (which is supported since 10.2, yeah!). Start python, in another > window do "ktrace -p pid", do the Python bits you're interested in > and then do "ktrace -C". You'll only get a system call trace, but if > you show it with "kdump -T" you'll get timestamps and it may give an > idea where the time is going. Hm, since this is about the startup time of an app bundle, I don't see how to get the pid in time to start ktrace. Hm, maybe the app should do something like os.system("ktrace -p %s" % os.getpid())? Would that work? After reading the man page: yeah, should work, -f <outfile> should come in handy. Off to bed now, Just |
From: Jack J. <Jac...@or...> - 2003-01-17 23:31:28
|
On vrijdag, jan 17, 2003, at 23:02 Europe/Amsterdam, Just van Rossum wrote: > Bill Bumgarner wrote: > >> Yes -- I'd like to know why it is so bloody slow, as well. >> >> I'm going to have to run it through the profiler sometime soon and see >> what the deal is. If running the profiler is difficult you could start with a ktrace (which is supported since 10.2, yeah!). Start python, in another window do "ktrace -p pid", do the Python bits you're interested in and then do "ktrace -C". You'll only get a system call trace, but if you show it with "kdump -T" you'll get timestamps and it may give an idea where the time is going. -- - 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: Just v. R. <ju...@le...> - 2003-01-17 22:21:57
|
Weird thing: >>> from Foundation import NSObject >>> class MyClass(NSObject): ... def foo(self): ... pass ... bar = foo ... >>> f = MyClass.alloc().init() >>> f.foo <selector foo of <MyClass objective-c instance 0xbe5280>> >>> f.bar <selector foo of <MyClass objective-c instance 0xbe5280>> >>> f.respondsToSelector_("foo") 1 >>> f.respondsToSelector_("bar") 0 >>> Are the selectors built from func.func_name instead of the key in the method dict passed to the meta class at class-build-time? [ ...doing some research... ] Ah, yes, that's it. This patch fixes it: Index: class-builder.m =================================================================== RCS file: /cvsroot/pyobjc/pyobjc/Modules/objc/class-builder.m,v retrieving revision 1.11 diff -c -r1.11 class-builder.m *** class-builder.m 6 Jan 2003 21:15:17 -0000 1.11 --- class-builder.m 17 Jan 2003 22:13:45 -0000 *************** *** 440,446 **** METHOD meth; int is_class_method = 0; ! pyname = PyObject_GetAttrString(value, "__name__"); if (pyname == NULL) continue; name = PyString_AS_STRING(pyname); --- 440,446 ---- METHOD meth; int is_class_method = 0; ! pyname = key; if (pyname == NULL) continue; name = PyString_AS_STRING(pyname); This also fixes a memory leak: pyname was never decref'd. I'd gladly check this in if ok. Although: the pyname variable could then go away altogether. Btw. it would be more efficient to not build a key list, but use the PyDict_Next API to iterate over the dict items (see http://www.python.org/doc/current/api/dictObjects.html). I doubt this part of the code is crucial for the startup time, so I don't think this optimization should be a priority... (It would clean up the code somewhat, though.) Just |
From: Just v. R. <ju...@le...> - 2003-01-17 22:02:23
|
[this started as a private conversation, I guess it makes more sense on the list now] Bill Bumgarner wrote: > Yes -- I'd like to know why it is so bloody slow, as well. > > I'm going to have to run it through the profiler sometime soon and see > what the deal is. > > Part of the problem is certainly the bridging of *all* classes. > I.e. 'from AppKit import *' has to do a lot of work to make all of > the classes available in the Python module, but I don't think that > explains *all* of the slowdown. Hm, I was also thinking it would have to be something different. I added some print statements to a simple app (the pyDotView example that was posted recently): (first run) after importing objc: 0.330672979355 after importing Foundation: 0.997979998589 after importing AppKit: 3.49985897541 after importing MyAppDelegate: 3.72730898857 (starting the event loop) initializing DotView: 11.8096979856 (second run) after importing objc: 0.102402925491 after importing Foundation: 0.417948961258 after importing AppKit: 1.14622688293 after importing MyAppDelegate: 1.30699288845 (starting the event loop) initializing DotView: 8.59571492672 Times in seconds from the top of __main__. The "initializing" line is from the DotView.initWithFrame_() method. Much time is spent between starting the event loop and setting up the window. Weird. This was with 2.2, however, with 2.3 I get a different number at the end: (first run) after importing objc: 0.306917071342 after importing Foundation: 0.843237996101 after importing AppKit: 1.79104101658 after importing MyAppDelegate: 1.98914909363 (starting the event loop) initializing DotView: 3.40978002548 (second run) after importing objc: 0.118615984917 after importing Foundation: 0.377791047096 after importing AppKit: 1.09300804138 after importing MyAppDelegate: 1.22211098671 (starting the event loop) initializing DotView: 2.63563001156 Still very slow for a trivial app, but quite a bit better. But why? Just |
From: Bill B. <bb...@co...> - 2003-01-17 19:07:59
|
I just committed a bug fix that fixed a fairly nasty problem with the bridging of enumerators. That is, any dictionary or array enumerated via the 'in' operator would terminate the enumeration early if the array/dict contained an object/key that evaluated to Python False. That is: for x in [1,2,3,'',4]: print x Would only output: 1 2 3 Fixed; trivial fix. I also added a function to Foundation that converts a Foundation based collection of objects into a Python collection: pythonCollectionFromPropertyList() This mirrors propertyListFromPythonCollection(). It proves to be an incredibly convenient means of taking an NSDictionary and creating a fully mutable copy: dict = pythonCollectionFromPropertyList(NSDictionary.dictionaryWithContentsOfFi le_("MySavedData.plist") All of this was motivated by the creation of a tool to parse OmniWeb bookmarks and import the result into Safari: http://radio.weblogs.com/0100490/2003/01/17.html#a377 b.bum |
From: Just v. R. <ju...@le...> - 2003-01-15 22:13:17
|
I just noticed that my PythonBrowser application doesn't work correctly after all if I don't subclass PythonItem from NSObject. I was getting strange messages in the log if I tried to unpack certain items: 2003-01-15 21:48:37.838 python[13055] PythonItem instance has no attribute '__getitem__' but I was sure *I* didn't do any subscripting on PythonItem instances. It appears Cocoa is calling it (*), through PyObjC, and while trying to find what's wrong I came across this snippet in Modules/objc/objc_support.m: else if (PySequence_Check(argument)) *(id *) datum = [OC_PythonArray newWithPythonObject:argument]; PySequence_Check() is a lame check, it always returns true for simple instances. But since there's a PyDict_Check() below (which really checks isinstance(x, dict)), I think the following would be better/safer: else if (PyList_Check(argument) || PyTuple_Check(argument)) *(id *) datum = [OC_PythonArray newWithPythonObject:argument]; However, if I make that change, PythonBrowser doesn't run at all anymore: it crashes before any window is shown. So I'm pretty sure my Python objects are (wrongly) wrapped in an OC_PythonArray object, yet when they are wrapped in a OC_PythonObject (which would happen after my change) it stops working completely. *) I have no clue why NSOutlineView would do that: perhaps it tries to get at children by itself if the object is array-like, instead of going through outlineView:child:ofItem: ? The NSOutlineView and NSOutlineViewDataSource documentation don't seem to mention such magic. Just |
From: Bob I. <bo...@re...> - 2003-01-15 00:36:03
|
On Tuesday, Jan 14, 2003, at 19:24 America/New_York, Bill Bumgarner wrote: > On Tuesday, Jan 14, 2003, at 19:07 US/Eastern, Bob Ippolito wrote: >> a method for morphing a console app started with ANY command line >> into a Cocoa app, even if it's not in a bundle or has been running a >> while as a console app and Cocoa wasn't linked in at the time it >> started. > > Gave this some thought.... > > The trick is to do this before the ObjC runtime is touched in *any* > way. Even then, we may lose-- if the NSBundle/CFBundle has been > tripped by some other mechanism, we lose. > > So, dynamic loading works, but anything w/Foundation/Core linked in > may not work-- will not work in all cases. IIRC the undocumented CPSSetProcessName and CPSEnableForegroundOperation allowed me to get around that. Apple's jar runner uses this method, I saw that I was able to double-click a jar that wasn't in a bundle and it would still run and get representation in the dock.. so I tinkered around in gdb until I figured out how. > In any case, I really don't like hacks like this outside of the > 'ooh... that's a cool hacque' context. I'm bummed that it is now in > PyObjC, but it does work. I'm not necessarily advocating it either. I mostly wanted to know how Apple was doing it for Java... though it could be useful in certain circumstances [granted, all of them have workarounds, but it could mean time saved] for developers. |
From: Bill B. <bb...@co...> - 2003-01-15 00:24:20
|
On Tuesday, Jan 14, 2003, at 19:07 US/Eastern, Bob Ippolito wrote: > a method for morphing a console app started with ANY command line > into a Cocoa app, even if it's not in a bundle or has been running a > while as a console app and Cocoa wasn't linked in at the time it > started. Gave this some thought.... The trick is to do this before the ObjC runtime is touched in *any* way. Even then, we may lose-- if the NSBundle/CFBundle has been tripped by some other mechanism, we lose. So, dynamic loading works, but anything w/Foundation/Core linked in may not work-- will not work in all cases. Bummer. In any case, I really don't like hacks like this outside of the 'ooh... that's a cool hacque' context. I'm bummed that it is now in PyObjC, but it does work. b.bum |
From: Bill B. <bb...@co...> - 2003-01-15 00:08:33
|
I committed the Cocoa-Python Document-based Application template to the CVS repository. I also fixed the problem with untitled files ALWAYS opening after I fixed the problem with them NEVER opening; there is now an NSApplicationDelegate in AppKit's __init__.py. b.bum |
From: Bob I. <bo...@re...> - 2003-01-15 00:07:54
|
On Tuesday, Jan 14, 2003, at 16:07 America/New_York, Bill Bumgarner wrote: > 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. I didn't know you could set NSProcessInfo like that, I wish I had known that before.. I tried to do the equivalent once by doing some tricks with the end of the stack, but you can easily muck up environment variables and stuff that way if you don't do it just right. Knowing that it's possible this way, it should be relatively painless to engineer another nasty private thing -- a method for morphing a console app started with ANY command line into a Cocoa app, even if it's not in a bundle or has been running a while as a console app and Cocoa wasn't linked in at the time it started. Note that I haven't tried it since 10.1, but it worked then if you had started the app with full path, I imagine it still works now but I haven't tested it.. It also would've worked with any argv if I managed to figure out the nastiness of setting up argv/argc/environment/etc post-launch (I confirmed this experimentally by intentionally passing a large enough argv such that I could do the full-path thing).. From what it looks like, your NSProcessInfo hack *might* just do the trick. If someone gets it working well, it might be worthwhile to add it to pyobjc in some way.. i.e. from objc import evilcocoahack Obviously it's not of so much use for a released application since you likely have the convenience of doing the app bundle thing, but for development/experimentation it might be worthwhile. I actually had code similar to this run on import of a python module to make sure that you were a Cocoa app: // Linking to Cocoa is sufficient to bring these symbols in struct CPSProcessSerNum { UInt32 lo; UInt32 hi; }; typedef struct CPSProcessSerNum CPSProcessSerNum; extern OSErr CPSGetCurrentProcess( CPSProcessSerNum *psn); extern OSErr CPSSetProcessName ( CPSProcessSerNum *psn, char *processname); // I don't know which of these arguments are real and which aren't.. doesn't so much matter since it's // passed by register. I figured these out with gdb so I don't know how many arguments there // actually are extern OSErr CPSEnableForegroundOperation( CPSProcessSerNum *psn, UInt32 _arg2, UInt32 _arg3, UInt32 _arg4, UInt32 _arg5); extern OSErr CPSGetFrontProcess( CPSProcessSerNum *psn); // Note that this doesn't do anything bad (in my experience) if you're already a gui app void evilMorphIntoCocoaApp(void) { CPSProcessSerNum PSN; // XXX set NSProcessInfo properly [NSApplication sharedApplication]; if (!CPSGetCurrentProcess(&PSN)) // IIRC this fails if you're already a GUI app, so no harm done if (!CPSSetProcessName(&PSN,"yourProcessName")) if (!CPSEnableForegroundOperation(&PSN,0x03,0x3C,0x2C,0x1103)) if (!CPSSetFrontProcess(&PSN)) [NSApplication sharedApplication]; } |
From: Ronald O. <ous...@ci...> - 2003-01-14 22:32:38
|
On Tuesday, Jan 14, 2003, at 20:39 Europe/Amsterdam, bb...@ma... wrote: > 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() No, it is i.release(). the cls.alloc() returns an object where we own the reference, and then the bridge calls retain. We therefore have to call release to get the correct reference-count. I still think we can get this working >95% of the time, with the other <5% being methods that also return a new reference but that we don't know of. The current code to deal with this is slightly to simpleminded, but IMHO it is possible to correctly recognize an 'alloc + init' sequence and then adjust the reference count. The other documented cases of method returning a new reference can be processed by the current logic. The Apple Objective-C manual mentions about 5 methods that return new references, all others should return borrowed references. As Bill noted earlier real code doesn't always follow these conventions, but I think it would be sick to return a borrowed reference from an 'alloc + init' sequence. I hope to write down a design for this soonish, but I'd like to do some performance testing before that. > > ... 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. But als you note below not really feasable unless we'd use 'def __new__(cls): return cls.alloc()'. Hmm, I kind of like this, but we should document that you *must* call an init-method afterwards. The following objective-C code might crash: [[SomeClass alloc] release]. This does crash for some classes in Cocoa and according to Apple this is correct behaviour: Until you call an init method the instance is not instantiated and therefore any method-call might fail. > >>> 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). According to Apple these are not bugs, you should only call an init method on the reference returned by +alloc. Me thinks this is a sad situation :-(. > >>>> 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. If adding a __new__ method would cause __init__ to be called when the class is instantiated from Python, we should make sure that __init__ is also called when the class is instantiated from Objective-C, otherwise we'd get some very odd behaviour ('It works when I run my test script, but doesn't when I use it from Interface Builder'). Ronald |
From: Ronald O. <ous...@ci...> - 2003-01-14 22:15:21
|
On Tuesday, Jan 14, 2003, at 20:55 Europe/Amsterdam, bb...@ma... wrote: > 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... The alloc-hack stuff is for another bug/feature of Cocoa. Some classes don't like calls to +alloc through an NSInvocation. I've opened a bugreport for this with Apple, but so far without result. You have to be a bit carefull: call alloc, some variation of init and then adjust the reference count. Doing it in another order will cause problems some times, mostly when using class clusters. Ronald |