[python-win32] extending com objects
Ross McKerchar
it at crummock.com
Fri May 25 11:38:41 CEST 2007
Tim Golden wrote:
> This -- just in case you haven't come across the expression --
> is called monkey-patching. It's a slightly general-purpose
> example of it, but it's something which is usefully easy
> to do in Python. (Consequently, it's easy to abuse but...)
Ah right - nice to know my dodgy hack is a member of a well known family :)
> Frankly, I never even thought of doing it. You may already
> have covered this, but it does have one or corner-cases
> you might want to consider. If one of your methods needs
> to completely cover one of the original ones *and* to call
> the original one as well (say to get the data you're going
> to wrap) then you have to do something a bit smarter than
> the straight __dict__.update you're doing there. Not very
> much harder, but you'd have to do it.
Yep - currently I'm just using it to add some basic convenience
functions (particularly __iter__, __getitem__, and the likes) so it's
not an issue. I suppose a slightly less naive technique would rename
conflicts first.
> > 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.
>
> Presumably, then, if the original COM class exposed,
> say, a .GetGroups method which returned a list of
> groups, each of which you wanted to wrap, in this
> implementation, you'd add a .MyGetGroups method which
> called the original and wrapped the result?
It's simpler than that: as long as you've monkey-patched the original
COM groups class, the groups returned by the GetGroups method will
already have your methods: no need to wrap.
Of course this presumes it's easy to find the Group class: my current
implementation assumes everything is in the same module, hence the
#find parent class of same name
parentclass = getattr(com_genpy_module,klass.__name__)
parentclass.__dict__.update(klass.__dict__)
If your com library returned com classes from another library (is that
even possible?) and hence used another genpy module then I suppose you'd
have more problems...
> Others may point out hidden flaws which I've missed,
> and I'll be glad to hear them, but if it works for
> you... :)
I've already come across some minor problems (not currently affecting me
too much but could become major headaches), mainly to do with existing
magic used by pythoncom:
1) Using your own attributes gets tricky as they pythoncom tries to
automatically assign them to the underlying com object. I've been
bypassing the __setattr__ override by doing "self.__dict__['spam'] =
'ham'" which would could get tedious rather quickly...
2) Defining your own __init__ causes all sorts of problems :)
3) You "take over" the com classes: that is, comclass.__class__ is your
class, not the original com_class: any kind on explicit introspection
(isinstance, etc.), within pythoncom or existing client code could now
fail. Again a less naive patching process that didn't overwrite
everything blindly should be easy.
-ross
More information about the Python-win32
mailing list