On 7-aug-04, at 2:50, ytrewq1@... wrote:
>
> On Wed, 4 Aug 2004 21:13:26 +0200, "Ronald Oussoren"
> <ronaldoussoren@...> said:
>>
>> On 1-aug-04, at 1:10, ytrewq1@... wrote:
>>> I'd like to try writing plugins for the Colloquy IRC client using
>>> PyObjC,
>>> but as far as I can tell from their sdk, they don't provide the
>>> pieces
>>> I'd need to use in the form of a bundle. I guessed this from
>>> examining
>>> the content of:
>>>
>>> http://colloquy.info/downloads/plugin-sdk.zip
>>
>>
>> I finally got around downloading this.
>>
>> The classes seem to be defined in the main bundle, you could try using
>> NSBundle.mainBundle().bundlePath() as an argument to loadBundle.
>
> Bob sent me this advice too (-; I performed some limited testing
> and I think it works. Thanks to both of you!
>
>> Another option is a more tradition approach: use objc.classList() and
>> add all classes whose name starts with 'JV' or 'MV' to your module.
>
> I'll keep this approach in my for the future -- nice to have options.
>
>> The header files contain a number of enum definitions, you can use our
>> codegenerator scripts to extract those, but I wouldn't do that here
>> (at
>> least not until we refactor those scripts).
>
> Thanks for the pointer. I'll have a look at those scripts. Are these
> the
> ones located in the CodeGenerators directory?
>
>>> [2] Though I'm having some trouble getting multiple PyObjC plugins to
>>> play
>>> well together -- but more on this in another message.
>>
>> Could you elaborate on that?
>
> Ok, let me give some background on what I did with Quicksilver plugins.
>
> Quicksilver plugins are bundles, and in addition to specifying the
> plugin's
> principal class via its Info.plist, one can specify class names which
> provide various types of functionality. For example, in the
> QSRegistration
> section of the Info.plist of one of my plugins there is:
>
> <key>QSObjectSources</key>
> <dict>
> <key>YTAtomObjectSource</key>
> <string>YTAtomObjectSource</string>
> </dict>
>
> Here YTAtomObjectSource is a subclass of QSObjectSource - an abstract
> class
> which represents a 'source' of objects which Quicksilver is meant to
> handle. (In this specific case, the source provides Atom API
> endpoints.)
>
> Most of my plugin is written in Python (e.g. the class
> YTAtomObjectSource),
> and I arranged for the principal class' load method to set up the
> interface w/ Python and load my python code. The nice thing about the
> Quicksilver plugin approach [1] is that I can use the principal class
> just to
> do set up and Quicksilver makes use of what's defined in QSRegistration
> as
> entry points in to the functionality which the plugin provides.
>
> My initial approach was based on what I found at:
>
> http://pyobjc.sourceforge.net/doc/extending_objc_with_python.php
>
> This worked fine for when there was only one plugin using Python, but
> not for using multiple plugins at the same time. One of the plugins
> would function normally, but the others would not -- though they all
> functioned properly if used individually. One of my suspicions as to
> the cause was that each of them was calling objc.loadBundle on the same
> bundle (while being loaded by PyRun_SimpleFile) -- but I didn't manage
> to confirm this as a factor.
>
> After much hair-pulling, I extracted and applied some of the
> generated-code
> section from pluginbuilder.py -- mostly related to avoiding
> PyRun_SimpleFile
> and __main__ (does that interpretation sound right?) -- and now I am
> able to use multiple PyObjC plugins in the same Quicksilver session.
>
> I hope that was understandable.
Hmm, your hunch might be right, loadBundle only looks at classes which
don't have a __module__ attribute yet. If you call loadBundle a second
time on the same bundle the classes in that bundle will already have a
valid __module__ atttribute and will therefore be ignored. That's
easily fixed when 1 restriction is applied: the 'module_name' argument
must be the same for all invocations of loadBundle.
Another way to avoid this issue is to make a QuickSilver module and
install that in /Library/Python/2.3. That way loadBundle will get
called only once.
>
>
> [1] Whereas I'm struggling with trying to write a plugin for Colloquy
> using
> PyObjC. I see that I can specify a principal class, and this seems the
> logical
> place to set up the interface (bridge?) w/ Python, but once that's
> done,
> IIUC, Colloquy will expect to call methods in an instance of the
> principal
> class (which will have been written in Objective C...whereas I'd like
> to
> be able to write these methods in Python).
If you use the normal pluginbuilder template and use a global Colloquy
module in /Library/Python/2.3, this should "just work". The
EnvironmentPrefs example implements the principal class in Python.
Pluginbuilder creates some objective-C code that also contains a class,
but that's only used for its +initialize method.
EnvironmentPrefs uses NibClassBuilder, but that's not relevant to this
discussion. Classes that use NibClassBuilder are not magic in any way,
NibClassBuilder is just a tool that makes it easier to keep the Python
class definition synchronized with that in the NIB file (especially
w.r.t. outlet definitions).
Ronald
--
X|support bv http://www.xsupport.nl/
T: +31 610271479 F: +31 204416173
|