diff --git a/comtypes/_post_coinit/misc.py b/comtypes/_post_coinit/misc.py index 1607f80b..e2c92108 100644 --- a/comtypes/_post_coinit/misc.py +++ b/comtypes/_post_coinit/misc.py @@ -142,24 +142,20 @@ def CoCreateInstance( return p # type: ignore -if TYPE_CHECKING: - - @overload - def CoGetClassObject( - clsid: GUID, - clsctx: Optional[int] = None, - pServerInfo: "Optional[COSERVERINFO]" = None, - interface: None = None, - ) -> hints.IClassFactory: ... - @overload - def CoGetClassObject( - clsid: GUID, - clsctx: Optional[int] = None, - pServerInfo: "Optional[COSERVERINFO]" = None, - interface: type[_T_IUnknown] = hints.IClassFactory, - ) -> _T_IUnknown: ... - - +@overload +def CoGetClassObject( + clsid: GUID, + clsctx: Optional[int] = None, + pServerInfo: "Optional[COSERVERINFO]" = None, + interface: None = None, +) -> "hints.IClassFactory": ... +@overload +def CoGetClassObject( + clsid: GUID, + clsctx: Optional[int] = None, + pServerInfo: "Optional[COSERVERINFO]" = None, + interface: type[_T_IUnknown] = IUnknown, +) -> _T_IUnknown: ... def CoGetClassObject( clsid: GUID, clsctx: Optional[int] = None, diff --git a/comtypes/client/_create.py b/comtypes/client/_create.py index 9a0a72bd..8ac9fc18 100644 --- a/comtypes/client/_create.py +++ b/comtypes/client/_create.py @@ -19,26 +19,26 @@ # # Object creation # -if TYPE_CHECKING: - - @overload - def GetClassObject( - progid: _UnionT[str, type[CoClass], GUID], - clsctx: Optional[int] = None, - pServerInfo: Optional[COSERVERINFO] = None, - interface: None = None, - ) -> hints.IClassFactory: ... - @overload - def GetClassObject( - progid: _UnionT[str, type[CoClass], GUID], - clsctx: Optional[int] = None, - pServerInfo: Optional[COSERVERINFO] = None, - interface: type[_T_IUnknown] = hints.IClassFactory, - ) -> _T_IUnknown: ... - - -def GetClassObject(progid, clsctx=None, pServerInfo=None, interface=None): - # type: (_UnionT[str, type[CoClass], GUID], Optional[int], Optional[COSERVERINFO], Optional[type[IUnknown]]) -> IUnknown +@overload +def GetClassObject( + progid: _UnionT[str, type[CoClass], GUID], + clsctx: Optional[int] = None, + pServerInfo: Optional[COSERVERINFO] = None, + interface: None = None, +) -> "hints.IClassFactory": ... +@overload +def GetClassObject( + progid: _UnionT[str, type[CoClass], GUID], + clsctx: Optional[int] = None, + pServerInfo: Optional[COSERVERINFO] = None, + interface: type[_T_IUnknown] = IUnknown, +) -> _T_IUnknown: ... +def GetClassObject( + progid: _UnionT[str, type[CoClass], GUID], + clsctx: Optional[int] = None, + pServerInfo: Optional[COSERVERINFO] = None, + interface: Optional[type[IUnknown]] = None, +) -> IUnknown: """Create and return the class factory for a COM object. 'clsctx' specifies how to create the object, use the CLSCTX_... constants. diff --git a/comtypes/test/test_classfactory.py b/comtypes/test/test_classfactory.py index 5bd247dd..05c291f4 100644 --- a/comtypes/test/test_classfactory.py +++ b/comtypes/test/test_classfactory.py @@ -1,11 +1,13 @@ import unittest as ut +import comtypes.client from comtypes import GUID, CoGetClassObject, IUnknown, shelllink from comtypes.server import IClassFactory CLSID_ShellLink = GUID("{00021401-0000-0000-C000-000000000046}") REGDB_E_CLASSNOTREG = -2147221164 # 0x80040154 +HKCU = 1 # HKEY_CURRENT_USER class Test_CreateInstance(ut.TestCase): @@ -27,6 +29,25 @@ def test_returns_iunknown_type_instance(self): shlnk.SetDescription("sample") self.assertEqual(shlnk.GetDescription(), "sample") + def test_returns_lazybind_dynamic_dispatch_if_typeinfo_is_available(self): + # When `dynamic=True`, objects providing type information will return a + # `lazybind.Dispatch` instance. + class_factory = comtypes.client.GetClassObject("Scripting.Dictionary") + self.assertIsInstance(class_factory, IClassFactory) + dic = class_factory.CreateInstance(dynamic=True) + self.assertIsInstance(dic, comtypes.client.lazybind.Dispatch) + dic.Item["key"] = "value" + self.assertEqual(dic.Item["key"], "value") + + def test_returns_fully_dynamic_dispatch_if_typeinfo_is_unavailable(self): + # When `dynamic=True`, objects that do NOT provide type information (or + # fail to provide it) will return a `dynamic._Dispatch` instance. + class_factory = comtypes.client.GetClassObject("WindowsInstaller.Installer") + self.assertIsInstance(class_factory, IClassFactory) + inst = class_factory.CreateInstance(dynamic=True) + self.assertIsInstance(inst, comtypes.client.dynamic._Dispatch) + self.assertTrue(inst.RegistryValue(HKCU, r"Control Panel\Desktop")) + def test_raises_valueerror_if_takes_dynamic_true_and_interface_explicitly(self): class_factory = CoGetClassObject(CLSID_ShellLink) self.assertIsInstance(class_factory, IClassFactory)