Skip to content

Commit c072ff7

Browse files
committed
Fix special method handling regression for CoClass COM objects, fixed mhammond#1753
1 parent 867cb79 commit c072ff7

File tree

2 files changed

+21
-10
lines changed

2 files changed

+21
-10
lines changed

com/win32com/client/__init__.py

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -515,7 +515,12 @@ def _get_good_object_(obj, obUserName=None, resultCLSID=None):
515515
class CoClassBaseClass:
516516
def __init__(self, oobj=None):
517517
if oobj is None: oobj = pythoncom.new(self.CLSID)
518-
self.__dict__["_dispobj_"] = self.default_interface(oobj)
518+
dispobj = self.__dict__["_dispobj_"] = self.default_interface(oobj)
519+
# See comments below re the special methods.
520+
for maybe in ["__call__", "__str__", "__int__", "__iter__", "__len__", "__nonzero__"]:
521+
if hasattr(dispobj, maybe):
522+
setattr(self, maybe, getattr(self, "__maybe" + maybe))
523+
519524
def __repr__(self):
520525
return "<win32com.gen_py.%s.%s>" % (__doc__, self.__class__.__name__)
521526

@@ -535,22 +540,25 @@ def __setattr__(self, attr, value):
535540
self.__dict__[attr] = value
536541

537542
# Special methods don't use __getattr__ etc, so explicitly delegate here.
538-
# Some wrapped objects might not have them, but that's OK - the attribute
539-
# error can just bubble up.
540-
def __call__(self, *args, **kwargs):
543+
# Note however, that not all are safe to let bubble up - things like
544+
# `bool(ob)` will break if the object defines __int__ but then raises an
545+
# attribute error - eg, see #1753.
546+
# It depends on what the wrapped COM object actually defines whether these
547+
# will exist on the underlying object, so __init__ explicitly checks if they
548+
# do and if so, wires them up.
549+
def __maybe__call__(self, *args, **kwargs):
541550
return self.__dict__["_dispobj_"].__call__(*args, **kwargs)
542-
def __str__(self, *args):
551+
def __maybe__str__(self, *args):
543552
return self.__dict__["_dispobj_"].__str__(*args)
544-
def __int__(self, *args):
553+
def __maybe__int__(self, *args):
545554
return self.__dict__["_dispobj_"].__int__(*args)
546-
def __iter__(self):
555+
def __maybe__iter__(self):
547556
return self.__dict__["_dispobj_"].__iter__()
548-
def __len__(self):
557+
def __maybe__len__(self):
549558
return self.__dict__["_dispobj_"].__len__()
550-
def __nonzero__(self):
559+
def __maybe__nonzero__(self):
551560
return self.__dict__["_dispobj_"].__nonzero__()
552561

553-
554562
# A very simple VARIANT class. Only to be used with poorly-implemented COM
555563
# objects. If an object accepts an arg which is a simple "VARIANT", but still
556564
# is very pickly about the actual variant type (eg, isn't happy with a VT_I4,

com/win32com/test/testPyComTest.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,9 @@ def TestGenerated():
421421
coclass_o = GetClass("{8EE0C520-5605-11D0-AE5F-CADD4C000000}")()
422422
TestCommon(coclass_o, True)
423423

424+
# Test the regression reported in #1753
425+
assert(bool(coclass_o))
426+
424427
# This is `CoSimpleCounter` and the counter tests should work.
425428
coclass = GetClass("{B88DD310-BAE8-11D0-AE86-76F2C1000000}")()
426429
TestCounter(coclass, True)

0 commit comments

Comments
 (0)