Skip to content

Commit

Permalink
Make special __dunder__ methods work with CoClass (#1699)
Browse files Browse the repository at this point in the history
  • Loading branch information
mhammond committed May 30, 2021
1 parent f4798e0 commit 17fb589
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 3 deletions.
3 changes: 3 additions & 0 deletions CHANGES.txt
Expand Up @@ -8,6 +8,9 @@ Note that build 228 was the last version supporting Python 2.

Since build 300:
----------------
* CoClass objects should work better with special methods like __len__ etc.
(#1699)

* Creating a `win32crypt.CRYPT_ATTRIBUTE` object now correctly sets `cbData`.

* COM objects are now registered with the full path to pythoncomXX.dll, fixes
Expand Down
17 changes: 17 additions & 0 deletions com/win32com/client/__init__.py
Expand Up @@ -534,6 +534,23 @@ def __setattr__(self, attr, value):
pass
self.__dict__[attr] = value

# Special methods don't use __getattr__ etc, so explicitly delegate here.
# Some wrapped objects might not have them, but that's OK - the attribute
# error can just bubble up.
def __call__(self, *args, **kwargs):
return self.__dict__["_dispobj_"].__call__(*args, **kwargs)
def __str__(self, *args):
return self.__dict__["_dispobj_"].__str__(*args)
def __int__(self, *args):
return self.__dict__["_dispobj_"].__int__(*args)
def __iter__(self):
return self.__dict__["_dispobj_"].__iter__()
def __len__(self):
return self.__dict__["_dispobj_"].__len__()
def __nonzero__(self):
return self.__dict__["_dispobj_"].__nonzero__()


# A very simple VARIANT class. Only to be used with poorly-implemented COM
# objects. If an object accepts an arg which is a simple "VARIANT", but still
# is very pickly about the actual variant type (eg, isn't happy with a VT_I4,
Expand Down
2 changes: 1 addition & 1 deletion com/win32com/client/genpy.py
Expand Up @@ -607,7 +607,7 @@ def WriteClass(self, generator):
for item, flag in self.interfaces:
if flag & pythoncom.IMPLTYPEFLAG_FDEFAULT: # and dual:
defItem = item
# If we have written a class, refeence its name, otherwise the IID
# If we have written a class, reference its name, otherwise the IID
if item.bWritten: key = item.python_name
else: key = repr(str(item.clsid)) # really the iid.
print('\t\t%s,' % (key,), file=stream)
Expand Down
21 changes: 19 additions & 2 deletions com/win32com/test/testPyComTest.py
Expand Up @@ -172,10 +172,17 @@ def TestCommon(o, is_generated):
progress("Checking getting/passing IUnknown")
check_get_set(o.GetSetUnknown, o)
progress("Checking getting/passing IDispatch")
if not isinstance(o.GetSetDispatch(o), o.__class__):
# This might be called with either the interface or the CoClass - but these
# functions always return from the interface.
expected_class = o.__class__
# CoClass instances have `default_interface`
expected_class = getattr(expected_class, "default_interface", expected_class)
if not isinstance(o.GetSetDispatch(o), expected_class):
raise error("GetSetDispatch failed: %r" % (o.GetSetDispatch(o),))
progress("Checking getting/passing IDispatch of known type")
if o.GetSetInterface(o).__class__ != o.__class__:
expected_class = o.__class__
expected_class = getattr(expected_class, "default_interface", expected_class)
if o.GetSetInterface(o).__class__ != expected_class:
raise error("GetSetDispatch failed")

progress("Checking misc args")
Expand Down Expand Up @@ -408,6 +415,16 @@ def TestGenerated():
counter = EnsureDispatch("PyCOMTest.SimpleCounter")
TestCounter(counter, True)

# This dance lets us get a CoClass even though it's not explicitly registered.
# This is `CoPyComTest`
from win32com.client.CLSIDToClass import GetClass
coclass_o = GetClass("{8EE0C520-5605-11D0-AE5F-CADD4C000000}")()
TestCommon(coclass_o, True)

# This is `CoSimpleCounter` and the counter tests should work.
coclass = GetClass("{B88DD310-BAE8-11D0-AE86-76F2C1000000}")()
TestCounter(coclass, True)

# XXX - this is failing in dynamic tests, but should work fine.
i1, i2 = o.GetMultipleInterfaces()
if not isinstance(i1, DispatchBaseClass) or not isinstance(i2, DispatchBaseClass):
Expand Down

0 comments on commit 17fb589

Please sign in to comment.