Skip to content

Commit b823fc6

Browse files
authored
Enhance ITypeInfo testing. (#884)
* test: Add test for `GetRefTypeOfImplType` with pure dispatch interfaces. This test verifies the behavior of `ITypeInfo.GetRefTypeOfImplType` when called on a pure dispatch interface. It asserts that a `COMError` with `TYPE_E_ELEMENTNOTFOUND` is raised, which also serves as further validation for the recently corrected HRESULT constant. * test: Add test for `GetRefTypeOfImplType` with custom interfaces. This adds another test for `ITypeInfo.GetRefTypeOfImplType`, this time using a custom interface. This expands test coverage and further validates that `COMError` with `TYPE_E_ELEMENTNOTFOUND` is correctly raised for invalid calls. * test: Add test for `GetRefTypeOfImplType` with dual interfaces. * refactor: Use qualified `typeinfo` constants and add `TYPEFLAG_FDUAL` assertions. Replaced direct imports of `TKIND_DISPATCH` and `TKIND_INTERFACE` with qualified references (e.g., `typeinfo.TKIND_DISPATCH`) for consistency within `test_typeinfo.py`. Additionally, added assertions for `TYPEFLAG_FDUAL` in the tests for pure dispatch and dual interfaces to more thoroughly verify interface flags, especially for dual interfaces. * refactor: Consolidate `hresult` import in `test_typeinfo.py`. The `comtypes.hresult` import was replaced with a direct import from `comtypes`, and usages were updated accordingly. This change improves consistency with other imports in the module. * refactor: Import `COMError` from `_ctypes` in `test_typeinfo.py`. To align with internal conventions, the import for `COMError` has been changed from `comtypes` to the more direct `_ctypes` module. * docs: Add comment with link to official documentation for `GetRefTypeOfImplType`.
1 parent bd1ed82 commit b823fc6

File tree

2 files changed

+41
-6
lines changed

2 files changed

+41
-6
lines changed

comtypes/test/test_typeinfo.py

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,11 @@
22
import os
33
import sys
44
import unittest
5+
from _ctypes import COMError
56
from ctypes.wintypes import MAX_PATH
67

7-
import comtypes.hresult
8-
from comtypes import GUID, COMError
8+
from comtypes import GUID, hresult, typeinfo
99
from comtypes.typeinfo import (
10-
TKIND_DISPATCH,
11-
TKIND_INTERFACE,
1210
GetModuleFileName,
1311
LoadRegTypeLib,
1412
LoadTypeLibEx,
@@ -69,7 +67,7 @@ def test_TypeInfo(self):
6967
c_tlib, c_index = ti.GetContainingTypeLib()
7068
self.assert_tlibattr_equal(c_tlib, tlib)
7169
self.assertEqual(c_index, index)
72-
if ta.typekind in (TKIND_INTERFACE, TKIND_DISPATCH):
70+
if ta.typekind in (typeinfo.TKIND_INTERFACE, typeinfo.TKIND_DISPATCH):
7371
if ta.cImplTypes:
7472
href = ti.GetRefTypeOfImplType(0)
7573
base = ti.GetRefTypeInfo(href)
@@ -87,7 +85,7 @@ def test_TypeInfo(self):
8785
guid_null = GUID()
8886
with self.assertRaises(COMError) as cm:
8987
tlib.GetTypeInfoOfGuid(guid_null)
90-
self.assertEqual(comtypes.hresult.TYPE_E_ELEMENTNOTFOUND, cm.exception.hresult)
88+
self.assertEqual(hresult.TYPE_E_ELEMENTNOTFOUND, cm.exception.hresult)
9189

9290
IID_IFile = GUID("{C7C3F5A4-88A3-11D0-ABCB-00A0C90FFFC0}")
9391
ti = tlib.GetTypeInfoOfGuid(IID_IFile)
@@ -97,6 +95,42 @@ def test_TypeInfo(self):
9795
self.assertEqual(c_ti, ti)
9896
self.assertEqual(IID_IFile, ti.GetTypeAttr().guid)
9997

98+
def test_pure_dispatch_ITypeInfo(self):
99+
tlib = LoadTypeLibEx("msi.dll")
100+
IID_Installer = GUID("{000C1090-0000-0000-C000-000000000046}")
101+
ti = tlib.GetTypeInfoOfGuid(IID_Installer)
102+
ta = ti.GetTypeAttr()
103+
self.assertEqual(ta.typekind, typeinfo.TKIND_DISPATCH)
104+
with self.assertRaises(COMError) as cm:
105+
ti.GetRefTypeOfImplType(-1)
106+
self.assertEqual(hresult.TYPE_E_ELEMENTNOTFOUND, cm.exception.hresult)
107+
self.assertFalse(ti.GetTypeAttr().wTypeFlags & typeinfo.TYPEFLAG_FDUAL)
108+
109+
def test_custom_interface_ITypeInfo(self):
110+
tlib = LoadTypeLibEx("UIAutomationCore.dll")
111+
IID_IUIAutomation = GUID("{30CBE57D-D9D0-452A-AB13-7AC5AC4825EE}")
112+
ti = tlib.GetTypeInfoOfGuid(IID_IUIAutomation)
113+
ta = ti.GetTypeAttr()
114+
self.assertEqual(ta.typekind, typeinfo.TKIND_INTERFACE)
115+
with self.assertRaises(COMError) as cm:
116+
ti.GetRefTypeOfImplType(-1)
117+
self.assertEqual(hresult.TYPE_E_ELEMENTNOTFOUND, cm.exception.hresult)
118+
self.assertFalse(ti.GetTypeAttr().wTypeFlags & typeinfo.TYPEFLAG_FDUAL)
119+
120+
def test_dual_interface_ITypeInfo(self):
121+
tlib = LoadTypeLibEx("scrrun.dll")
122+
IID_IDictionary = GUID("{42C642C1-97E1-11CF-978F-00A02463E06F}")
123+
ti = tlib.GetTypeInfoOfGuid(IID_IDictionary)
124+
ta = ti.GetTypeAttr()
125+
self.assertEqual(ta.typekind, typeinfo.TKIND_DISPATCH)
126+
self.assertTrue(ta.wTypeFlags & typeinfo.TYPEFLAG_FDUAL)
127+
refti = ti.GetRefTypeInfo(ti.GetRefTypeOfImplType(-1))
128+
refta = refti.GetTypeAttr()
129+
self.assertEqual(IID_IDictionary, refti.GetTypeAttr().guid)
130+
self.assertTrue(refta.wTypeFlags & typeinfo.TYPEFLAG_FDUAL)
131+
self.assertEqual(refta.typekind, typeinfo.TKIND_INTERFACE)
132+
self.assertEqual(ti, refti.GetRefTypeInfo(refti.GetRefTypeOfImplType(-1)))
133+
100134

101135
class Test_GetModuleFileName(unittest.TestCase):
102136
@unittest.skipUnless(

comtypes/tools/tlbparser.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -624,6 +624,7 @@ def parse_typeinfo(self, tinfo: typeinfo.ITypeInfo) -> Any:
624624
try:
625625
# GetRefTypeOfImplType(-1) returns the custom portion
626626
# of a dispinterface, if it is dual
627+
# See https://learn.microsoft.com/en-us/windows/win32/api/oaidl/nf-oaidl-itypeinfo-getreftypeofimpltype#remarks
627628
href = tinfo.GetRefTypeOfImplType(-1)
628629
except COMError:
629630
# no dual interface

0 commit comments

Comments
 (0)