From b29c581610c8d4a6e258b7a50fe639b7b02a67d9 Mon Sep 17 00:00:00 2001 From: junkmd Date: Sat, 21 Feb 2026 12:37:05 +0900 Subject: [PATCH 1/2] test: Add error reporting tests for custom COMObject implementations. - Add `Test_CustomImplementation` to `test_comobject.py`. - Verify that `ReportError` correctly raises `COMError` with expected `hresult` and `details` for custom `COMObject` methods. --- comtypes/test/test_comobject.py | 58 +++++++++++++++++++++++++++++++-- 1 file changed, 56 insertions(+), 2 deletions(-) diff --git a/comtypes/test/test_comobject.py b/comtypes/test/test_comobject.py index bf8b7426..72228a12 100644 --- a/comtypes/test/test_comobject.py +++ b/comtypes/test/test_comobject.py @@ -1,12 +1,15 @@ import ctypes import unittest as ut -from ctypes import POINTER, byref, pointer +from _ctypes import COMError +from ctypes import POINTER, FormatError, byref, pointer from unittest import mock import comtypes.client -from comtypes import CLSCTX_SERVER, COMObject, IPersist, IUnknown, hresult +from comtypes import CLSCTX_SERVER, GUID, COMObject, IPersist, IUnknown, hresult from comtypes._post_coinit.misc import _CoCreateInstance from comtypes.automation import IDispatch +from comtypes.errorinfo import ReportError +from comtypes.server import IClassFactory from comtypes.typeinfo import GUIDKIND_DEFAULT_SOURCE_DISP_IID comtypes.client.GetModule("UIAutomationCore.dll") @@ -157,3 +160,54 @@ def test_com_pointers(self): self.assertNotIn(IDispatch._iid_, cuia._com_pointers_) self.assertIn(stdole.IPictureDisp._iid_, stdpic._com_pointers_) self.assertIn(uiac.IUIAutomation._iid_, cuia._com_pointers_) + + +class Test_CustomImplementation(ut.TestCase): + def test_raises_comerror(self): + ERR_DESC = "Simulated COMError" + ERR_HELPFILE = "test.hlp" + ERR_HELPCTX = 42 + + class MyClassFactory(COMObject): + _com_interfaces_ = [IClassFactory] + + def CreateInstance(self, this, punkOuter, riid, ppv): + return ReportError( + f"{ERR_DESC}: CreateInstance", + IClassFactory._iid_, + GUID.create_new(), + ERR_HELPFILE, + ERR_HELPCTX, + hresult.E_UNEXPECTED, + ) + + def LockServer(self, this, fLock): + return ReportError( + f"{ERR_DESC}: LockServer", + IClassFactory._iid_, + GUID.create_new(), + ERR_HELPFILE, + ERR_HELPCTX, + hresult.E_FAIL, + ) + + # Get a COM pointer to the interface of our custom object. + cf = MyClassFactory().QueryInterface(IClassFactory) + # calling `LockServer` + with self.assertRaises(COMError) as cm: + cf.CreateInstance(interface=IUnknown) + self.assertEqual(cm.exception.hresult, hresult.E_UNEXPECTED) + self.assertEqual(cm.exception.text, FormatError(hresult.E_UNEXPECTED)) + self.assertEqual( + cm.exception.details, + (f"{ERR_DESC}: CreateInstance", None, ERR_HELPFILE, ERR_HELPCTX, None), + ) + # calling `LockServer` + with self.assertRaises(COMError) as cm: + cf.LockServer(True) + self.assertEqual(cm.exception.hresult, hresult.E_FAIL) + self.assertEqual(cm.exception.text, FormatError(hresult.E_FAIL)) + self.assertEqual( + cm.exception.details, + (f"{ERR_DESC}: LockServer", None, ERR_HELPFILE, ERR_HELPCTX, None), + ) From 2492adb554aba37cad80282adcfa0e0bbd59aa7b Mon Sep 17 00:00:00 2001 From: Jun Komoda <45822440+junkmd@users.noreply.github.com> Date: Sat, 21 Feb 2026 13:50:14 +0900 Subject: [PATCH 2/2] refactor: Replace `clsid` with a class variable. --- comtypes/test/test_comobject.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/comtypes/test/test_comobject.py b/comtypes/test/test_comobject.py index 72228a12..811429a9 100644 --- a/comtypes/test/test_comobject.py +++ b/comtypes/test/test_comobject.py @@ -170,12 +170,13 @@ def test_raises_comerror(self): class MyClassFactory(COMObject): _com_interfaces_ = [IClassFactory] + _reg_clsid_ = GUID.create_new() def CreateInstance(self, this, punkOuter, riid, ppv): return ReportError( f"{ERR_DESC}: CreateInstance", IClassFactory._iid_, - GUID.create_new(), + self._reg_clsid_, ERR_HELPFILE, ERR_HELPCTX, hresult.E_UNEXPECTED, @@ -185,7 +186,7 @@ def LockServer(self, this, fLock): return ReportError( f"{ERR_DESC}: LockServer", IClassFactory._iid_, - GUID.create_new(), + self._reg_clsid_, ERR_HELPFILE, ERR_HELPCTX, hresult.E_FAIL,