comtypes 1.4.10__zip → 1.4.12__zip
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {comtypes-1.4.10 → comtypes-1.4.12}/CHANGES.txt +48 -0
- {comtypes-1.4.10/comtypes.egg-info → comtypes-1.4.12}/PKG-INFO +4 -3
- {comtypes-1.4.10 → comtypes-1.4.12}/README.md +1 -1
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/__init__.py +11 -5
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/_comobject.py +29 -31
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/_memberspec.py +107 -81
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/_meta.py +1 -1
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/_npsupport.py +12 -17
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/_post_coinit/_cominterface_meta_patcher.py +8 -10
- comtypes-1.4.12/comtypes/_post_coinit/activeobj.py +61 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/_post_coinit/misc.py +1 -23
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/_post_coinit/unknwn.py +33 -26
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/_vtbl.py +55 -58
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/automation.py +19 -23
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/client/__init__.py +2 -1
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/client/_activeobj.py +8 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/client/_code_cache.py +10 -24
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/client/_constants.py +1 -1
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/client/_events.py +92 -54
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/client/_generate.py +1 -3
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/client/dynamic.py +3 -3
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/client/lazybind.py +3 -3
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/connectionpoints.py +37 -3
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/errorinfo.py +54 -16
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/hints.pyi +15 -2
- comtypes-1.4.12/comtypes/hresult.py +159 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/messageloop.py +15 -13
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/patcher.py +2 -2
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/persist.py +9 -2
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/safearray.py +10 -10
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/server/__init__.py +5 -37
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/server/automation.py +2 -2
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/server/connectionpoints.py +71 -70
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/server/inprocserver.py +10 -7
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/server/localserver.py +16 -22
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/server/register.py +7 -7
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_GUID.py +6 -7
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_agilent.py +1 -1
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_basic.py +6 -3
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_client_dynamic.py +1 -1
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_collections.py +6 -3
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_comobject.py +19 -6
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_comserver.py +32 -4
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_createwrappers.py +1 -1
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_dict.py +2 -1
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_dispifc_records.py +0 -2
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_dispifc_safearrays.py +0 -2
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_dispinterface.py +1 -1
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_dyndispatch.py +4 -2
- comtypes-1.4.12/comtypes/test/test_errorinfo.py +115 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_excel.py +1 -3
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_getactiveobj.py +19 -2
- comtypes-1.4.12/comtypes/test/test_hresult.py +87 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_inout_args.py +9 -2
- comtypes-1.4.12/comtypes/test/test_messageloop.py +117 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_midl_safearray_create.py +0 -2
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_msscript.py +1 -1
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_npsupport.py +22 -11
- comtypes-1.4.12/comtypes/test/test_persist.py +71 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_recordinfo.py +0 -2
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_safearray.py +2 -1
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_server.py +6 -6
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_server_register.py +2 -1
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_storage.py +1 -1
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_stream.py +22 -2
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_typeinfo.py +19 -2
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_urlhistory.py +1 -1
- comtypes-1.4.12/comtypes/test/test_util.py +227 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_variant.py +43 -25
- comtypes-1.4.12/comtypes/test/test_viewobject.py +78 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_w_getopt.py +4 -4
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_word.py +1 -1
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/tools/codegenerator/codegenerator.py +1 -1
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/tools/codegenerator/comments.py +1 -1
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/tools/codegenerator/heads.py +5 -5
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/tools/codegenerator/helpers.py +7 -7
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/tools/codegenerator/namespaces.py +3 -3
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/tools/codegenerator/typeannotator.py +2 -2
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/tools/tlbparser.py +8 -7
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/tools/typedesc.py +14 -14
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/tools/typedesc_base.py +19 -19
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/typeinfo.py +14 -9
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/util.py +38 -6
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/viewobject.py +29 -5
- {comtypes-1.4.10 → comtypes-1.4.12/comtypes.egg-info}/PKG-INFO +4 -3
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes.egg-info/SOURCES.txt +6 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/pyproject.toml +13 -7
- comtypes-1.4.10/comtypes/hresult.py +0 -81
- comtypes-1.4.10/comtypes/test/test_persist.py +0 -38
- {comtypes-1.4.10 → comtypes-1.4.12}/LICENSE.txt +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/MANIFEST.in +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/GUID.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/_post_coinit/__init__.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/_post_coinit/bstr.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/_post_coinit/instancemethod.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/_safearray.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/_tlib_version_checker.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/clear_cache.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/client/_create.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/client/_managing.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/git.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/logutil.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/server/w_getopt.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/shelllink.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/stream.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/TestComServer.idl +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/TestComServer.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/TestComServer.tlb +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/TestDispServer.idl +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/TestDispServer.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/TestDispServer.tlb +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/__init__.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/find_memleak.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/mylib.idl +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/mylib.tlb +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/mytypelib.idl +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/runtests.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/setup.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_BSTR.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_DISPPARAMS.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_QueryService.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_avmc.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_casesensitivity.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_clear_cache.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_client.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_client_regenerate_modules.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_findgendir.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_ie.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_ienum.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_imfattributes.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_jscript.js +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_monikers.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_outparam.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_pump_events.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_sapi.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_shelllink.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_showevents.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_subinterface.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_typeannotator.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_win32com_interop.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_wmi.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/urlhist.tlb +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/tools/__init__.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/tools/codegenerator/__init__.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/tools/codegenerator/modulenamer.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/tools/codegenerator/packing.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes.egg-info/dependency_links.txt +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes.egg-info/entry_points.txt +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes.egg-info/top_level.txt +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/setup.cfg +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/setup.py +0 -0
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import ctypes
|
|
2
1
|
import logging
|
|
3
2
|
import sys
|
|
4
3
|
import winreg
|
|
4
|
+
from ctypes import c_void_p, pointer
|
|
5
5
|
from typing import TYPE_CHECKING, Any, Literal, Optional, Type
|
|
6
6
|
|
|
7
7
|
from comtypes import GUID, COMObject, IUnknown, hresult
|
|
8
|
+
from comtypes._comobject import InprocServer as _InprocRefCounter
|
|
8
9
|
from comtypes.server import IClassFactory
|
|
9
10
|
|
|
10
11
|
if TYPE_CHECKING:
|
|
@@ -21,7 +22,7 @@ class ClassFactory(COMObject):
|
|
|
21
22
|
_com_interfaces_ = [IClassFactory]
|
|
22
23
|
|
|
23
24
|
def __init__(self, cls: Type[COMObject]) -> None:
|
|
24
|
-
super(
|
|
25
|
+
super().__init__()
|
|
25
26
|
self._cls = cls
|
|
26
27
|
|
|
27
28
|
def IClassFactory_CreateInstance(
|
|
@@ -29,7 +30,7 @@ class ClassFactory(COMObject):
|
|
|
29
30
|
this: Any,
|
|
30
31
|
punkOuter: Optional[Type["_Pointer[IUnknown]"]],
|
|
31
32
|
riid: "_Pointer[GUID]",
|
|
32
|
-
ppv:
|
|
33
|
+
ppv: c_void_p,
|
|
33
34
|
) -> int:
|
|
34
35
|
_debug("ClassFactory.CreateInstance(%s)", riid[0])
|
|
35
36
|
result = self._cls().IUnknown_QueryInterface(None, riid, ppv)
|
|
@@ -37,6 +38,7 @@ class ClassFactory(COMObject):
|
|
|
37
38
|
return result
|
|
38
39
|
|
|
39
40
|
def IClassFactory_LockServer(self, this: Any, fLock: bool) -> Literal[0]:
|
|
41
|
+
assert COMObject.__server__ is not None, "The inprocserver is not running yet"
|
|
40
42
|
if fLock:
|
|
41
43
|
COMObject.__server__.Lock()
|
|
42
44
|
else:
|
|
@@ -58,7 +60,7 @@ def inproc_find_class(clsid: GUID) -> Type[COMObject]:
|
|
|
58
60
|
except:
|
|
59
61
|
_debug("NO path to insert")
|
|
60
62
|
else:
|
|
61
|
-
if not
|
|
63
|
+
if pathdir not in sys.path:
|
|
62
64
|
sys.path.insert(0, str(pathdir))
|
|
63
65
|
_debug("insert path %r", pathdir)
|
|
64
66
|
else:
|
|
@@ -90,7 +92,7 @@ def _setup_logging(clsid: GUID) -> None:
|
|
|
90
92
|
|
|
91
93
|
try:
|
|
92
94
|
hkey = winreg.OpenKey(winreg.HKEY_CLASSES_ROOT, r"CLSID\%s\Logging" % clsid)
|
|
93
|
-
except
|
|
95
|
+
except OSError:
|
|
94
96
|
return
|
|
95
97
|
from comtypes.logutil import NTDebugHandler
|
|
96
98
|
|
|
@@ -138,7 +140,7 @@ def DllGetClassObject(rclsid: int, riid: int, ppv: int) -> int:
|
|
|
138
140
|
return hresult.CLASS_E_CLASSNOTAVAILABLE
|
|
139
141
|
|
|
140
142
|
result = ClassFactory(cls).IUnknown_QueryInterface(
|
|
141
|
-
None,
|
|
143
|
+
None, pointer(iid), c_void_p(ppv)
|
|
142
144
|
)
|
|
143
145
|
_debug("DllGetClassObject() -> %s", result)
|
|
144
146
|
return result
|
|
@@ -149,7 +151,8 @@ def DllGetClassObject(rclsid: int, riid: int, ppv: int) -> int:
|
|
|
149
151
|
|
|
150
152
|
def DllCanUnloadNow() -> Literal[1]: # S_FALSE
|
|
151
153
|
COMObject.__run_inprocserver__()
|
|
152
|
-
|
|
154
|
+
assert isinstance(COMObject.__server__, _InprocRefCounter)
|
|
155
|
+
result = COMObject.__server__.DllCanUnloadNow() # noqa
|
|
153
156
|
# To avoid a memory leak when PyInitialize()/PyUninitialize() are
|
|
154
157
|
# called several times, we refuse to unload the dll.
|
|
155
158
|
return hresult.S_FALSE
|
|
@@ -1,18 +1,12 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
import queue
|
|
3
|
-
from ctypes import
|
|
4
|
-
HRESULT,
|
|
5
|
-
POINTER,
|
|
6
|
-
OleDLL,
|
|
7
|
-
byref,
|
|
8
|
-
c_ulong,
|
|
9
|
-
c_void_p,
|
|
10
|
-
)
|
|
3
|
+
from ctypes import HRESULT, OleDLL, byref, c_ulong, c_void_p
|
|
11
4
|
from ctypes.wintypes import DWORD, LPDWORD
|
|
12
5
|
from typing import TYPE_CHECKING, Any, Literal, Optional, Sequence, Type
|
|
13
6
|
|
|
14
7
|
import comtypes
|
|
15
|
-
from comtypes import GUID, hresult
|
|
8
|
+
from comtypes import GUID, COMObject, IUnknown, hresult
|
|
9
|
+
from comtypes.GUID import REFCLSID
|
|
16
10
|
from comtypes.server import IClassFactory
|
|
17
11
|
|
|
18
12
|
if TYPE_CHECKING:
|
|
@@ -30,7 +24,6 @@ REGCLS_SURROGATE = 8 # must be used when a surrogate process
|
|
|
30
24
|
|
|
31
25
|
_ole32 = OleDLL("ole32")
|
|
32
26
|
|
|
33
|
-
REFCLSID = POINTER(GUID)
|
|
34
27
|
_CoRegisterClassObject = _ole32.CoRegisterClassObject
|
|
35
28
|
_CoRegisterClassObject.argtypes = [REFCLSID, c_void_p, DWORD, DWORD, LPDWORD]
|
|
36
29
|
_CoRegisterClassObject.restype = HRESULT
|
|
@@ -40,19 +33,19 @@ _CoRevokeClassObject.argtypes = [DWORD]
|
|
|
40
33
|
_CoRevokeClassObject.restype = HRESULT
|
|
41
34
|
|
|
42
35
|
|
|
43
|
-
def run(classes: Sequence[Type[
|
|
36
|
+
def run(classes: Sequence[Type[COMObject]]) -> None:
|
|
44
37
|
classobjects = [ClassFactory(cls) for cls in classes]
|
|
45
|
-
|
|
38
|
+
COMObject.__run_localserver__(classobjects)
|
|
46
39
|
|
|
47
40
|
|
|
48
|
-
class ClassFactory(
|
|
41
|
+
class ClassFactory(COMObject):
|
|
49
42
|
_com_interfaces_ = [IClassFactory]
|
|
50
43
|
_locks: int = 0
|
|
51
44
|
_queue: Optional[queue.Queue] = None
|
|
52
45
|
regcls: int = REGCLS_MULTIPLEUSE
|
|
53
46
|
|
|
54
|
-
def __init__(self, cls: Type[
|
|
55
|
-
super(
|
|
47
|
+
def __init__(self, cls: Type[COMObject], *args, **kw) -> None:
|
|
48
|
+
super().__init__()
|
|
56
49
|
self._cls = cls
|
|
57
50
|
self._register_class()
|
|
58
51
|
self._args = args
|
|
@@ -67,11 +60,11 @@ class ClassFactory(comtypes.COMObject):
|
|
|
67
60
|
def _register_class(self) -> None:
|
|
68
61
|
regcls = getattr(self._cls, "_regcls_", self.regcls)
|
|
69
62
|
cookie = c_ulong()
|
|
70
|
-
ptr = self._com_pointers_[
|
|
71
|
-
clsctx = self._cls._reg_clsctx_
|
|
63
|
+
ptr = self._com_pointers_[IUnknown._iid_]
|
|
64
|
+
clsctx = self._cls._reg_clsctx_ # type: ignore
|
|
72
65
|
clsctx &= ~comtypes.CLSCTX_INPROC # reset the inproc flags
|
|
73
66
|
_CoRegisterClassObject(
|
|
74
|
-
byref(
|
|
67
|
+
byref(GUID(self._cls._reg_clsid_)),
|
|
75
68
|
ptr,
|
|
76
69
|
clsctx,
|
|
77
70
|
regcls,
|
|
@@ -85,8 +78,8 @@ class ClassFactory(comtypes.COMObject):
|
|
|
85
78
|
def CreateInstance(
|
|
86
79
|
self,
|
|
87
80
|
this: Any,
|
|
88
|
-
punkOuter: Optional[Type["_Pointer[
|
|
89
|
-
riid: "_Pointer[
|
|
81
|
+
punkOuter: Optional[Type["_Pointer[IUnknown]"]],
|
|
82
|
+
riid: "_Pointer[GUID]",
|
|
90
83
|
ppv: c_void_p,
|
|
91
84
|
) -> int:
|
|
92
85
|
_debug("ClassFactory.CreateInstance(%s)", riid[0])
|
|
@@ -96,8 +89,9 @@ class ClassFactory(comtypes.COMObject):
|
|
|
96
89
|
return result
|
|
97
90
|
|
|
98
91
|
def LockServer(self, this: Any, fLock: bool) -> Literal[0]:
|
|
92
|
+
assert COMObject.__server__ is not None, "The localserver is not running yet"
|
|
99
93
|
if fLock:
|
|
100
|
-
|
|
94
|
+
COMObject.__server__.Lock()
|
|
101
95
|
else:
|
|
102
|
-
|
|
96
|
+
COMObject.__server__.Unlock()
|
|
103
97
|
return hresult.S_OK
|
|
@@ -43,7 +43,7 @@ import os
|
|
|
43
43
|
import sys
|
|
44
44
|
import winreg
|
|
45
45
|
from ctypes import WinDLL, WinError
|
|
46
|
-
from ctypes.wintypes import HKEY, LONG, LPCWSTR
|
|
46
|
+
from ctypes.wintypes import HKEY, LONG, LPCWSTR, MAX_PATH
|
|
47
47
|
from typing import Iterable, Iterator, List, Optional, Tuple, Type, Union
|
|
48
48
|
from winreg import HKEY_CLASSES_ROOT as HKCR
|
|
49
49
|
from winreg import HKEY_CURRENT_USER as HKCU
|
|
@@ -105,7 +105,7 @@ def _delete_key(hkey: int, subkey: str, *, force: bool) -> None:
|
|
|
105
105
|
else:
|
|
106
106
|
_debug("DeleteKey %s\\%s", _explain(hkey), subkey)
|
|
107
107
|
winreg.DeleteKey(hkey, subkey)
|
|
108
|
-
except
|
|
108
|
+
except OSError as detail:
|
|
109
109
|
if get_winerror(detail) != 2:
|
|
110
110
|
raise
|
|
111
111
|
|
|
@@ -113,7 +113,7 @@ def _delete_key(hkey: int, subkey: str, *, force: bool) -> None:
|
|
|
113
113
|
_Entry = Tuple[int, str, str, str]
|
|
114
114
|
|
|
115
115
|
|
|
116
|
-
class Registrar
|
|
116
|
+
class Registrar:
|
|
117
117
|
"""COM class registration.
|
|
118
118
|
|
|
119
119
|
The COM class can override what this does by implementing
|
|
@@ -142,7 +142,7 @@ class Registrar(object):
|
|
|
142
142
|
_debug('DeleteKey( %s\\CLSID\\%s\\Logging"' % (_explain(HKCR), clsid))
|
|
143
143
|
hkey = winreg.OpenKey(HKCR, rf"CLSID\{clsid}")
|
|
144
144
|
winreg.DeleteKey(hkey, "Logging")
|
|
145
|
-
except
|
|
145
|
+
except OSError as detail:
|
|
146
146
|
if get_winerror(detail) != 2:
|
|
147
147
|
raise
|
|
148
148
|
|
|
@@ -166,7 +166,7 @@ class Registrar(object):
|
|
|
166
166
|
_debug("DeleteValue(format)")
|
|
167
167
|
try:
|
|
168
168
|
winreg.DeleteValue(hkey, "format")
|
|
169
|
-
except
|
|
169
|
+
except OSError as detail:
|
|
170
170
|
if get_winerror(detail) != 2:
|
|
171
171
|
raise
|
|
172
172
|
|
|
@@ -231,7 +231,7 @@ class Registrar(object):
|
|
|
231
231
|
try:
|
|
232
232
|
_debug("UnRegisterTypeLib(%s, %s, %s)", *tlib)
|
|
233
233
|
UnRegisterTypeLib(*tlib)
|
|
234
|
-
except
|
|
234
|
+
except OSError as detail:
|
|
235
235
|
if not get_winerror(detail) in (
|
|
236
236
|
TYPE_E_REGISTRYACCESS,
|
|
237
237
|
TYPE_E_CANTLOADLIBRARY,
|
|
@@ -242,7 +242,7 @@ class Registrar(object):
|
|
|
242
242
|
|
|
243
243
|
def _get_serverdll(handle: int) -> str:
|
|
244
244
|
"""Return the pathname of the dll hosting the COM object."""
|
|
245
|
-
return GetModuleFileName(handle,
|
|
245
|
+
return GetModuleFileName(handle, MAX_PATH)
|
|
246
246
|
|
|
247
247
|
|
|
248
248
|
class RegistryEntries(abc.ABC):
|
|
@@ -30,25 +30,24 @@ class Test(unittest.TestCase):
|
|
|
30
30
|
)
|
|
31
31
|
|
|
32
32
|
def test_invalid_constructor_arg(self):
|
|
33
|
-
self.assertRaises(WindowsError
|
|
33
|
+
with self.assertRaises(WindowsError):
|
|
34
|
+
GUID("abc")
|
|
34
35
|
|
|
35
36
|
def test_from_progid(self):
|
|
36
37
|
self.assertEqual(
|
|
37
38
|
GUID.from_progid("Scripting.FileSystemObject"),
|
|
38
39
|
GUID("{0D43FE01-F093-11CF-8940-00A0C9054228}"),
|
|
39
40
|
)
|
|
40
|
-
self.assertRaises(WindowsError
|
|
41
|
+
with self.assertRaises(WindowsError):
|
|
42
|
+
GUID.from_progid("abc")
|
|
41
43
|
|
|
42
44
|
def test_as_progid(self):
|
|
43
45
|
self.assertEqual(
|
|
44
46
|
GUID("{0D43FE01-F093-11CF-8940-00A0C9054228}").as_progid(),
|
|
45
47
|
"Scripting.FileSystemObject",
|
|
46
48
|
)
|
|
47
|
-
self.assertRaises(
|
|
48
|
-
|
|
49
|
-
lambda guid: guid.as_progid(),
|
|
50
|
-
GUID("{00000000-0000-0000-C000-000000000046}"),
|
|
51
|
-
)
|
|
49
|
+
with self.assertRaises(WindowsError):
|
|
50
|
+
GUID("{00000000-0000-0000-C000-000000000046}").as_progid()
|
|
52
51
|
|
|
53
52
|
def test_create_new(self):
|
|
54
53
|
self.assertNotEqual(GUID.create_new(), GUID.create_new())
|
|
@@ -61,7 +61,8 @@ class BasicTest(ut.TestCase):
|
|
|
61
61
|
self.assertEqual(method_count(IMyInterface), 3)
|
|
62
62
|
|
|
63
63
|
# assigning _methods_ does not work until we have an _iid_!
|
|
64
|
-
self.assertRaises(AttributeError
|
|
64
|
+
with self.assertRaises(AttributeError):
|
|
65
|
+
setattr(IMyInterface, "_methods_", [])
|
|
65
66
|
IMyInterface._iid_ = GUID.create_new()
|
|
66
67
|
IMyInterface._methods_ = []
|
|
67
68
|
self.assertEqual(method_count(IMyInterface), 3)
|
|
@@ -96,9 +97,11 @@ class BasicTest(ut.TestCase):
|
|
|
96
97
|
_iid_ = GUID.create_new()
|
|
97
98
|
|
|
98
99
|
# We cannot assign _methods_ to IDerived before IBase has it's _methods_:
|
|
99
|
-
self.assertRaises(TypeError
|
|
100
|
+
with self.assertRaises(TypeError):
|
|
101
|
+
setattr(IDerived, "_methods_", [])
|
|
100
102
|
# Make sure that setting _methods_ failed completely.
|
|
101
|
-
self.assertRaises(KeyError
|
|
103
|
+
with self.assertRaises(KeyError):
|
|
104
|
+
IDerived.__dict__["_methods_"]
|
|
102
105
|
IBase._methods_ = []
|
|
103
106
|
# Now it works:
|
|
104
107
|
IDerived._methods_ = []
|
|
@@ -26,7 +26,7 @@ class Test_Dispatch_Function(ut.TestCase):
|
|
|
26
26
|
|
|
27
27
|
def test_returns_dynamic_Dispatch_if_takes_ptrIDispatch_and_raised_winerr(self):
|
|
28
28
|
obj = mock.MagicMock(spec=ctypes.POINTER(automation.IDispatch))
|
|
29
|
-
obj.GetTypeInfo.side_effect =
|
|
29
|
+
obj.GetTypeInfo.side_effect = OSError()
|
|
30
30
|
self.assertIsInstance(dynamic.Dispatch(obj), dynamic._Dispatch)
|
|
31
31
|
|
|
32
32
|
def test_returns_what_is_took_if_takes_other(self):
|
|
@@ -60,7 +60,8 @@ class Test(unittest.TestCase):
|
|
|
60
60
|
|
|
61
61
|
# slicing is not (yet?) supported
|
|
62
62
|
cv.Reset()
|
|
63
|
-
self.assertRaises(ArgumentError
|
|
63
|
+
with self.assertRaises(ArgumentError):
|
|
64
|
+
cv[:]
|
|
64
65
|
|
|
65
66
|
@unittest.skip("This test takes a long time. Do we need it? Can it be rewritten?")
|
|
66
67
|
def test_leaks_1(self):
|
|
@@ -151,10 +152,12 @@ class TestCollectionInterface(unittest.TestCase):
|
|
|
151
152
|
self.assertAccessInterface(d)
|
|
152
153
|
|
|
153
154
|
def test_named_property_no_length(self):
|
|
154
|
-
self.assertRaises(TypeError
|
|
155
|
+
with self.assertRaises(TypeError):
|
|
156
|
+
len(self.d.Item)
|
|
155
157
|
|
|
156
158
|
def test_named_property_not_iterable(self):
|
|
157
|
-
self.assertRaises(TypeError
|
|
159
|
+
with self.assertRaises(TypeError):
|
|
160
|
+
list(self.d.Item)
|
|
158
161
|
|
|
159
162
|
|
|
160
163
|
if __name__ == "__main__":
|
|
@@ -4,9 +4,10 @@ from ctypes import POINTER, byref, pointer
|
|
|
4
4
|
from unittest import mock
|
|
5
5
|
|
|
6
6
|
import comtypes.client
|
|
7
|
-
from comtypes import CLSCTX_SERVER, COMObject, IUnknown, hresult
|
|
7
|
+
from comtypes import CLSCTX_SERVER, COMObject, IPersist, IUnknown, hresult
|
|
8
8
|
from comtypes._post_coinit.misc import _CoCreateInstance
|
|
9
9
|
from comtypes.automation import IDispatch
|
|
10
|
+
from comtypes.typeinfo import GUIDKIND_DEFAULT_SOURCE_DISP_IID
|
|
10
11
|
|
|
11
12
|
comtypes.client.GetModule("UIAutomationCore.dll")
|
|
12
13
|
comtypes.client.GetModule("scrrun.dll")
|
|
@@ -131,11 +132,9 @@ class Test_IProvideClassInfo_GetClassInfo(ut.TestCase):
|
|
|
131
132
|
|
|
132
133
|
class Test_IProvideClassInfo2_GetGUID(ut.TestCase):
|
|
133
134
|
def test(self):
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
stdole.FontEvents._iid_,
|
|
138
|
-
)
|
|
135
|
+
obj = stdole.StdFont()
|
|
136
|
+
actual = obj.IProvideClassInfo2_GetGUID(GUIDKIND_DEFAULT_SOURCE_DISP_IID)
|
|
137
|
+
self.assertEqual(actual, stdole.FontEvents._iid_)
|
|
139
138
|
|
|
140
139
|
|
|
141
140
|
class Test_IPersist_GetClassID(ut.TestCase):
|
|
@@ -144,3 +143,17 @@ class Test_IPersist_GetClassID(ut.TestCase):
|
|
|
144
143
|
uiac.CUIAutomation().IPersist_GetClassID(),
|
|
145
144
|
uiac.CUIAutomation._reg_clsid_,
|
|
146
145
|
)
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
class Test_Vtbl(ut.TestCase):
|
|
149
|
+
def test_com_pointers(self):
|
|
150
|
+
stdpic = stdole.StdPicture()
|
|
151
|
+
cuia = uiac.CUIAutomation()
|
|
152
|
+
self.assertIs(
|
|
153
|
+
type(stdpic._com_pointers_[IPersist._iid_]),
|
|
154
|
+
type(cuia._com_pointers_[IPersist._iid_]),
|
|
155
|
+
)
|
|
156
|
+
self.assertIn(IDispatch._iid_, stdpic._com_pointers_)
|
|
157
|
+
self.assertNotIn(IDispatch._iid_, cuia._com_pointers_)
|
|
158
|
+
self.assertIn(stdole.IPictureDisp._iid_, stdpic._com_pointers_)
|
|
159
|
+
self.assertIn(uiac.IUIAutomation._iid_, cuia._com_pointers_)
|
|
@@ -5,7 +5,7 @@ from typing import Any
|
|
|
5
5
|
|
|
6
6
|
import comtypes.server
|
|
7
7
|
import comtypes.test.TestComServer
|
|
8
|
-
from comtypes import BSTR
|
|
8
|
+
from comtypes import BSTR, errorinfo, hresult, shelllink
|
|
9
9
|
from comtypes.automation import VARIANT, _midlSAFEARRAY
|
|
10
10
|
from comtypes.client import CreateObject, GetActiveObject
|
|
11
11
|
from comtypes.server.register import register, unregister
|
|
@@ -22,7 +22,7 @@ except ImportError:
|
|
|
22
22
|
def setUpModule():
|
|
23
23
|
try:
|
|
24
24
|
register(comtypes.test.TestComServer.TestComServer)
|
|
25
|
-
except
|
|
25
|
+
except OSError as e:
|
|
26
26
|
if e.winerror != 5: # [Error 5] Access is denied
|
|
27
27
|
raise e
|
|
28
28
|
raise unittest.SkipTest(
|
|
@@ -35,7 +35,7 @@ def tearDownModule():
|
|
|
35
35
|
unregister(comtypes.test.TestComServer.TestComServer)
|
|
36
36
|
|
|
37
37
|
|
|
38
|
-
class BaseServerTest
|
|
38
|
+
class BaseServerTest:
|
|
39
39
|
def create_object(self) -> Any: ...
|
|
40
40
|
|
|
41
41
|
def _find_memleak(self, func):
|
|
@@ -116,6 +116,11 @@ class TestInproc(BaseServerTest, unittest.TestCase):
|
|
|
116
116
|
"TestComServerLib.TestComServer", clsctx=comtypes.CLSCTX_INPROC_SERVER
|
|
117
117
|
)
|
|
118
118
|
|
|
119
|
+
@unittest.skip("Fails occasionally with a memory leak on INPROC.")
|
|
120
|
+
def test_eval(self):
|
|
121
|
+
# This test sometimes leaks memory when run as an in-process server.
|
|
122
|
+
pass
|
|
123
|
+
|
|
119
124
|
|
|
120
125
|
class TestLocalServer(BaseServerTest, unittest.TestCase):
|
|
121
126
|
def create_object(self):
|
|
@@ -201,6 +206,26 @@ class ActiveObjTest(unittest.TestCase):
|
|
|
201
206
|
self._doit(weak=False)
|
|
202
207
|
|
|
203
208
|
|
|
209
|
+
class SupportErrorInfoTest(unittest.TestCase):
|
|
210
|
+
def create_object(self):
|
|
211
|
+
return CreateObject(
|
|
212
|
+
comtypes.test.TestComServer.TestComServer,
|
|
213
|
+
interface=comtypes.test.TestComServer.ITestComServer,
|
|
214
|
+
)
|
|
215
|
+
|
|
216
|
+
def test_returns_S_OK(self):
|
|
217
|
+
psei = self.create_object().QueryInterface(errorinfo.ISupportErrorInfo)
|
|
218
|
+
iid = comtypes.test.TestComServer.ITestComServer._iid_
|
|
219
|
+
hr = psei.InterfaceSupportsErrorInfo(iid)
|
|
220
|
+
self.assertEqual(hr, hresult.S_OK)
|
|
221
|
+
|
|
222
|
+
def test_returns_S_FALSE(self):
|
|
223
|
+
psei = self.create_object().QueryInterface(errorinfo.ISupportErrorInfo)
|
|
224
|
+
iid = shelllink.IShellLinkW._iid_
|
|
225
|
+
hr = psei.InterfaceSupportsErrorInfo(iid)
|
|
226
|
+
self.assertEqual(hr, hresult.S_FALSE)
|
|
227
|
+
|
|
228
|
+
|
|
204
229
|
class VariantTest(unittest.TestCase):
|
|
205
230
|
def test_UDT(self):
|
|
206
231
|
from comtypes.gen.TestComServerLib import MYCOLOR
|
|
@@ -277,7 +302,10 @@ class TestEvents(unittest.TestCase):
|
|
|
277
302
|
import comtypes.test.test_comserver
|
|
278
303
|
|
|
279
304
|
doctest.testmod(
|
|
280
|
-
comtypes.test.test_comserver,
|
|
305
|
+
comtypes.test.test_comserver,
|
|
306
|
+
verbose=False,
|
|
307
|
+
optionflags=doctest.ELLIPSIS,
|
|
308
|
+
raise_on_error=True,
|
|
281
309
|
)
|
|
282
310
|
|
|
283
311
|
|
|
@@ -14,7 +14,8 @@ class Test(unittest.TestCase):
|
|
|
14
14
|
|
|
15
15
|
# Count is a normal propget, no propput
|
|
16
16
|
self.assertEqual(d.Count, 0)
|
|
17
|
-
self.assertRaises(AttributeError
|
|
17
|
+
with self.assertRaises(AttributeError):
|
|
18
|
+
setattr(d, "Count", -1)
|
|
18
19
|
|
|
19
20
|
# HashVal is a 'named' propget, no propput
|
|
20
21
|
##d.HashVal
|
|
@@ -66,10 +66,12 @@ class Test(unittest.TestCase):
|
|
|
66
66
|
self.assertEqual(d3.Item["baz"], 3.14)
|
|
67
67
|
|
|
68
68
|
def test_named_property_no_length(self):
|
|
69
|
-
self.assertRaises(TypeError
|
|
69
|
+
with self.assertRaises(TypeError):
|
|
70
|
+
len(self.d.Item)
|
|
70
71
|
|
|
71
72
|
def test_named_property_not_iterable(self):
|
|
72
|
-
self.assertRaises(TypeError
|
|
73
|
+
with self.assertRaises(TypeError):
|
|
74
|
+
list(self.d.Item)
|
|
73
75
|
|
|
74
76
|
def assertAccessInterface(self, d):
|
|
75
77
|
"""Asserts access via indexing and named property"""
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import unittest as ut
|
|
2
|
+
|
|
3
|
+
from comtypes import errorinfo, shelllink
|
|
4
|
+
from comtypes import hresult as hres
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class Test_GetErrorInfo(ut.TestCase):
|
|
8
|
+
def test_error_has_been_set(self):
|
|
9
|
+
self.assertIsNone(errorinfo.GetErrorInfo())
|
|
10
|
+
errmsg = "sample unexpected error message for tests"
|
|
11
|
+
errcode = hres.E_UNEXPECTED
|
|
12
|
+
helpcontext = 123
|
|
13
|
+
hr = errorinfo.ReportError(
|
|
14
|
+
errmsg,
|
|
15
|
+
shelllink.IShellLinkW._iid_,
|
|
16
|
+
str(shelllink.ShellLink._reg_clsid_),
|
|
17
|
+
helpfile="help.chm",
|
|
18
|
+
helpcontext=helpcontext,
|
|
19
|
+
hresult=errcode,
|
|
20
|
+
)
|
|
21
|
+
self.assertEqual(errcode, hr)
|
|
22
|
+
pei = errorinfo.GetErrorInfo()
|
|
23
|
+
self.assertIsNotNone(pei)
|
|
24
|
+
assert pei is not None # for static type guard
|
|
25
|
+
self.assertEqual(shelllink.IShellLinkW._iid_, pei.GetGUID())
|
|
26
|
+
self.assertEqual("lnkfile", pei.GetSource())
|
|
27
|
+
self.assertEqual(errmsg, pei.GetDescription())
|
|
28
|
+
self.assertEqual("help.chm", pei.GetHelpFile())
|
|
29
|
+
self.assertEqual(helpcontext, pei.GetHelpContext())
|
|
30
|
+
# Calling `GetErrorInfo` clears the error state for the thread.
|
|
31
|
+
# Therefore, `None` is returned in the second call.
|
|
32
|
+
self.assertIsNone(errorinfo.GetErrorInfo())
|
|
33
|
+
|
|
34
|
+
def test_without_optional_args(self):
|
|
35
|
+
self.assertIsNone(errorinfo.GetErrorInfo())
|
|
36
|
+
errmsg = "sample unexpected error message for tests"
|
|
37
|
+
hr = errorinfo.ReportError(errmsg, shelllink.IShellLinkW._iid_)
|
|
38
|
+
self.assertEqual(hres.DISP_E_EXCEPTION, hr)
|
|
39
|
+
pei = errorinfo.GetErrorInfo()
|
|
40
|
+
self.assertIsNotNone(pei)
|
|
41
|
+
assert pei is not None # for static type guard
|
|
42
|
+
self.assertEqual(shelllink.IShellLinkW._iid_, pei.GetGUID())
|
|
43
|
+
self.assertIsNone(pei.GetSource())
|
|
44
|
+
self.assertEqual(errmsg, pei.GetDescription())
|
|
45
|
+
self.assertIsNone(pei.GetHelpFile())
|
|
46
|
+
self.assertEqual(0, pei.GetHelpContext())
|
|
47
|
+
|
|
48
|
+
def test_error_has_not_been_set(self):
|
|
49
|
+
self.assertIsNone(errorinfo.GetErrorInfo())
|
|
50
|
+
pei = errorinfo.GetErrorInfo()
|
|
51
|
+
self.assertIsNone(pei)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def raise_runtime_error():
|
|
55
|
+
_raise_runtime_error()
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def _raise_runtime_error():
|
|
59
|
+
raise RuntimeError("for testing")
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class Test_ReportException(ut.TestCase):
|
|
63
|
+
def test_without_stacklevel(self):
|
|
64
|
+
self.assertIsNone(errorinfo.GetErrorInfo())
|
|
65
|
+
iid = shelllink.IShellLinkW._iid_
|
|
66
|
+
try:
|
|
67
|
+
raise_runtime_error()
|
|
68
|
+
except RuntimeError:
|
|
69
|
+
hr = errorinfo.ReportException(hres.E_UNEXPECTED, iid)
|
|
70
|
+
self.assertEqual(hres.E_UNEXPECTED, hr)
|
|
71
|
+
pei = errorinfo.GetErrorInfo()
|
|
72
|
+
self.assertIsNotNone(pei)
|
|
73
|
+
assert pei is not None # for static type guard
|
|
74
|
+
self.assertEqual(shelllink.IShellLinkW._iid_, pei.GetGUID())
|
|
75
|
+
self.assertIsNone(pei.GetSource())
|
|
76
|
+
self.assertEqual("<class 'RuntimeError'>: for testing", pei.GetDescription())
|
|
77
|
+
self.assertIsNone(pei.GetHelpFile())
|
|
78
|
+
self.assertEqual(0, pei.GetHelpContext())
|
|
79
|
+
self.assertIsNone(errorinfo.GetErrorInfo())
|
|
80
|
+
|
|
81
|
+
def test_with_stacklevel(self):
|
|
82
|
+
self.assertIsNone(errorinfo.GetErrorInfo())
|
|
83
|
+
stem = "<class 'RuntimeError'>: for testing"
|
|
84
|
+
iid = shelllink.IShellLinkW._iid_
|
|
85
|
+
for slv, text in [
|
|
86
|
+
# XXX: If the codebase changes, the line where functions or
|
|
87
|
+
# methods are defined will change, meaning this test is brittle.
|
|
88
|
+
(0, f"{stem} ({__name__}, line 96)"),
|
|
89
|
+
(1, f"{stem} ({__name__}, line 55)"),
|
|
90
|
+
(2, f"{stem} ({__name__}, line 59)"),
|
|
91
|
+
]:
|
|
92
|
+
with self.subTest(text=text):
|
|
93
|
+
try:
|
|
94
|
+
raise_runtime_error()
|
|
95
|
+
except RuntimeError:
|
|
96
|
+
errorinfo.ReportException(hres.E_UNEXPECTED, iid, stacklevel=slv)
|
|
97
|
+
pei = errorinfo.GetErrorInfo()
|
|
98
|
+
assert pei is not None # for static type guard
|
|
99
|
+
self.assertEqual(text, pei.GetDescription())
|
|
100
|
+
self.assertIsNone(errorinfo.GetErrorInfo())
|
|
101
|
+
|
|
102
|
+
def test_with_over_stacklevel(self):
|
|
103
|
+
self.assertIsNone(errorinfo.GetErrorInfo())
|
|
104
|
+
iid = shelllink.IShellLinkW._iid_
|
|
105
|
+
try:
|
|
106
|
+
raise_runtime_error()
|
|
107
|
+
except RuntimeError:
|
|
108
|
+
with self.assertRaises(ValueError):
|
|
109
|
+
errorinfo.ReportException(hres.E_UNEXPECTED, iid, stacklevel=4)
|
|
110
|
+
|
|
111
|
+
def test_with_no_error_and_zero_stacklevel(self):
|
|
112
|
+
self.assertIsNone(errorinfo.GetErrorInfo())
|
|
113
|
+
iid = shelllink.IShellLinkW._iid_
|
|
114
|
+
with self.assertRaises(ValueError):
|
|
115
|
+
errorinfo.ReportException(hres.E_UNEXPECTED, iid, stacklevel=0)
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
# -*- coding: latin-1 -*-
|
|
2
|
-
|
|
3
1
|
import datetime
|
|
4
2
|
import sys
|
|
5
3
|
import unittest
|
|
@@ -26,7 +24,7 @@ except (ImportError, OSError):
|
|
|
26
24
|
IMPORT_FAILED = True
|
|
27
25
|
|
|
28
26
|
|
|
29
|
-
class BaseBindTest
|
|
27
|
+
class BaseBindTest:
|
|
30
28
|
# `dynamic = True/False` must be defined in subclasses!
|
|
31
29
|
dynamic: ClassVar[bool]
|
|
32
30
|
|