Thread: [Pyobjc-dev] [ pyobjc-Bugs-836247 ] NSWindow.contentRectForFrameRect_styleMask_ not a class meth
Brought to you by:
ronaldoussoren
From: SourceForge.net <no...@so...> - 2003-11-05 03:56:58
|
Bugs item #836247, was opened at 2003-11-05 03:56 Message generated for change (Tracker Item Submitted) made by Item Submitter You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=114534&aid=836247&group_id=14534 Category: None Group: None Status: Open Resolution: None Priority: 5 Submitted By: Zachery Bir (zbir) Assigned to: Nobody/Anonymous (nobody) Summary: NSWindow.contentRectForFrameRect_styleMask_ not a class meth Initial Comment: Trying the following snippet of code: def showPrefPane(self, pane, sender): windowFrame = NSWindow.contentRectForFrameRect_styleMask_( NSWindow, self.window().frame(), self.window().styleMask()) newWindowHeight = NSHeight(pane.frame()) if self.window().toolbar().isVisible(): newWindowHeight += NSHeight( self.window().toolbar()._toolbarView().frame()) newWindowFrame = NSWindow.frameRectForContentRect_styleMask_( NSWindow, NSMakeRect(NSMinX(windowFrame), NSMaxY(windowFrame) - newWindowHeight, NSWidth(windowFrame), newWindowHeight), self.window().styleMask()) self.window().setContentView_(pane) self.window().setFrame_display_animate_(newWindowFra me, YES, self.window().isVisible()) ********** Host: gorilla.urbanape.com Date/Time: 2003-11-04 22:52:17 -0500 OS Version: 10.3 (Build 7B85) Command: python (/Users/zbir/Applications/ ZopeEditManager.app/Contents/MacOS/python) PID: 613 Thread: 0 Exception: EXC_BAD_ACCESS (0x0001) Codes: KERN_PROTECTION_FAILURE (0x0002) at 0x0000000c Thread 0 Crashed: #0 0x90831388 in objc_msgSend_stret (objc_msgSend_stret + 8) #1 0x92dcff08 in -[NSWindow contentRectForFrameRect: styleMask:] (-[NSWindow contentRectForFrameRect: styleMask:] + 160) #2 0x00428974 in ffi_call_DARWIN (ffi_call_DARWIN + 208) #3 0x00428368 in ffi_call (ffi_darwin.c:401) #4 0x00426f08 in ObjC_FFICaller (libffi_support.m:1088) #5 0x0041a12c in objcsel_call (selector.m:594) #6 0x95f4a8d0 in PyObject_Call (PyObject_Call + 48) #7 0x95fa9ba8 in PyEval_GetFuncDesc (PyEval_GetFuncDesc + 2268) #8 0x95fa9598 in PyEval_GetFuncDesc (PyEval_GetFuncDesc + 716) #9 0x95fa6c64 in PyEval_EvalCode (PyEval_EvalCode + 9568) #10 0x95fa7e30 in PyEval_EvalCodeEx (PyEval_EvalCodeEx + 2128) #11 0x95f5f354 in PyFunction_SetClosure (PyFunction_SetClosure + 3436) #12 0x95f4a8d0 in PyObject_Call (PyObject_Call + 48) #13 0x0041b13c in pysel_call (selector.m:997) #14 0x95f4a8d0 in PyObject_Call (PyObject_Call + 48) #15 0x95fa9ba8 in PyEval_GetFuncDesc (PyEval_GetFuncDesc + 2268) #16 0x95fa9598 in PyEval_GetFuncDesc (PyEval_GetFuncDesc + 716) #17 0x95fa6c64 in PyEval_EvalCode (PyEval_EvalCode + 9568) #18 0x95fa7e30 in PyEval_EvalCodeEx (PyEval_EvalCodeEx + 2128) #19 0x95f5f354 in PyFunction_SetClosure (PyFunction_SetClosure + 3436) #20 0x95f4a8d0 in PyObject_Call (PyObject_Call + 48) #21 0x0041b13c in pysel_call (selector.m:997) #22 0x95f4a8d0 in PyObject_Call (PyObject_Call + 48) #23 0x95fa9ba8 in PyEval_GetFuncDesc (PyEval_GetFuncDesc + 2268) #24 0x95fa9598 in PyEval_GetFuncDesc (PyEval_GetFuncDesc + 716) #25 0x95fa6c64 in PyEval_EvalCode (PyEval_EvalCode + 9568) #26 0x95fa7e30 in PyEval_EvalCodeEx (PyEval_EvalCodeEx + 2128) #27 0x95f5f354 in PyFunction_SetClosure (PyFunction_SetClosure + 3436) #28 0x95f4a8d0 in PyObject_Call (PyObject_Call + 48) #29 0x0041b024 in pysel_call (selector.m:979) #30 0x95f4a8d0 in PyObject_Call (PyObject_Call + 48) #31 0x004104ac in PyObjC_CallPython (class-builder.m: 1410) #32 0x0042524c in method_stub (libffi_support.m:416) #33 0x004286ac in ffi_closure_helper_DARWIN (ffi_darwin.c:699) #34 0x00428a44 in ffi_closure_ASM (ffi_closure_ASM + 116) #35 0x92df240c in -[NSIBObjectData nibInstantiateWithOwner:topLevelObjects:] (- [NSIBObjectData nibInstantiateWithOwner: topLevelObjects:] + 920) #36 0x92ee3ab4 in loadNib (loadNib + 252) #37 0x92e3ae64 in +[NSBundle(NSNibLoading) _loadNibFile:nameTable:withZone:ownerBundle:] (+[NSBundle(NSNibLoading) _loadNibFile:nameTable: withZone:ownerBundle:] + 744) #38 0x92eb9b58 in +[NSBundle(NSNibLoading) loadNibFile:externalNameTable:withZone:] (+[NSBundle(NSNibLoading) loadNibFile: externalNameTable:withZone:] + 156) #39 0x92ec095c in -[NSWindowController loadWindow] (- [NSWindowController loadWindow] + 204) #40 0x92e75128 in -[NSWindowController window] (- [NSWindowController window] + 92) #41 0x92f31adc in -[NSWindowController showWindow:] (-[NSWindowController showWindow:] + 36) #42 0x00428974 in ffi_call_DARWIN (ffi_call_DARWIN + 208) #43 0x00428368 in ffi_call (ffi_darwin.c:401) #44 0x00426f2c in ObjC_FFICaller (libffi_support.m: 1097) #45 0x0041a010 in objcsel_call (selector.m:575) #46 0x95f4a8d0 in PyObject_Call (PyObject_Call + 48) #47 0x95fa9ba8 in PyEval_GetFuncDesc (PyEval_GetFuncDesc + 2268) #48 0x95fa9598 in PyEval_GetFuncDesc (PyEval_GetFuncDesc + 716) #49 0x95fa6c64 in PyEval_EvalCode (PyEval_EvalCode + 9568) #50 0x95fa7e30 in PyEval_EvalCodeEx (PyEval_EvalCodeEx + 2128) #51 0x95f5f354 in PyFunction_SetClosure (PyFunction_SetClosure + 3436) #52 0x95f4a8d0 in PyObject_Call (PyObject_Call + 48) #53 0x0041b024 in pysel_call (selector.m:979) #54 0x95f4a8d0 in PyObject_Call (PyObject_Call + 48) #55 0x004104ac in PyObjC_CallPython (class-builder.m: 1410) #56 0x0042524c in method_stub (libffi_support.m:416) #57 0x004286ac in ffi_closure_helper_DARWIN (ffi_darwin.c:699) #58 0x00428a44 in ffi_closure_ASM (ffi_closure_ASM + 116) #59 0x92e779d0 in -[NSApplication sendAction:to:from:] (-[NSApplication sendAction:to:from:] + 108) #60 0x92ead1bc in -[NSMenu performActionForItemAtIndex:] (-[NSMenu performActionForItemAtIndex:] + 392) #61 0x92ef1ac4 in -[NSCarbonMenuImpl performActionWithHighlightingForItemAtIndex:] (- [NSCarbonMenuImpl performActionWithHighlightingForItemAtIndex:] + 104) #62 0x92ef83f4 in -[NSMenu performKeyEquivalent:] (- [NSMenu performKeyEquivalent:] + 260) #63 0x92ed7420 in -[NSApplication _handleKeyEquivalent:] (-[NSApplication _handleKeyEquivalent:] + 292) #64 0x92df4eec in -[NSApplication sendEvent:] (- [NSApplication sendEvent:] + 2652) #65 0x92dfd754 in -[NSApplication run] (-[NSApplication run] + 576) #66 0x92eb9a1c in NSApplicationMain (NSApplicationMain + 464) #67 0x006beda8 in objc_NSApplicationMain (_AppKit.m: 116) #68 0x95fa94a8 in PyEval_GetFuncDesc (PyEval_GetFuncDesc + 476) #69 0x95fa6c64 in PyEval_EvalCode (PyEval_EvalCode + 9568) #70 0x95fa7e30 in PyEval_EvalCodeEx (PyEval_EvalCodeEx + 2128) #71 0x95fa97dc in PyEval_GetFuncDesc (PyEval_GetFuncDesc + 1296) #72 0x95fa9580 in PyEval_GetFuncDesc (PyEval_GetFuncDesc + 692) #73 0x95fa6c64 in PyEval_EvalCode (PyEval_EvalCode + 9568) #74 0x95fa7e30 in PyEval_EvalCodeEx (PyEval_EvalCodeEx + 2128) #75 0x95fa4734 in PyEval_EvalCode (PyEval_EvalCode + 48) #76 0x95fc85f0 in PyRun_FileExFlags (PyRun_FileExFlags + 228) #77 0x95fc7668 in PyRun_SimpleFileExFlags (PyRun_SimpleFileExFlags + 444) #78 0x95fd1ec0 in Py_Main (Py_Main + 1996) #79 0x00003c78 in start (start + 444) #80 0x00003aec in start (start + 48) PPC Thread State: srr0: 0x90831388 srr1: 0x0200f030 vrsave: 0x00000000 cr: 0x40224242 xer: 0x20000004 lr: 0x92dcff08 ctr: 0x90831380 r0: 0x92dcff08 r1: 0xbfffa150 r2: 0xa2dc1535 r3: 0xbfffa190 r4: 0x0000000c r5: 0x9086ee4c r6: 0x42200000 r7: 0x443cc000 r8: 0x43c80000 r9: 0x42a60000 r10: 0x00000003 r11: 0xa2dc1fb4 r12: 0x90831380 r13: 0x0123d060 r14: 0x00000000 r15: 0x00791558 r16: 0x00000000 r17: 0x00000000 r18: 0x00000000 r19: 0x00000000 r20: 0x00000000 r21: 0x003054c0 r22: 0x00000003 r23: 0x0037412e r24: 0xbfffaf2c r25: 0x00366f84 r26: 0x00000000 r27: 0x01148920 r28: 0x00000003 r29: 0xa2dfce3c r30: 0xbfffa1e4 r31: 0x92dcfe68 ---------------------------------------------------------------------- You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=114534&aid=836247&group_id=14534 |
Re: [Pyobjc-dev] [ pyobjc-Bugs-836247 ] NSWindow.contentRectForFrameRect_styleMask_ not a class meth
From: Bob I. <bo...@re...> - 2003-11-05 08:24:15
|
On Nov 4, 2003, at 10:56 PM, SourceForge.net wrote: > Bugs item #836247, was opened at 2003-11-05 03:56 > Message generated for change (Tracker Item Submitted) made by Item > Submitter > You can respond by visiting: > https://sourceforge.net/tracker/? > func=detail&atid=114534&aid=836247&group_id=14534 This bug exposes a fairly obnoxious problem in the current implementation of PyObjC: there are not separate namespaces for class and instance methods, so you end up with stupid problems when you have some class that implements the same selector for both the instance and class. There's a lot of pretty common selectors that are like this: +[NSObject description] -[NSObject description] .. etc .. I did discover a workaround, which is ClassObject.bothClassAndInstanceMethod(ClassObject).. for example: >>> NSObject.description(NSObject) u'<NSObject: 0xa0a04e40>' Ideally one would be able to do NSObject.description().. which means that the descriptor has to know about these "class or instance" methods. It's also, as far as I know, not possible to override the class implementation for a selector if an instance implementation exists (from Python). So my question is, how the heck do we approach this? It seems that the current selector objects/descriptors need to be changed quite a bit in order to facilitate this, especially allowing one to do it from Python. Perhaps we can change the selector function to take a class function, instance function, or both.. and throw away isClassMethod. We can add a flag on the selector that says "I have both a class and an instance". I'm pretty new to these internals.. so, Ronald, do you want to handle this one? Or give me some ideas as to how this should be done? -bob |
Re: [Pyobjc-dev] [ pyobjc-Bugs-836247 ] NSWindow.contentRectForFrameRect_styleMask_ not a class meth
From: Bob I. <bo...@re...> - 2003-11-05 09:42:29
|
On Nov 5, 2003, at 3:23 AM, Bob Ippolito wrote: > On Nov 4, 2003, at 10:56 PM, SourceForge.net wrote: > >> Bugs item #836247, was opened at 2003-11-05 03:56 >> Message generated for change (Tracker Item Submitted) made by Item >> Submitter >> You can respond by visiting: >> https://sourceforge.net/tracker/? >> func=detail&atid=114534&aid=836247&group_id=14534 > > This bug exposes a fairly obnoxious problem in the current > implementation of PyObjC: there are not separate namespaces for class > and instance methods, so you end up with stupid problems when you have > some class that implements the same selector for both the instance and > class. There's a lot of pretty common selectors that are like this: > +[NSObject description] > -[NSObject description] > .. etc .. > > I did discover a workaround, which is > ClassObject.bothClassAndInstanceMethod(ClassObject).. for example: > >>> NSObject.description(NSObject) > u'<NSObject: 0xa0a04e40>' > > Ideally one would be able to do NSObject.description().. which means > that the descriptor has to know about these "class or instance" > methods. It's also, as far as I know, not possible to override the > class implementation for a selector if an instance implementation > exists (from Python). > > So my question is, how the heck do we approach this? It seems that > the current selector objects/descriptors need to be changed quite a > bit in order to facilitate this, especially allowing one to do it from > Python. Perhaps we can change the selector function to take a class > function, instance function, or both.. and throw away isClassMethod. > We can add a flag on the selector that says "I have both a class and > an instance". I'm pretty new to these internals.. so, Ronald, do you > want to handle this one? Or give me some ideas as to how this should > be done? Ok, I was totally wrong about that workaround.. Anyhow: >>> NSObject.pyobjc_classMethods.description() u'NSObject' >>> NSObject.alloc().init().pyobjc_instanceMethods.description() u'<NSObject: 0x3a3c60>' That is the real workaround.. fixed tests checked in. -bob |
Re: [Pyobjc-dev] [ pyobjc-Bugs-836247 ] NSWindow.contentRectForFrameRect_styleMask_ not a class meth
From: Ronald O. <ous...@ci...> - 2003-11-05 10:00:16
|
Managment summary: use 'NSWindow.pyobjc_classMethods.contentRectForFrameRect_styleMask_' to call the class method. On 5 nov 2003, at 9:23, Bob Ippolito wrote: > On Nov 4, 2003, at 10:56 PM, SourceForge.net wrote: > >> Bugs item #836247, was opened at 2003-11-05 03:56 >> Message generated for change (Tracker Item Submitted) made by Item >> Submitter >> You can respond by visiting: >> https://sourceforge.net/tracker/? >> func=detail&atid=114534&aid=836247&group_id=14534 > > This bug exposes a fairly obnoxious problem in the current > implementation of PyObjC: there are not separate namespaces for class > and instance methods, so you end up with stupid problems when you have > some class that implements the same selector for both the instance and > class. There's a lot of pretty common selectors that are like this: > +[NSObject description] > -[NSObject description] > .. etc .. I noticed. It is already possible to call both methods, although not necessarily in a very convenient way: NSObject.foo() # Instancemethod, or if that does not exist classmethod NSObject.pyobjc_classMethods.foo() # Classmethod NSObject.pyobjc_instanceMethods.foo() # Instancemethod At the time we ran into this issue I couldn't find any methods where it would be usefull to override the class method, it is therefore not possible to override the class method at the moment. > > I did discover a workaround, which is > ClassObject.bothClassAndInstanceMethod(ClassObject).. for example: > >>> NSObject.description(NSObject) > u'<NSObject: 0xa0a04e40>' That's more a bug than a feature... > > Ideally one would be able to do NSObject.description().. which means > that the descriptor has to know about these "class or instance" > methods. It's also, as far as I know, not possible to override the > class implementation for a selector if an instance implementation > exists (from Python). Note that it is currently not possible to know of 'NSObject.description' refers to the class or instance method due to the way types are implemented in Python: obj.description() is basically implemented as: obj.__class__.description(obj) And furthermore Cocoa classes should 'feel' as much as Python classes as possible, it should therefore be possible to call 'NSObject.description(obj)'. > > So my question is, how the heck do we approach this? It seems that > the current selector objects/descriptors need to be changed quite a > bit in order to facilitate this, especially allowing one to do it from > Python. Perhaps we can change the selector function to take a class > function, instance function, or both.. and throw away isClassMethod. > We can add a flag on the selector that says "I have both a class and > an instance". I'm pretty new to these internals.. so, Ronald, do you > want to handle this one? Or give me some ideas as to how this should > be done? Is it necessary to be able to override class methods? My gut feeling is that it would be easy-ish to change objc.selector() to allow something like this: class FooClass (NSObject): def _cls_description(cls): return "FooClass class" def _inst_description(self): return "FooClass instance" description = objc.selector(selector="description", clsImp=_cls_description, instImp=_inst_description) del _cls_description, _inst_description This is pretty ugly, but at least would make it possible to override both the class and instance method without introducing an additional class. However, I don't think this is worth the effort unless someone has a real use case. Ronald |
Re: [Pyobjc-dev] [ pyobjc-Bugs-836247 ] NSWindow.contentRectForFrameRect_styleMask_ not a class meth
From: Bob I. <bo...@re...> - 2003-11-05 11:25:29
|
On Nov 5, 2003, at 5:00 AM, Ronald Oussoren wrote: > Ideally one would be able to do NSObject.description().. which means > that the descriptor has to know about these "class or instance" > methods. It's also, as far as I know, not possible to override the > class implementation for a selector if an instance implementation > exists (from Python). > > Note that it is currently not possible to know of > 'NSObject.description' refers to the class or instance method due to > the way types are implemented in Python: > > obj.description() > > is basically implemented as: > > obj.__class__.description(obj) > > And furthermore Cocoa classes should 'feel' as much as Python classes > as possible, it should therefore be possible to call > 'NSObject.description(obj)'. Well the current semantics for instance method only and class method only are perfectly fine.. it's the occasions when a particular selector is implemented both ways where things start to get hairy. I'd rather have NSObject.description(obj) not work, if it meant that NSObject.description() did work. Even still, I think enough information is available to make it possible. What about something like this (sorta pseudocode, not in tp_descr_get C API). METH_CLASS = 1 << 0 METH_INST = 1 << 1 class Selector(object): EXPECTED_ARG_LEN = 0 def __init__(self, name, flags, boundklass=None, boundinst=None): self.name = name self.flags = flags self.boundklass = boundklass self.boundinst = boundinst def __get__(self, inst, klass): if inst is None: return Selector(self.name, self.flags, boundklass=klass) elif not (self.flags & METH_INST): # trying to get a pure class method from an instance, don't do that raise AttributeError, "%s is a class method" % (self.name,) # it's been acquired from an instance return Selector(self.name, self.flags, boundinst=inst, boundklass=klass) def __call__(self, *args): if self.boundklass is None and self.boundinst is None: raise ValueError, "Selector not initialized" elif self.boundinst is not None: # acquired from an instance.. return execute(self.boundinst, args) elif self.flags & METH_INST and len(args) > self.EXPECTED_ARG_LEN: # must be using class.instanceMethod(instance, ....) # so what if this breaks down on varargs? how are varargs wrapped anyway (if at all)? # those people can use a workaround or just not use klass.instanceMethod(instance, ...) return execute(args[0], args[1:]) else: return execute(self.boundklass, args) |
Re: [Pyobjc-dev] [ pyobjc-Bugs-836247 ] NSWindow.contentRectForFrameRect_styleMask_ not a class meth
From: Bob I. <bo...@re...> - 2003-11-05 16:32:16
|
On Nov 5, 2003, at 5:00 AM, Ronald Oussoren wrote: > NSObject.foo() # Instancemethod, or if that does not exist > classmethod > NSObject.pyobjc_classMethods.foo() # Classmethod > NSObject.pyobjc_instanceMethods.foo() # Instancemethod Another idea - how about putting that on the selector instead? NSObject.foo() # smart decision by the selector (smarter than instance if it has one, see previous email) NSObject.foo.classMethod() # classmethod NSObject.foo.instanceMethod() # instanceMethod -bob |
Re: [Pyobjc-dev] [ pyobjc-Bugs-836247 ] NSWindow.contentRectForFrameRect_styleMask_ not a class meth
From: Jack J. <Jac...@cw...> - 2003-11-05 22:24:30
|
On 5-nov-03, at 17:26, Bob Ippolito wrote: > > On Nov 5, 2003, at 5:00 AM, Ronald Oussoren wrote: > >> NSObject.foo() # Instancemethod, or if that does not exist >> classmethod >> NSObject.pyobjc_classMethods.foo() # Classmethod >> NSObject.pyobjc_instanceMethods.foo() # Instancemethod > > Another idea - how about putting that on the selector instead? > > NSObject.foo() # smart decision by the selector (smarter than > instance if it has one, see previous email) > NSObject.foo.classMethod() # classmethod > NSObject.foo.instanceMethod() # instanceMethod That would make "NSObject.foo" a funny sort of object. In the current scheme NSObject.foo is a perfectly normal object, either an unbound method or a class method. -- Jack Jansen, <Jac...@cw...>, http://www.cwi.nl/~jack If I can't dance I don't want to be part of your revolution -- Emma Goldman |
Re: [Pyobjc-dev] [ pyobjc-Bugs-836247 ] NSWindow.contentRectForFrameRect_styleMask_ not a class meth
From: Bob I. <bo...@re...> - 2003-11-05 22:44:27
|
On Nov 5, 2003, at 5:24 PM, Jack Jansen wrote: > On 5-nov-03, at 17:26, Bob Ippolito wrote: > >> >> On Nov 5, 2003, at 5:00 AM, Ronald Oussoren wrote: >> >>> NSObject.foo() # Instancemethod, or if that does not exist >>> classmethod >>> NSObject.pyobjc_classMethods.foo() # Classmethod >>> NSObject.pyobjc_instanceMethods.foo() # Instancemethod >> >> Another idea - how about putting that on the selector instead? >> >> NSObject.foo() # smart decision by the selector (smarter than >> instance if it has one, see previous email) >> NSObject.foo.classMethod() # classmethod >> NSObject.foo.instanceMethod() # instanceMethod > > That would make "NSObject.foo" a funny sort of object. In the current > scheme NSObject.foo is a perfectly normal object, either an unbound > method or a class method. Except that it has a signature, isClassMethod, etc. It's not a perfectly normal object, it's a selector instance. One of the big "selling points" of ObjC is that you can pretty much translate ObjC code to Python, this is a stumbling block I think we should work around. With the "algorithm" I posted earlier, using these special "classMethod / instanceMethod" accessors should never really be necessary, except in rare instances where you are doing SomeClass.someInstanceMethod(instance, ...) with varargs or something. -bob |
Re: [Pyobjc-dev] [ pyobjc-Bugs-836247 ] NSWindow.contentRectForFrameRect_styleMask_ not a class meth
From: Jack J. <Jac...@cw...> - 2003-11-07 11:35:31
|
On 5 Nov 2003, at 23:44, Bob Ippolito wrote: >>> NSObject.foo() # smart decision by the selector (smarter than >>> instance if it has one, see previous email) >>> NSObject.foo.classMethod() # classmethod >>> NSObject.foo.instanceMethod() # instanceMethod >> >> That would make "NSObject.foo" a funny sort of object. In the current >> scheme NSObject.foo is a perfectly normal object, either an unbound >> method or a class method. > > Except that it has a signature, isClassMethod, etc. It's not a > perfectly normal object, it's a selector instance. One of the big > "selling points" of ObjC is that you can pretty much translate ObjC > code to Python, this is a stumbling block I think we should work > around. Hmm, you have a point. If I look at this then sometimes I agree with you, sometimes I agree with myself. It really depends on whether you take a Pythonic view or on ObjC-view. -- Jack Jansen <Jac...@cw...> http://www.cwi.nl/~jack If I can't dance I don't want to be part of your revolution -- Emma Goldman |
Re: [Pyobjc-dev] [ pyobjc-Bugs-836247 ] NSWindow.contentRectForFrameRect_styleMask_ not a class meth
From: Bob I. <bo...@re...> - 2003-11-07 15:01:25
|
On Nov 7, 2003, at 6:34 AM, Jack Jansen wrote: > > On 5 Nov 2003, at 23:44, Bob Ippolito wrote: >>>> NSObject.foo() # smart decision by the selector (smarter than >>>> instance if it has one, see previous email) >>>> NSObject.foo.classMethod() # classmethod >>>> NSObject.foo.instanceMethod() # instanceMethod >>> >>> That would make "NSObject.foo" a funny sort of object. In the >>> current scheme NSObject.foo is a perfectly normal object, either an >>> unbound method or a class method. >> >> Except that it has a signature, isClassMethod, etc. It's not a >> perfectly normal object, it's a selector instance. One of the big >> "selling points" of ObjC is that you can pretty much translate ObjC >> code to Python, this is a stumbling block I think we should work >> around. > > Hmm, you have a point. If I look at this then sometimes I agree with > you, sometimes I agree with myself. It really depends on whether you > take a Pythonic view or on ObjC-view. Well the way I see it is this. Making selectors more magical will make ObjC code work more often without "change". The only thing that *might* break is doing SomeClass.someInstanceSelector(someInstance, ...) -- but people only really do that if someInstance is a string or something weird is going on with PyObjC.. I really don't think this change would cause any problems, and I don't think that the classMethod/instanceMethod members would ever really need to be used, but would be there as a backup plan in case for some reason PyObjC guessed wrong and you really want to use a instance method that was taken off the class. classMethod is only there for symmetry, it would never be necessary. -bob |
Re: [Pyobjc-dev] [ pyobjc-Bugs-836247 ] NSWindow.contentRectForFrameRect_styleMask_ not a class meth
From: b.bum <bb...@ma...> - 2003-11-07 16:03:20
Attachments:
smime.p7s
|
Unless I'm missing something, can't we always tell at the moment of dispatch whether or not a particular method should be resolved in the class or instance context? When objc_msgSend() is invoked, the SEL parameter is resolved internally based on the 'self' parameter -- on the target of invocation. So, once we have an object reference and a selector, our bridged dispatch to the method IMP should "just work" regardless of whether it is a class or instance. The only place that class vs. instance method is problematic would appear to be within the Python subclasses of ObjC objects where there is a need to define both a class and an instance method. I.e. +description vs. -description. Given that +description requires, effectively, a redeclaration through the use of selector(), we could change the name of the method slightly-- and invisibly-- at that time. But that is ugly. Instead, can we handle this at the time of dispatch? I.e. if you do Foo.description to grab a reference to the description method of the Foo class-- which has both +description and -description-- then we should be able to figure out if the class or instance implementation should be invoked at the time of dispatch based on what the target of the invocation is. There are other details that would have to be worked out. But, for the most part, it would seem that this could be done in a largely automatic and transparent fashion. The remaining unknowns are largely arbitrary in nature because they only occur due to the combined interaction of the ObjC and Python runtimes -- we are free to do whatever we want. b.bum |
Re: [Pyobjc-dev] [ pyobjc-Bugs-836247 ] NSWindow.contentRectForFrameRect_styleMask_ not a class meth
From: Bob I. <bo...@re...> - 2003-11-07 16:21:00
|
On Nov 7, 2003, at 10:53 AM, b.bum wrote: > Unless I'm missing something, can't we always tell at the moment of > dispatch whether or not a particular method should be resolved in the > class or instance context? > > When objc_msgSend() is invoked, the SEL parameter is resolved > internally based on the 'self' parameter -- on the target of > invocation. So, once we have an object reference and a selector, our > bridged dispatch to the method IMP should "just work" regardless of > whether it is a class or instance. > > The only place that class vs. instance method is problematic would > appear to be within the Python subclasses of ObjC objects where there > is a need to define both a class and an instance method. I.e. > +description vs. -description. No, it also happens when you are just using ObjC classes from the Python side of the bridge. It *always* binds to the instance method, nomatter what, if it has one. I'm not even worried about overriding them from Python at the moment, just making ObjC classes usable as they should be. > Given that +description requires, effectively, a redeclaration through > the use of selector(), we could change the name of the method > slightly-- and invisibly-- at that time. > > But that is ugly. > > Instead, can we handle this at the time of dispatch? Sure, that's what I'm asking for :) > I.e. if you do Foo.description to grab a reference to the description > method of the Foo class-- which has both +description and > -description-- then we should be able to figure out if the class or > instance implementation should be invoked at the time of dispatch > based on what the target of the invocation is. > > There are other details that would have to be worked out. But, for > the most part, it would seem that this could be done in a largely > automatic and transparent fashion. The remaining unknowns are > largely arbitrary in nature because they only occur due to the > combined interaction of the ObjC and Python runtimes -- we are free to > do whatever we want. That's what I was proposing, however there is some ambiguity in determining the target of the invocation if and only if we allow SomeClass.instanceMethod(someInstance) -- but I proposed a way that would figure that out most of the time, by counting the number of arguments given if that selector exists for both the class and the instance, which should work in every case that doesn't use varargs (do any?). -bob |
Re: [Pyobjc-dev] [ pyobjc-Bugs-836247 ] NSWindow.contentRectForFrameRect_styleMask_ not a class meth
From: b.bum <bb...@ma...> - 2003-11-07 17:45:22
Attachments:
smime.p7s
|
On Nov 7, 2003, at 8:20 AM, Bob Ippolito wrote: > No, it also happens when you are just using ObjC classes from the > Python side of the bridge. It *always* binds to the instance method, > nomatter what, if it has one. I'm not even worried about overriding > them from Python at the moment, just making ObjC classes usable as > they should be. Right -- and that is a bug. "Binding" shouldn't occur until invocation except in the case where the developer has explicitly invoked method via the unbound method mechanism where they previously obtained a reference to the instance or class version of a method. I.e. if I have... id foo; foo = ... something ...; [foo performSelector: @selector(description)]; ... then the class or instance version of description will be invoked depending on if foo is a class or instance object. >> I.e. if you do Foo.description to grab a reference to the description >> method of the Foo class-- which has both +description and >> -description-- then we should be able to figure out if the class or >> instance implementation should be invoked at the time of dispatch >> based on what the target of the invocation is. >> >> There are other details that would have to be worked out. But, for >> the most part, it would seem that this could be done in a largely >> automatic and transparent fashion. The remaining unknowns are >> largely arbitrary in nature because they only occur due to the >> combined interaction of the ObjC and Python runtimes -- we are free >> to do whatever we want. > > That's what I was proposing, however there is some ambiguity in > determining the target of the invocation if and only if we allow > SomeClass.instanceMethod(someInstance) -- but I proposed a way that > would figure that out most of the time, by counting the number of > arguments given if that selector exists for both the class and the > instance, which should work in every case that doesn't use varargs (do > any?). If someInstance is an instance method, then the instance implementation should be used... if it is a class method, then use the class implementation. This most closely mimics the ObjC runtime. If the developer specifically wants the class vs. instance version of the method, then we should add API for querying for the one versus the other. The API already exists on NSObject. b.bum |
Re: [Pyobjc-dev] [ pyobjc-Bugs-836247 ] NSWindow.contentRectForFrameRect_styleMask_ not a class meth
From: Bob I. <bo...@re...> - 2003-11-07 18:17:06
|
On Nov 7, 2003, at 12:45 PM, b.bum wrote: > On Nov 7, 2003, at 8:20 AM, Bob Ippolito wrote: >> No, it also happens when you are just using ObjC classes from the >> Python side of the bridge. It *always* binds to the instance method, >> nomatter what, if it has one. I'm not even worried about overriding >> them from Python at the moment, just making ObjC classes usable as >> they should be. > > Right -- and that is a bug. > > "Binding" shouldn't occur until invocation except in the case where > the developer has explicitly invoked method via the unbound method > mechanism where they previously obtained a reference to the instance > or class version of a method. > > I.e. if I have... > > id foo; > > foo = ... something ...; > [foo performSelector: @selector(description)]; > > ... then the class or instance version of description will be invoked > depending on if foo is a class or instance object. That's exactly what should happen, but that's not exactly how Python works.. Basically, selectors are descriptor instances. When you get the selector-instance-turned-descriptor from the class or instance it calls __get__(self, fromInstanceOrNone, fromClass) on the selector instance (tp_descr_get from the C API). So, the selector instance needs to remember the values of fromInstanceOrNone and fromClass and return an object (perhaps itself, but maybe not) that's suitable to be introspected or called. So, when you dispatch this object, you know if it was taken from the class or an instance (b/c fromInstanceOrNone would be None if it was taken from the class). In the current PyObjC, at this point it has already decided if it's going to use a class or instance method. Before dispatch happens. If you read back a couple posts I had a mock-Python Selector class that shows how I would like the rules of the selector descriptor game to work, which should fix this bug. The thing that I think you're confused about is that it's not clearly obvious what the target of the dispatch is.. obviously if the descriptor was taken from an instance, you know you want to use the instance version. It gets more complicated if you want to make these things act more like Python objects, where you're allowed to do call instance methods off of the class directly.. see my next paragraph. >>> I.e. if you do Foo.description to grab a reference to the >>> description method of the Foo class-- which has both +description >>> and -description-- then we should be able to figure out if the class >>> or instance implementation should be invoked at the time of dispatch >>> based on what the target of the invocation is. >>> >>> There are other details that would have to be worked out. But, for >>> the most part, it would seem that this could be done in a largely >>> automatic and transparent fashion. The remaining unknowns are >>> largely arbitrary in nature because they only occur due to the >>> combined interaction of the ObjC and Python runtimes -- we are free >>> to do whatever we want. >> >> That's what I was proposing, however there is some ambiguity in >> determining the target of the invocation if and only if we allow >> SomeClass.instanceMethod(someInstance) -- but I proposed a way that >> would figure that out most of the time, by counting the number of >> arguments given if that selector exists for both the class and the >> instance, which should work in every case that doesn't use varargs >> (do any?). > > If someInstance is an instance method, then the instance > implementation should be used... if it is a class method, then use the > class implementation. This most closely mimics the ObjC runtime. I should have said SomeClass.bothInstanceAndClassMethod(someInstance) -- doing this method-from-class-using-instance-as-argument thing creates a somewhat ambiguous case. Without *counting* the number of arguments, you can't be sure whether you meant to call the instance version or the class version. My suggested behavior breaks down when the number of arguments can not be reliably counted (varags). I don't know if this actually happens or not with the bridge, and even if it did I would imagine that it would be extremely rare to find an ObjC class that implements the same varargs selector for class and instance. > If the developer specifically wants the class vs. instance version of > the method, then we should add API for querying for the one versus the > other. The API already exists on NSObject. It's currently possible but ugly and unintuitive (I didn't even know about it, after looking at PyObjC's source code for hours). My suggestion was to use: SomeClass.bothInstanceAndClassMethod.instanceMethod(...) instead of: SomeClass.pyobjc_instanceMethods.bothInstanceAndClassMethod(...) (note that this would *never* be needed if my proposed semantics were implemented, *except* in the degenerate varargs case, if that case can even exist). -bob |
Re: [Pyobjc-dev] [ pyobjc-Bugs-836247 ] NSWindow.contentRectForFrameRect_styleMask_ not a class meth
From: Jack J. <Jac...@cw...> - 2003-11-08 23:30:29
|
On 7-nov-03, at 18:45, b.bum wrote: > On Nov 7, 2003, at 8:20 AM, Bob Ippolito wrote: >> No, it also happens when you are just using ObjC classes from the >> Python side of the bridge. It *always* binds to the instance method, >> nomatter what, if it has one. I'm not even worried about overriding >> them from Python at the moment, just making ObjC classes usable as >> they should be. > > Right -- and that is a bug. This hits the two-faced issue on the head: it's a bug if you look at this with ObjC in mind, it's an essential shortcoming if you look at it with Python in mind. Bob said (at some point in the past of this discussion) something to the effect that someclass.somemehod is a selector. If you view it from that angle then the current behavior is a bug. My initial thought (with my Python hat on) was that someclass.somemethod is either a class method or an unbounded instance method. Then this isn't a bug but a shortcoming that can't be overcome. -- Jack Jansen, <Jac...@cw...>, http://www.cwi.nl/~jack If I can't dance I don't want to be part of your revolution -- Emma Goldman |
Re: [Pyobjc-dev] [ pyobjc-Bugs-836247 ] NSWindow.contentRectForFrameRect_styleMask_ not a class meth
From: Ronald O. <ous...@ci...> - 2003-11-09 09:37:18
|
On 9 nov 2003, at 0:30, Jack Jansen wrote: > > On 7-nov-03, at 18:45, b.bum wrote: > >> On Nov 7, 2003, at 8:20 AM, Bob Ippolito wrote: >>> No, it also happens when you are just using ObjC classes from the >>> Python side of the bridge. It *always* binds to the instance >>> method, nomatter what, if it has one. I'm not even worried about >>> overriding them from Python at the moment, just making ObjC classes >>> usable as they should be. >> >> Right -- and that is a bug. > > This hits the two-faced issue on the head: it's a bug if you look at > this with ObjC in mind, it's an essential shortcoming if you look at > it with Python in mind. > > Bob said (at some point in the past of this discussion) something to > the effect that someclass.somemehod is a selector. If you view it from > that angle then the current behavior is a bug. > My initial thought (with my Python hat on) was that > someclass.somemethod is either a class method or an unbounded instance > method. Then this isn't a bug but a shortcoming that can't be > overcome. That's a nice summary of the issues. Having thought about this a little I wouldn't mind if we changed the selector code to be smarter about this, e.g.: 1) If the method is accessed through an instance it is always an instance method (and if there is only a class method we raise an AttributeError) 2) If the method is accessed through a class it is: - an unbound method if it is only an instance method - a bound method if it is only a class method - a "smart" method if it is both an instance method and a class method Smart methods somehow detect how they are used (the number of arguments passed in springs to mind, if you call an unbound instance method you pass the self argument, if you call a bound class method you don't). Other issues: - if the class method has a different signature than the instance method we cannot create a "smart" method, I'd fall back to the current behaviour (e.g. return the instance method). It is highly unlikely that this ever happens. - It *must* be possible to get information about instance methods through the class, otherwise we cannot create class browsers. - If a "smart" method is overridden in a subclass, the subclass should still contain a "smart" method. Ronald |