[python-win32] extending com objects

Ross McKerchar it at crummock.com
Thu May 24 11:32:05 CEST 2007


A few months ago I posted asking for some advice on ways to extend 
classes provided by com objects.

Primarily I was keen to make a com library that I work with a lot 
(Notes/Domino if anyone's interested) nicer and more pythonic to use.

I've spent a good few hours bashing away and have found two ways which 
appear to work with my simplistic test suite. However I'm not 
particularly comfortable with either of them (the black magic I'm using 
is all a bit new to me). Consequently if anyone has time to have a look 
at my solutions I'd be very grateful.

Attempt #1 (code at http://www2.crummock.com/comwrapper.py):

Based on what Tim Golden called a "Delegation model", involved holding 
an internal copy of my com class and by implementing getattr/setattr 
calling the com object when necessary. This turned out a fair bit more 
complicated than I originally expected as lots of the com objects 
methods returned other com objects from the same library. I wanted these 
returned com objects to also be automatically wrapped in my extension 
classes to save having to constantly wrap in my client code. To do this 
I ended up with some very convoluted code that intercepted all my com 
method calls to see if they returned a com object for which I had a 
corresponding wrapper class and if so, wrap it. Of course I then had to 
check all tuples returned to see if they also contained  candidates for 
wrapping.

I got this working (well enough that it passed my far-from-comprehensive 
test-suite) but I wasn't convinced by it: the complexity of my wrapping 
system is bound to contain some subtle bugs and it also introduced a 
significant performance overhead (about 15% runtime overhead from some 
rough tests).

Attempt #2:

This very simple, alternative method then occured to me:

#My custom classes
class IDocument: ...
class IDatabase: ...
class IDocumentCollection: ...

from win32com.client.gencache import GetModuleForProgID
module = GetModuleForProgID('Lotus.NotesSession')
implementedChildClasses = (IDocument,IDatabase,IDocumentCollection)
for klass in implementedChildClasses:
     #find parent class of same name
     parentclass = getattr(module,klass.__name__)
     parentclass.__dict__.update(klass.__dict__)

I just put this code at the bottom of my module and it automagically 
adds all my methods & attributes from classes listed in 
"implementedChildClasses" to the com class (at the expense of needing to 
run makepy on the com library, of course). The beauty of this is that I 
dont have to worry about wrapping the results of any functions as I'm 
always dealing with the real com class, just with some extra methods 
added. It is also a more efficient - a small overhead when loading the 
module but a lot quicker when using it. Unfortunately, it does feel like 
a big hack and I'm not convinced it's a sensible thing to do?

So, I dont actually have any real problems as such I'm just looking for 
advice/comments from anyone who is more familiar with all these magical 
techniques.

-ross


More information about the Python-win32 mailing list