Thread: [Pyobjc-dev] NibLoader.py: parsing nibs at runtime
Brought to you by:
ronaldoussoren
From: Just v. R. <ju...@le...> - 2002-11-15 05:55:02
Attachments:
NibLoader.py
|
Today, instead of learning how to do useful things with Cocoa <wink>, I wrote a replacement for mknibwrapper/objc.classnib.py, that does the same thing at runtime, making nibwrapper.py files superfluous. This abviously has some startup time hit, but it seems quite quick. Not that I think that having to generate nibwrapper.py files is all that bad, I was just looking for an opportunity to learn a thing or two, eg. about metaclasses... The attached module lets you do this: [...more imports snipped...] from NibLoader import NibLoader, addNib # (the addNib() could be done elewhere, or could be done more # concisely with a helper funciton in the NibLoader module) addNib(os.path.join(sys.path[0], "English.lproj/MainMenu.nib")) class PyModel(NibLoader, NSTableDataSource): ...etc... addNib() parses a nib file and sucks the class info out of it. NibLoader is a magic class (or rather, has a magic superclass) that will make sure the subclass has the right base class, and will populate it with all the stuff that was normally generated in the nibwrapper file. So far I've only tested it with the TableModel demo: it works for me. The NibLoader module contains a tiny test program: you can invoke it from the command line like so: % python NibLoader.py <path-to-nib> [more paths to nibs] It will parse all nibs specified and will build dummy test classes for all found nib classes and print some blurb to stdout. I've tested this on a few nibs found in apps that came with the OS as well as with all the nibs in the Examples folder, and apart from some classes that don't seem to have a SUPERCLASS attribute, building the test classes seems to work. Obviously much of the code is ripped straight from objc/classnib.py. Useful? Just |
From: <bb...@ma...> - 2002-11-15 16:19:14
|
On Thursday, November 14, 2002, at 07:09 PM, Just van Rossum wrote: > Today, instead of learning how to do useful things with Cocoa <wink>, > I wrote a > replacement for mknibwrapper/objc.classnib.py, that does the same > thing at > runtime, making nibwrapper.py files superfluous. Excellent. > This abviously has some startup time hit, but it seems quite quick. > Not that I > think that having to generate nibwrapper.py files is all that bad, I > was just > looking for an opportunity to learn a thing or two, eg. about > metaclasses... The startup is minor in comparison to other startup issues and to the unarchival of the object graph contained in the NIB [I would think]. Small price to pay in return for one less dependency within the development environment. > It will parse all nibs specified and will build dummy test classes for > all found > nib classes and print some blurb to stdout. I've tested this on a few > nibs found > in apps that came with the OS as well as with all the nibs in the > Examples > folder, and apart from some classes that don't seem to have a > SUPERCLASS > attribute, building the test classes seems to work. If a class doesn't have a SUPERCLASS, it should default to NSObject, I would think. I'll look into this as I convert some of my projects over to using NibLoader. > Obviously much of the code is ripped straight from objc/classnib.py. > > Useful? Very. Added to the CVS repository as Lib/AppKit/NibLoader.py. I modified it to skip FirstResponder -- a class does not need to be created for FirstResponder (target/action directed at first responder indicates to the event handling system that the action should be sent to the first object in the responder chain that responds to the action). I also added an addNibFromBundle() function that can be used like this: NibLoader.addNibFromBundle( "MainMenu.nib" ) It takes an optional second argument if you want to point it at a particular bundle or framework; defaults to NSBundle.mainBundle(). It uses NSBundle's pathForResource:ofType: method to find the NIB and, as such, will automatically load the NIB of the correct language in localized apps. Ronald: Does this supersede classnib? I.e. should classnib be removed? b.bum b.bum No Chunks... ... No Foul! |
From: <bb...@ma...> - 2002-11-15 16:30:05
|
[code committed] Unfortunately, I'm not having any luck modifying WebServicesTool to use the loader. If I do: from AppKit import NibLoader NibLoader.addNibFromBundle( "MainMenu.nib" ) class WSTApplicationDelegate (NibLoader): def newConnectionAction_(self, sender): WSTConnectionWindowController.connectionWindowController().showWindow_(s ender) def applicationDidFinishLaunching_(self, aNotification): self.newConnectionAction_(None) ... then, at runtime, I see ... 2002-11-15 11:26:58.092 Web Services Tool[24489] Process ID is: 24489 ( gdb /usr/bin/python 24489 to debug) 2002-11-15 11:27:08.624 Web Services Tool[24489] Unknown class `WSTApplicationDelegate' in nib file, using `NSObject' instead. 2002-11-15 11:27:08.639 Web Services Tool[24489] Could not connect the action newConnectionAction: to target of class NSObject ... It seems that the WSTApplicationDelegate class is not being defined in a fashion that is found by the ObjC side of the bridge? Actually, If I do... print WSTApplicationDelegate print dir(WSTApplicationDelegate) ... after the class definition, the output changes to ... <module '?' (built-in)> [] 2002-11-15 11:29:30.565 Web Services Tool[24519] Unknown class `WSTApplicationDelegate' in nib file, using `NSObject' instead. 2002-11-15 11:29:30.567 Web Services Tool[24519] Could not connect the action newConnectionAction: to target of class NSObject I'm confused now. b.bum |
From: Ronald O. <ous...@ci...> - 2002-11-15 19:31:46
|
On Friday, Nov 15, 2002, at 17:29 Europe/Amsterdam, bb...@ma... wrote: > [code committed] > > Unfortunately, I'm not having any luck modifying WebServicesTool to > use the loader. If I do: > > from AppKit import NibLoader > > NibLoader.addNibFromBundle( "MainMenu.nib" ) > > class WSTApplicationDelegate (NibLoader): This should be ... (NibLoader.NibLoader): Ronald |
From: <bb...@ma...> - 2002-11-15 22:04:36
|
On Friday, November 15, 2002, at 02:30 PM, Ronald Oussoren wrote: >> class WSTApplicationDelegate (NibLoader): > This should be ... (NibLoader.NibLoader): Doh! Defeated by the Obvious Yet Again! Instead of calling it 'NibLoader', how about NibSuper, NibAbstract, NibBase, or something else other than the module name? I have been burned by this-- and have helped folks new to Python-- on this exact same kind of a problem *so many times* now, that I really try to avoid this kind of namespace overloading as much as possible. Once changed, works flawlessly! b.bum |
From: Jack J. <Jac...@or...> - 2002-11-15 23:27:57
|
On vrijdag, nov 15, 2002, at 23:04 Europe/Amsterdam, bb...@ma... wrote: > On Friday, November 15, 2002, at 02:30 PM, Ronald Oussoren wrote: >>> class WSTApplicationDelegate (NibLoader): >> This should be ... (NibLoader.NibLoader): > > Doh! Defeated by the Obvious Yet Again! > > Instead of calling it 'NibLoader', how about NibSuper, NibAbstract, > NibBase, or something else other than the module name? I have been > burned by this-- and have helped folks new to Python-- on this exact > same kind of a problem *so many times* now, that I really try to avoid > this kind of namespace overloading as much as possible. It's standard Python idiom (if a module has a main class give them the same name), but now that the bases for a class can be pretty much everything that is callable, in stead of only modules as it used to be, it can lead to strange errors. But I think NibLoader should be able to detect this situation (not sure though, I don't have the code handy, and I still haven't read Just's message which will hopefully finally make me understand metaclasses). -- - 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...> - 2002-11-15 17:09:00
|
bb...@ma... wrote: > Added to the CVS repository as Lib/AppKit/NibLoader.py. Ah, I would have suggested to add it to objc, though. Also, I've already completely rewritten it... And I'm having an offline discussion with Jack (Cc-ing Ronald) about the design. Tonight I'll be able to post a new version and outline the revised design, but now it's dinner time! If you want, can give me commit rights, my sf name is "jvr". Later, Just |
From: Ronald O. <ous...@ci...> - 2002-11-15 18:49:08
|
While I like the idea, I feel there is a minor disadvantage to this solution: With an explicit nibwrapper.py you can easily check which methods you should implement and which outlets are available. The advantage of your approach is that you do not have to worry about updating the nibwrapper.py file when you make relevant changes to a NIB file. The additional startup time is probably not very relevant (at least at the moment, loading the frameworks pretty expensive) We could of course use a variant of mknibwrapper to generate userfriendly documentation instead of a python file. Ronald On Friday, Nov 15, 2002, at 01:09 Europe/Amsterdam, Just van Rossum wrote: > Today, instead of learning how to do useful things with Cocoa <wink>, > I wrote a > replacement for mknibwrapper/objc.classnib.py, that does the same > thing at > runtime, making nibwrapper.py files superfluous. > > This abviously has some startup time hit, but it seems quite quick. > Not that I > think that having to generate nibwrapper.py files is all that bad, I > was just > looking for an opportunity to learn a thing or two, eg. about > metaclasses... > > The attached module lets you do this: > > > [...more imports snipped...] > from NibLoader import NibLoader, addNib > > # (the addNib() could be done elewhere, or could be done more > # concisely with a helper funciton in the NibLoader module) > addNib(os.path.join(sys.path[0], "English.lproj/MainMenu.nib")) > > class PyModel(NibLoader, NSTableDataSource): > ...etc... > > > addNib() parses a nib file and sucks the class info out of it. > NibLoader is a magic class (or rather, has a magic superclass) that > will make > sure the subclass has the right base class, and will populate it with > all the > stuff that was normally generated in the nibwrapper file. > > So far I've only tested it with the TableModel demo: it works for me. > > The NibLoader module contains a tiny test program: you can invoke it > from the > command line like so: > > % python NibLoader.py <path-to-nib> [more paths to nibs] > > It will parse all nibs specified and will build dummy test classes for > all found > nib classes and print some blurb to stdout. I've tested this on a few > nibs found > in apps that came with the OS as well as with all the nibs in the > Examples > folder, and apart from some classes that don't seem to have a > SUPERCLASS > attribute, building the test classes seems to work. > > Obviously much of the code is ripped straight from objc/classnib.py. > > Useful? > > Just<NibLoader.py> |
From: Just v. R. <ju...@le...> - 2002-11-15 19:10:39
|
Ronald Oussoren wrote: > While I like the idea, I feel there is a minor disadvantage to this > solution: With an explicit nibwrapper.py you can easily check which > methods you should implement and which outlets are available. Yes, that crossed my mind. > The advantage of your approach is that you do not have to worry about > updating the nibwrapper.py file when you make relevant changes to a > NIB file. Exactly. I think that's a big win. > The additional startup time is probably not very relevant > (at least at the moment, loading the frameworks pretty expensive) Right. > We could of course use a variant of mknibwrapper to generate > userfriendly documentation instead of a python file. It would be trivial to add such a thing to NibLoader.py. I'll do so after the next iteration of the module. Just |
From: Jack J. <Jac...@or...> - 2002-11-15 23:27:57
|
On vrijdag, nov 15, 2002, at 11:39 Europe/Amsterdam, Ronald Oussoren wrote: > We could of course use a variant of mknibwrapper to generate > userfriendly documentation instead of a python file. Not only documentation but also a skeleton implementation, similar to the "generate .c/.h" from Interface Builder. And while we're at it: it would be a killer feature if NibLoader could optionally use Python's introspection features to check that your subclass actually implements all needed methods and such, so that if you set NibLoader.DEBUG to true (or have that set automatically if the environment variable PY_NIBLOADER_DEBUG is set) your classes are checked for conforming to what the nib expects. Of course we can't go any further than method names and number of arguments, but it would still be a great tool. -- - 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...> - 2002-11-16 19:55:49
|
Jack Jansen wrote: > On vrijdag, nov 15, 2002, at 11:39 Europe/Amsterdam, Ronald Oussoren > wrote: > > We could of course use a variant of mknibwrapper to generate > > userfriendly documentation instead of a python file. > > Not only documentation but also a skeleton implementation, similar to > the "generate .c/.h" from Interface Builder. (Where is this functionality? Can't find any menu for it in IB...) > And while we're at it: it would be a killer feature if NibLoader could > optionally use Python's introspection features to check that your > subclass actually implements all needed methods and such, so that if > you set NibLoader.DEBUG to true (or have that set automatically if the > environment variable PY_NIBLOADER_DEBUG is set) your classes are > checked for conforming to what the nib expects. Of course we can't go > any further than method names and number of arguments, but it would > still be a great tool. Right, this should actually be straightforward! What the NibClassBuilder metaclass currently does is add stub methods for actions not defined in the class itself, and add IBOutlets for outlets that haven't been defined "manually". It would be easy to print a warning to stderr at class-build-time if an action isn't defined. I think this flag should be True by default, though, since you're supposed to implement them all anyway. If you _choose_ to just keep the noop stub, _then_ you should set the debug flag to false... (I don't grok outlets just yet: are the default IBOutlet objects all that are ever needed, or are you supposed to provide them yourself?) Just PS: I still can't commit. Does anyone know whether it would be wise to open an sf support request yet, or should I be a little more patient? |
From: <bb...@ma...> - 2002-11-16 20:10:55
|
On Saturday, November 16, 2002, at 02:55 PM, Just van Rossum wrote: > PS: I still can't commit. Does anyone know whether it would be wise to > open an > sf support request yet, or should I be a little more patient? What is the specific error? I may have screwed something up on the SF administrative front but it could just as easily be an SF problem as I have seen a number of those in the past. b.bum |
From: Just v. R. <ju...@le...> - 2002-11-16 20:43:11
|
bb...@ma... wrote: > What is the specific error? just% cvs up cvs server: failed to create lock directory for `/cvsroot/pyobjc/pyobjc/Lib/AppKit' (/cvsroot/pyobjc/pyobjc/Lib/AppKit/#cvs.lock): Permission denied cvs server: failed to obtain dir lock in repository `/cvsroot/pyobjc/pyobjc/Lib/AppKit' cvs [server aborted]: read lock failed - giving up just% > I may have screwed something up on the SF administrative front but it > could just as easily be an SF problem as I have seen a number of those > in the past. Yeah, this sounds most likely... If it's not over by tomorrow I'll file a support request. Just |
From: Ronald O. <ous...@ci...> - 2002-11-16 20:30:33
|
On Saturday, Nov 16, 2002, at 20:55 Europe/Amsterdam, Just van Rossum wrote: > > >> And while we're at it: it would be a killer feature if NibLoader could >> optionally use Python's introspection features to check that your >> subclass actually implements all needed methods and such, so that if >> you set NibLoader.DEBUG to true (or have that set automatically if the >> environment variable PY_NIBLOADER_DEBUG is set) your classes are >> checked for conforming to what the nib expects. Of course we can't go >> any further than method names and number of arguments, but it would >> still be a great tool. > > Right, this should actually be straightforward! What the > NibClassBuilder > metaclass currently does is add stub methods for actions not defined > in the > class itself, and add IBOutlets for outlets that haven't been defined > "manually". It would be easy to print a warning to stderr at > class-build-time if > an action isn't defined. I think this flag should be True by default, > though, > since you're supposed to implement them all anyway. If you _choose_ to > just keep > the noop stub, _then_ you should set the debug flag to false... If you choose to do nothing you might as wel write the empty method yourself (there is probably a reason for doing nothing). That way we can do away with the flag and always warn if you don't implement all actions. > > (I don't grok outlets just yet: are the default IBOutlet objects all > that are > ever needed, or are you supposed to provide them yourself?) The default IBOutlets are all that is ever needed. You can set specific types in Interface Builder, but those are all Objective-C classes and those are all represented the same way in the Objective-C runtime. I'd probably prefer to emit a warning when you do define IBOutlet objects over doing it when you don't. Never warning at al is probably best. BTW. outlets are implemented using attributes/member variables in ObjC code, IBOutlets perform the same task in PyObjC. Ronald |
From: Just v. R. <ju...@le...> - 2002-11-16 20:53:17
|
Ronald Oussoren wrote: [ noop action stubs ] > If you choose to do nothing you might as wel write the empty method > yourself (there is probably a reason for doing nothing). That way we > can do away with the flag and always warn if you don't implement all > actions. Agreed. Will do. > > (I don't grok outlets just yet: are the default IBOutlet objects all > > that are > > ever needed, or are you supposed to provide them yourself?) > > The default IBOutlets are all that is ever needed. You can set specific > types in Interface Builder, but those are all Objective-C classes and > those are all represented the same way in the Objective-C runtime. Ok. I've renamed the NibInfo.printOverview() method to NibInfo.printTemplate(). It will print a Python template with stubs for actions and comments for outlets. NibLoader.py is converging back to classnib.py ;-) > I'd probably prefer to emit a warning when you do define IBOutlet > objects over doing it when you don't. Never warning at al is probably > best. > > BTW. outlets are implemented using attributes/member variables in ObjC > code, IBOutlets perform the same task in PyObjC. The thing that I don't understand is why they are class attributes: I'd expect (but then again, I don't grok them yet) they'd be specific to an instance, and therefore be instance attributes. How does it work? Just |
From: <bb...@ma...> - 2002-11-16 21:35:00
|
For action methods, I would suggest not building the stub methods for each action. Cocoa's nib loading mechanism already verifies that an action method exists as the NIB is loaded and, if not, will emit a message such as... 2002-11-16 16:29:47.283 example[1603] Could not connect the action randomAction: to target of class ExampleObject ... which serves nicely to remind the developer that that particular action method needs to be implemented. Note that pushing the button that tried to connect that action doesn't do anything. As far as outlets are concerned, validation becomes more difficult. Whether or not the outlet exists is determined by the configuration of the NIB file, not the developer and, as such, it is impossible-- given Just's most excellent code-- for the developer to 'use' an outlet that is not actually declared in the NIB (the developer can try, but they will get the classic KeyError style 'no such attribute' python exception). b.bum |
From: Just v. R. <ju...@le...> - 2002-11-16 22:08:02
|
bb...@ma... wrote: > For action methods, I would suggest not building the stub methods for > each action. Cocoa's nib loading mechanism already verifies that an > action method exists as the NIB is loaded and, if not, will emit a > message such as... > > 2002-11-16 16:29:47.283 example[1603] Could not connect the action > randomAction: to target of class ExampleObject > > .... which serves nicely to remind the developer that that particular > action method needs to be implemented. Note that pushing the button > that tried to connect that action doesn't do anything. Erm, when is this warning emitted? When the class is instantiated or when the button is clicked? If the latter: NibLoader could do it at class-build-time. Just |
From: <bb...@ma...> - 2002-11-16 22:22:12
|
On Saturday, November 16, 2002, at 05:06 PM, Just van Rossum wrote: > bb...@ma... wrote: >> For action methods, I would suggest not building the stub methods for >> each action. Cocoa's nib loading mechanism already verifies that an >> action method exists as the NIB is loaded and, if not, will emit a >> message such as... >> >> 2002-11-16 16:29:47.283 example[1603] Could not connect the action >> randomAction: to target of class ExampleObject >> >> .... which serves nicely to remind the developer that that particular >> action method needs to be implemented. Note that pushing the button >> that tried to connect that action doesn't do anything. > > Erm, when is this warning emitted? When the class is instantiated or > when the > button is clicked? If the latter: NibLoader could do it at > class-build-time. Neither; when the NIB is loaded and the nib loading mechanism walks through the connections to ensure that the appropriate target/action methods can be connected. This is the only time that such validation can occur. Class instantiation is too early as there may be additional methods added to the class between the time the class is created and those methods may contain the action implementations. b.bum |
From: Just v. R. <ju...@le...> - 2002-11-16 22:35:18
|
bb...@ma... wrote: > > Erm, when is this warning emitted? When the class is instantiated > > or when the button is clicked? If the latter: NibLoader could do it > > at class-build-time. > > Neither; when the NIB is loaded and the nib loading mechanism walks > through the connections to ensure that the appropriate target/action > methods can be connected. You mean when (eg.) a window is instantiated? > This is the only time that such validation can occur. Class > instantiation is too early as there may be additional methods added > to the class between the time the class is created and those methods > may contain the action implementations. Not sure if I get this. What NibLoader could do is, that as soon the module containing the class is imported, it verifies the action methods contained in the class body actually contain all the methods as specified in the nib. How does this compare to what the Cocoa runtime does? Just |
From: <bb...@ma...> - 2002-11-16 22:54:13
|
On Saturday, November 16, 2002, at 05:34 PM, Just van Rossum wrote: > bb...@ma... wrote: >>> Erm, when is this warning emitted? When the class is instantiated >>> or when the button is clicked? If the latter: NibLoader could do it >>> at class-build-time. >> >> Neither; when the NIB is loaded and the nib loading mechanism walks >> through the connections to ensure that the appropriate target/action >> methods can be connected. > > You mean when (eg.) a window is instantiated? NIB loading basically happens in two passes: - all objects contained in the object graph within the NIB are unarchived (this is an oversimplification -- see the 'deferred' functionality on NSWindow -- irrelevant for this discussion, though very interesting it is) - all of the NIB connections are made The second step is when the validation occurs. So, it happens after instantiation but before the first action is sent. Through -awakeFromNib, the developer is given the opportunity to further edit the object graph before the first action is sent. >> This is the only time that such validation can occur. Class >> instantiation is too early as there may be additional methods added >> to the class between the time the class is created and those methods >> may contain the action implementations. > > Not sure if I get this. What NibLoader could do is, that as soon the > module > containing the class is imported, it verifies the action methods > contained in > the class body actually contain all the methods as specified in the > nib. How > does this compare to what the Cocoa runtime does? A step back for a second: The NibLoader.py that exists now doesn't really have anything to do directly with NIB loading and has everything to do with defining new Objective-C classes. NibLoader provides the developer with an incredible convenience; the developer no longer has to worry about keeping their source files in sync with the reality perpetuated by the NIB file. NIB loading happens much later. Furthermore, the typical Cocoa application will have a need to user the classes that may potentially be defined via NibLoader long before the NIB file is actually loaded. Consider the case of a Preferences controller. The controller may provide API for retrieving and setting preferences values that are used application wide. It may also provide various actions/outlets via which it controls the display of preferences in a preferences panel. The preferences controller may be instantiated long before the preferences UI is ever displayed (and the UI may never be displayed). In terms of validation, the validation of the target/action connections made in a NIB file cannot be made until the NIB file itself is actually loaded. Consider this very bogus example: >>> class MyFoo(NSObject): pass ... >>> def barAction_(self, sender): print "responding to bar -- %s" % sender ... >>> MyFoo.barAction_ = barAction_ Now, imagine that the definition of the MyFoo class was the result of using NibLoader, which found the MyFoo class in the NIB file. Sometime between the initial definition of the class MyFoo and the loading of the NIB file, the developer has added the barAction_() method to MyFoo -- in traditional ObjC, this is likely because they loaded an NSBundle that contains a category on the MyFoo class that added the additional method(s). This is actually a pretty common situation given the responder chain. By simply tossing some action methods into a category on NSApplication or NSWindow, then setting the target of a menu item or button to nil while setting the action to be the newly added methods, that action can be triggered from anywhere in the UI. Similar tricks can be done to add new functionality to every button, every field, every text view, every table view, or any other subset of objects. With python, the ability to derive new methods programmatically and add them at will makes it all the more powerful. In any case, the end result is that the target/action connectivity cannot be validated when the class is initially defined as a combination of what is found in the NIB and what the developer has directly implemented -- there may be new method implementations added before the NIB is loaded that will fill in the missing pieces, effectively. b.bum |
From: Ronald O. <ous...@ci...> - 2002-11-17 07:07:09
|
On Saturday, Nov 16, 2002, at 23:34 Europe/Amsterdam, Just van Rossum wrote: > bb...@ma... wrote: > >>> Erm, when is this warning emitted? When the class is instantiated >>> or when the button is clicked? If the latter: NibLoader could do it >>> at class-build-time. >> >> Neither; when the NIB is loaded and the nib loading mechanism walks >> through the connections to ensure that the appropriate target/action >> methods can be connected. > > You mean when (eg.) a window is instantiated? That is what I understood of it. This would only catch errors for actions that are actually used, not for actions that are defined but are not a target. I prefer emitting warnings when the class is instantiated as this would give you a complete set of warnings during program startup. Actually only if you load all Nib classes during program startup but I've been doing that upto now. > >> This is the only time that such validation can occur. Class >> instantiation is too early as there may be additional methods added >> to the class between the time the class is created and those methods >> may contain the action implementations. > > Not sure if I get this. What NibLoader could do is, that as soon the > module > containing the class is imported, it verifies the action methods > contained in > the class body actually contain all the methods as specified in the > nib. How > does this compare to what the Cocoa runtime does? In Objective-C it is possible to define categories that in effect add new methods to an existing class interface. It is possible to load categories at runtime (NSString is one example in Cocoa, its interface is defined in Foundation and then enhanced in AppKit). In Python you can also add new methods to a class. I'd not worry to much about this, if only because it will be less efficient to call those additional methods from Objective-C: The additional methods are called through an NSInvocation while the normal methods are called through more efficient method stubs. Ronald |
From: <bb...@ma...> - 2002-11-18 16:16:29
|
On Sunday, November 17, 2002, at 02:06 AM, Ronald Oussoren wrote: > In Python you can also add new methods to a class. I'd not worry to > much about this, if only because it will be less efficient to call > those additional methods from Objective-C: The additional methods are > called through an NSInvocation while the normal methods are called > through more efficient method stubs. Efficiency of dispatch in this context is largely irrelevant as it generally happens as a part of the user clicking a button or hitting a menu item -- i.e. once to trigger the event processing. Given that action method validation already exists within the AppKit framework and it works at the only time where complete/correct validation is possible, why should we bother duplicating that functionality in the PyObjC module and doing so in a fashion that is going to generate false warnings? b.bum |
From: Ronald O. <ous...@ci...> - 2002-11-19 06:22:00
|
On Monday, Nov 18, 2002, at 16:01 Europe/Amsterdam, bb...@ma... wrote: > On Sunday, November 17, 2002, at 02:06 AM, Ronald Oussoren wrote: >> In Python you can also add new methods to a class. I'd not worry to >> much about this, if only because it will be less efficient to call >> those additional methods from Objective-C: The additional methods are >> called through an NSInvocation while the normal methods are called >> through more efficient method stubs. > > Efficiency of dispatch in this context is largely irrelevant as it > generally happens as a part of the user clicking a button or hitting a > menu item -- i.e. once to trigger the event processing. It is not entirely irrelevant, some methods in the NSTableDataSource are called quite often and if those are slow this is noticable. > > Given that action method validation already exists within the AppKit > framework and it works at the only time where complete/correct > validation is possible, why should we bother duplicating that > functionality in the PyObjC module and doing so in a fashion that is > going to generate false warnings? It might generate false warnings if the Python code adds new methods at runtime. Whenever I do things like that I prefer not to depend on automatic mechanisms likes Just's AutoBaseClass. The other 'false' warnings are generated when actions have been defined in Interface Builder that are not yet used. I don't think these are false warnings at all, either the UI does not yet use the actions (e.g. this is a development version) or you're building up cruft in your NIB file. Ronald |
From: <bb...@ma...> - 2002-11-19 08:59:59
|
On Tuesday, November 19, 2002, at 01:20 AM, Ronald Oussoren wrote: > On Monday, Nov 18, 2002, at 16:01 Europe/Amsterdam, bb...@ma... wrote: > >> On Sunday, November 17, 2002, at 02:06 AM, Ronald Oussoren wrote: >>> In Python you can also add new methods to a class. I'd not worry to >>> much about this, if only because it will be less efficient to call >>> those additional methods from Objective-C: The additional methods >>> are called through an NSInvocation while the normal methods are >>> called through more efficient method stubs. >> >> Efficiency of dispatch in this context is largely irrelevant as it >> generally happens as a part of the user clicking a button or hitting >> a menu item -- i.e. once to trigger the event processing. > > It is not entirely irrelevant, some methods in the NSTableDataSource > are called quite often and if those are slow this is noticable. Yes; Speaking of.... when are NSTableDataSource methods validated? ... at Nib load or when the table goes to the datasource the first time? I would consider it a performance issue that we have to go through NSInvocation in this situation -- a bug, really -- but I'm not at all sure there is anyway around it? >> Given that action method validation already exists within the AppKit >> framework and it works at the only time where complete/correct >> validation is possible, why should we bother duplicating that >> functionality in the PyObjC module and doing so in a fashion that is >> going to generate false warnings? > > It might generate false warnings if the Python code adds new methods > at runtime. Whenever I do things like that I prefer not to depend on > automatic mechanisms likes Just's AutoBaseClass. Agreed. > The other 'false' warnings are generated when actions have been > defined in Interface Builder that are not yet used. I don't think > these are false warnings at all, either the UI does not yet use the > actions (e.g. this is a development version) or you're building up > cruft in your NIB file. Agreed -- and they are warnings that will be covered when the NIB is loaded, so why reinvent the wheel? I often use the warnings that the Cocoa NIB loading mechanism emits as a kind of bookmark for functionality that needs to be implemented. This is a big part of the reason why I don't think that the AutoBaseClass on-the-fly class definition should define placeholders; they effectively disable already working validation, move the validation to a location that an experienced Cocoa programmer will not expect, and raise the situation of potentially false validation warnings. b.bum |
From: Just v. R. <ju...@le...> - 2002-11-19 09:13:37
|
[bbum] > > Given that action method validation already exists within the AppKit > > framework and it works at the only time where complete/correct > > validation is possible, why should we bother duplicating that > > functionality in the PyObjC module and doing so in a fashion that is > > going to generate false warnings? I would be easy to avoid these false warnings by (manually) adding a stub action. [Ronald Oussoren] > It might generate false warnings if the Python code adds new methods at > runtime. Whenever I do things like that I prefer not to depend on > automatic mechanisms likes Just's AutoBaseClass. Right. Currently AutoBaseClass adds stub actions, basically disabling the AppKit validation, so I think this should be removed. Btw. is it possible to mix in action methods from another class like so: class PyModel(AutoBaseClass, NSTableSource, SomeCommonActionsIPreparedEarlier): ... ? If this _is_ possible, then the stub-injecting code currently in NibClassBuilder will only screw things up... Ok, the stub actions need to go. Then remains the question whether (in addition to AppKit's own warnings) it may be useful to issue a warning on missing actions here as well. Just |