comtypes 1.4.11__zip → 1.4.13__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.11 → comtypes-1.4.13}/CHANGES.txt +33 -0
- {comtypes-1.4.11/comtypes.egg-info → comtypes-1.4.13}/PKG-INFO +5 -5
- {comtypes-1.4.11 → comtypes-1.4.13}/README.md +3 -3
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/__init__.py +8 -2
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/_comobject.py +6 -6
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/_memberspec.py +7 -7
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/_meta.py +7 -3
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/_npsupport.py +12 -17
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/_post_coinit/_cominterface_meta_patcher.py +5 -5
- comtypes-1.4.13/comtypes/_post_coinit/activeobj.py +61 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/_post_coinit/misc.py +1 -23
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/_post_coinit/unknwn.py +10 -8
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/_vtbl.py +3 -3
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/automation.py +10 -13
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/client/__init__.py +2 -1
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/client/_activeobj.py +8 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/client/_code_cache.py +1 -1
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/client/_constants.py +1 -1
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/client/_events.py +6 -6
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/client/_generate.py +1 -1
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/client/dynamic.py +3 -3
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/client/lazybind.py +3 -3
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/errorinfo.py +1 -1
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/hresult.py +68 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/messageloop.py +1 -1
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/patcher.py +2 -2
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/persist.py +9 -2
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/safearray.py +10 -10
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/server/__init__.py +5 -37
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/server/automation.py +2 -2
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/server/connectionpoints.py +3 -3
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/server/inprocserver.py +2 -2
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/server/localserver.py +3 -3
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/server/register.py +5 -5
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_agilent.py +1 -1
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_client_dynamic.py +1 -1
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_comserver.py +15 -2
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_createwrappers.py +1 -1
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_dispifc_records.py +0 -2
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_dispifc_safearrays.py +0 -2
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_dispinterface.py +1 -1
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_excel.py +2 -5
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_getactiveobj.py +19 -2
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_hresult.py +39 -0
- comtypes-1.4.13/comtypes/test/test_messageloop.py +117 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_midl_safearray_create.py +0 -2
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_msscript.py +1 -1
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_npsupport.py +22 -11
- comtypes-1.4.13/comtypes/test/test_persist.py +71 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_recordinfo.py +0 -2
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_server.py +6 -6
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_storage.py +1 -1
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_stream.py +22 -2
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_urlhistory.py +1 -1
- comtypes-1.4.13/comtypes/test/test_util.py +227 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_variant.py +41 -24
- comtypes-1.4.13/comtypes/test/test_viewobject.py +78 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_word.py +1 -1
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/tools/codegenerator/codegenerator.py +1 -1
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/tools/codegenerator/comments.py +1 -1
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/tools/codegenerator/heads.py +5 -5
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/tools/codegenerator/helpers.py +7 -7
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/tools/codegenerator/namespaces.py +3 -3
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/tools/codegenerator/typeannotator.py +2 -2
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/tools/tlbparser.py +1 -1
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/tools/typedesc.py +14 -14
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/tools/typedesc_base.py +19 -19
- comtypes-1.4.13/comtypes/util.py +189 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/viewobject.py +29 -5
- {comtypes-1.4.11 → comtypes-1.4.13/comtypes.egg-info}/PKG-INFO +5 -5
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes.egg-info/SOURCES.txt +4 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/pyproject.toml +12 -1
- {comtypes-1.4.11 → comtypes-1.4.13}/setup.cfg +1 -1
- comtypes-1.4.11/comtypes/test/test_persist.py +0 -38
- comtypes-1.4.11/comtypes/util.py +0 -107
- {comtypes-1.4.11 → comtypes-1.4.13}/LICENSE.txt +0 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/MANIFEST.in +0 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/GUID.py +0 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/_post_coinit/__init__.py +0 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/_post_coinit/bstr.py +0 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/_post_coinit/instancemethod.py +0 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/_safearray.py +0 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/_tlib_version_checker.py +0 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/clear_cache.py +0 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/client/_create.py +0 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/client/_managing.py +0 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/connectionpoints.py +0 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/git.py +0 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/hints.pyi +0 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/logutil.py +0 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/server/w_getopt.py +0 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/shelllink.py +0 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/stream.py +0 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/TestComServer.idl +0 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/TestComServer.py +0 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/TestComServer.tlb +0 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/TestDispServer.idl +0 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/TestDispServer.py +0 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/TestDispServer.tlb +0 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/__init__.py +0 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/find_memleak.py +0 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/mylib.idl +0 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/mylib.tlb +0 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/mytypelib.idl +0 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/runtests.py +0 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/setup.py +0 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_BSTR.py +0 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_DISPPARAMS.py +0 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_GUID.py +0 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_QueryService.py +0 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_avmc.py +0 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_basic.py +0 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_casesensitivity.py +0 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_clear_cache.py +0 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_client.py +0 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_client_regenerate_modules.py +0 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_collections.py +0 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_comobject.py +0 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_dict.py +0 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_dyndispatch.py +0 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_errorinfo.py +0 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_findgendir.py +0 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_ie.py +0 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_ienum.py +0 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_imfattributes.py +0 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_inout_args.py +0 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_jscript.js +0 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_monikers.py +0 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_outparam.py +0 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_pump_events.py +0 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_safearray.py +0 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_sapi.py +0 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_server_register.py +0 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_shelllink.py +0 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_showevents.py +0 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_subinterface.py +0 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_typeannotator.py +0 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_typeinfo.py +0 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_w_getopt.py +0 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_win32com_interop.py +0 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_wmi.py +0 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/urlhist.tlb +0 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/tools/__init__.py +0 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/tools/codegenerator/__init__.py +0 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/tools/codegenerator/modulenamer.py +0 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/tools/codegenerator/packing.py +0 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/typeinfo.py +0 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes.egg-info/dependency_links.txt +0 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes.egg-info/entry_points.txt +0 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/comtypes.egg-info/top_level.txt +0 -0
- {comtypes-1.4.11 → comtypes-1.4.13}/setup.py +0 -0
|
@@ -64,7 +64,7 @@ _CloseHandle.restype = BOOL
|
|
|
64
64
|
_ReceiverType = _UnionT[COMObject, IUnknown]
|
|
65
65
|
|
|
66
66
|
|
|
67
|
-
class _AdviseConnection
|
|
67
|
+
class _AdviseConnection:
|
|
68
68
|
cp: Optional[IConnectionPoint]
|
|
69
69
|
cookie: Optional[int]
|
|
70
70
|
receiver: Optional[_ReceiverType]
|
|
@@ -104,7 +104,7 @@ class _AdviseConnection(object):
|
|
|
104
104
|
if self.cookie is not None:
|
|
105
105
|
assert self.cp is not None
|
|
106
106
|
self.cp.Unadvise(self.cookie)
|
|
107
|
-
except (
|
|
107
|
+
except (OSError, COMError):
|
|
108
108
|
# Are we sure we want to ignore errors here?
|
|
109
109
|
pass
|
|
110
110
|
|
|
@@ -209,7 +209,7 @@ class _SinkMethodFinder(_MethodFinder):
|
|
|
209
209
|
"""
|
|
210
210
|
|
|
211
211
|
def __init__(self, inst: COMObject, sink: Any) -> None:
|
|
212
|
-
super(
|
|
212
|
+
super().__init__(inst)
|
|
213
213
|
self.sink = sink
|
|
214
214
|
|
|
215
215
|
def find_method(self, fq_name: str, mthname: str) -> Callable[..., Any]:
|
|
@@ -229,7 +229,7 @@ class _SinkMethodFinder(_MethodFinder):
|
|
|
229
229
|
|
|
230
230
|
def _find_method(self, fq_name: str, mthname: str) -> Callable[..., Any]:
|
|
231
231
|
try:
|
|
232
|
-
return super(
|
|
232
|
+
return super().find_method(fq_name, mthname)
|
|
233
233
|
except AttributeError:
|
|
234
234
|
try:
|
|
235
235
|
return getattr(self.sink, fq_name)
|
|
@@ -283,7 +283,7 @@ def GetEvents(
|
|
|
283
283
|
return _AdviseConnection(source, interface, rcv)
|
|
284
284
|
|
|
285
285
|
|
|
286
|
-
class EventDumper
|
|
286
|
+
class EventDumper:
|
|
287
287
|
"""Universal sink for COM events."""
|
|
288
288
|
|
|
289
289
|
def __getattr__(self, name: str) -> Callable[..., Any]:
|
|
@@ -381,7 +381,7 @@ def PumpEvents(timeout: Any) -> None:
|
|
|
381
381
|
handles,
|
|
382
382
|
byref(ctypes.c_ulong()),
|
|
383
383
|
)
|
|
384
|
-
except
|
|
384
|
+
except OSError as details:
|
|
385
385
|
if details.winerror != hresult.RPC_S_CALLPENDING: # timeout expired
|
|
386
386
|
raise
|
|
387
387
|
else:
|
|
@@ -211,7 +211,7 @@ def _create_module(modulename: str, code: str) -> types.ModuleType:
|
|
|
211
211
|
return _my_import(modulename)
|
|
212
212
|
|
|
213
213
|
|
|
214
|
-
class ModuleGenerator
|
|
214
|
+
class ModuleGenerator:
|
|
215
215
|
def __init__(self, tlib: typeinfo.ITypeLib, pathname: Optional[str]) -> None:
|
|
216
216
|
self.wrapper_name = codegenerator.name_wrapper_module(tlib)
|
|
217
217
|
self.friendly_name = codegenerator.name_friendly_module(tlib)
|
|
@@ -27,7 +27,7 @@ def Dispatch(obj):
|
|
|
27
27
|
if isinstance(obj, ctypes.POINTER(automation.IDispatch)):
|
|
28
28
|
try:
|
|
29
29
|
tinfo = obj.GetTypeInfo(0)
|
|
30
|
-
except (
|
|
30
|
+
except (OSError, COMError):
|
|
31
31
|
return _Dispatch(obj)
|
|
32
32
|
return lazybind.Dispatch(obj, tinfo)
|
|
33
33
|
return obj
|
|
@@ -59,7 +59,7 @@ class MethodCaller:
|
|
|
59
59
|
)
|
|
60
60
|
|
|
61
61
|
|
|
62
|
-
class _Dispatch
|
|
62
|
+
class _Dispatch:
|
|
63
63
|
"""Expose methods and properties via fully dynamic dispatch."""
|
|
64
64
|
|
|
65
65
|
_comobj: automation.IDispatch
|
|
@@ -160,7 +160,7 @@ class _Dispatch(object):
|
|
|
160
160
|
# )
|
|
161
161
|
|
|
162
162
|
|
|
163
|
-
class _Collection
|
|
163
|
+
class _Collection:
|
|
164
164
|
def __init__(self, enum: automation.IEnumVARIANT):
|
|
165
165
|
self.enum = enum
|
|
166
166
|
|
|
@@ -12,7 +12,7 @@ from comtypes.automation import (
|
|
|
12
12
|
from comtypes.typeinfo import FUNC_DISPATCH, FUNC_PUREVIRTUAL
|
|
13
13
|
|
|
14
14
|
|
|
15
|
-
class FuncDesc
|
|
15
|
+
class FuncDesc:
|
|
16
16
|
"""Stores important FUNCDESC properties by copying them from a
|
|
17
17
|
real FUNCDESC instance.
|
|
18
18
|
"""
|
|
@@ -28,7 +28,7 @@ class FuncDesc(object):
|
|
|
28
28
|
_all_slice = slice(None, None, None)
|
|
29
29
|
|
|
30
30
|
|
|
31
|
-
class NamedProperty
|
|
31
|
+
class NamedProperty:
|
|
32
32
|
def __init__(self, disp, get, put, putref):
|
|
33
33
|
self.get = get
|
|
34
34
|
self.put = put
|
|
@@ -83,7 +83,7 @@ class NamedProperty(object):
|
|
|
83
83
|
# objects do not (could be added, would probably be expensive)
|
|
84
84
|
|
|
85
85
|
|
|
86
|
-
class Dispatch
|
|
86
|
+
class Dispatch:
|
|
87
87
|
"""Dynamic dispatch for an object the exposes type information.
|
|
88
88
|
Binding at runtime is done via ITypeComp::Bind calls.
|
|
89
89
|
"""
|
|
@@ -89,3 +89,71 @@ def HRESULT_FROM_WIN32(x: int) -> int:
|
|
|
89
89
|
# them into HRESULT values by setting the high bit, ensuring a consistent way
|
|
90
90
|
# to indicate failure across these APIs.
|
|
91
91
|
RPC_S_SERVER_UNAVAILABLE = -2147023174 # 0x800706BA (WIN32: 1722 0x6BA)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
################################################################
|
|
95
|
+
# signed32bithex
|
|
96
|
+
#
|
|
97
|
+
# When using this package, error codes for exceptions like
|
|
98
|
+
# `COMError` or `WindowsError` are base10 integers.
|
|
99
|
+
#
|
|
100
|
+
# However, as shown below, many technical references represent
|
|
101
|
+
# HRESULT values using signed 32-bit hexadecimal notation:
|
|
102
|
+
# https://learn.microsoft.com/en-us/windows/win32/seccrypto/common-hresult-values
|
|
103
|
+
# https://learn.microsoft.com/en-us/windows/win32/learnwin32/error-codes-in-com
|
|
104
|
+
#
|
|
105
|
+
# If you search for the error code using the proper notation,
|
|
106
|
+
# you might be able to find the reference.
|
|
107
|
+
#
|
|
108
|
+
# Don't be overly afraid of `COMError` or `WindowsError`!
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def signed32bithex_to_int(value: str, /) -> int:
|
|
112
|
+
"""Converts a string in signed 32-bit hexadecimal notation to an integer.
|
|
113
|
+
|
|
114
|
+
Examples:
|
|
115
|
+
|
|
116
|
+
>>> signed32bithex_to_int('0x00000000') == 0 # S_OK
|
|
117
|
+
True
|
|
118
|
+
>>> signed32bithex_to_int('0x00000001') == 1 # S_FALSE
|
|
119
|
+
True
|
|
120
|
+
>>> signed32bithex_to_int('0x8000FFFF') == -2147418113 # E_UNEXPECTED
|
|
121
|
+
True
|
|
122
|
+
"""
|
|
123
|
+
val = int(value, 16)
|
|
124
|
+
if val < 0x80000000:
|
|
125
|
+
return val
|
|
126
|
+
return val - 0x100000000
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def int_to_signed32bithex(value: int, /) -> str:
|
|
130
|
+
"""Converts an integer to a string in signed 32-bit hexadecimal notation.
|
|
131
|
+
|
|
132
|
+
Examples:
|
|
133
|
+
|
|
134
|
+
>>> import comtypes.hresult as hr
|
|
135
|
+
>>> int_to_signed32bithex(hr.S_OK)
|
|
136
|
+
'0x00000000'
|
|
137
|
+
>>> int_to_signed32bithex(hr.S_FALSE)
|
|
138
|
+
'0x00000001'
|
|
139
|
+
>>> int_to_signed32bithex(hr.E_UNEXPECTED)
|
|
140
|
+
'0x8000FFFF'
|
|
141
|
+
|
|
142
|
+
>>> from comtypes import CoCreateInstance
|
|
143
|
+
>>> from comtypes import shelllink, automation
|
|
144
|
+
>>> CLSID_ShellLink = shelllink.ShellLink().IPersist_GetClassID()
|
|
145
|
+
>>> p = CoCreateInstance(CLSID_ShellLink)
|
|
146
|
+
>>> p.QueryInterface(shelllink.IShellLinkA) # doctest: +ELLIPSIS
|
|
147
|
+
<POINTER(IShellLinkA) ptr=0x... at ...>
|
|
148
|
+
>>> p.QueryInterface(automation.IDispatch) # doctest: +ELLIPSIS
|
|
149
|
+
Traceback (most recent call last):
|
|
150
|
+
...
|
|
151
|
+
_ctypes.COMError: (-2147467262, ..., (None, None, None, 0, None))
|
|
152
|
+
>>> int_to_signed32bithex(-2147467262) # E_NOINTERFACE
|
|
153
|
+
'0x80004002'
|
|
154
|
+
"""
|
|
155
|
+
# it is simpler than using `hex(value & 0xFFFFFFFF)`
|
|
156
|
+
return f"0x{value & 0xFFFFFFFF:08X}"
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
################################################################
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
class Patch
|
|
1
|
+
class Patch:
|
|
2
2
|
"""
|
|
3
3
|
Implements a class decorator suitable for patching an existing class with
|
|
4
4
|
a new namespace.
|
|
@@ -69,7 +69,7 @@ def no_replace(f):
|
|
|
69
69
|
return f
|
|
70
70
|
|
|
71
71
|
|
|
72
|
-
class ReferenceEmptyClass
|
|
72
|
+
class ReferenceEmptyClass:
|
|
73
73
|
"""
|
|
74
74
|
This empty class will serve as a reference for attributes present on
|
|
75
75
|
any class.
|
|
@@ -12,7 +12,7 @@ interface, useful in client code.
|
|
|
12
12
|
|
|
13
13
|
from ctypes import POINTER, Structure, c_int, c_ulong, c_ushort, c_wchar_p
|
|
14
14
|
from ctypes.wintypes import BOOL, DWORD, WORD
|
|
15
|
-
from typing import TYPE_CHECKING
|
|
15
|
+
from typing import TYPE_CHECKING, Any, Optional
|
|
16
16
|
|
|
17
17
|
from comtypes import COMMETHOD, GUID, HRESULT, IPersist, IUnknown
|
|
18
18
|
from comtypes.automation import VARIANT, tagEXCEPINFO
|
|
@@ -65,6 +65,13 @@ class IPropertyBag(IUnknown):
|
|
|
65
65
|
),
|
|
66
66
|
]
|
|
67
67
|
|
|
68
|
+
if TYPE_CHECKING:
|
|
69
|
+
|
|
70
|
+
def Read(
|
|
71
|
+
self, pszPropName: str, pVar: VARIANT, pErrorLog: Optional[IErrorLog]
|
|
72
|
+
) -> Any: ...
|
|
73
|
+
def Write(self, pszPropName: str, pVar: Any) -> hints.Hresult: ...
|
|
74
|
+
|
|
68
75
|
|
|
69
76
|
class IPersistPropertyBag(IPersist):
|
|
70
77
|
_iid_ = GUID("{37D84F60-42CB-11CE-8135-00AA004BB851}")
|
|
@@ -266,7 +273,7 @@ class DictPropertyBag(COMObject):
|
|
|
266
273
|
_com_interfaces_ = [IPropertyBag]
|
|
267
274
|
|
|
268
275
|
def __init__(self, **kw):
|
|
269
|
-
super(
|
|
276
|
+
super().__init__()
|
|
270
277
|
self.values = kw
|
|
271
278
|
|
|
272
279
|
def Read(self, this, name, pVar, errorlog):
|
|
@@ -17,7 +17,7 @@ if TYPE_CHECKING:
|
|
|
17
17
|
_safearray_type_cache = {}
|
|
18
18
|
|
|
19
19
|
|
|
20
|
-
class _SafeArrayAsNdArrayContextManager
|
|
20
|
+
class _SafeArrayAsNdArrayContextManager:
|
|
21
21
|
"""Context manager allowing safe arrays to be extracted as ndarrays.
|
|
22
22
|
|
|
23
23
|
This is thread-safe.
|
|
@@ -110,7 +110,7 @@ def _make_safearray_type(itemtype):
|
|
|
110
110
|
raise TypeError(itemtype)
|
|
111
111
|
|
|
112
112
|
@Patch(POINTER(sa_type))
|
|
113
|
-
class _
|
|
113
|
+
class _:
|
|
114
114
|
# Should explain the ideas how SAFEARRAY is used in comtypes
|
|
115
115
|
_itemtype_ = itemtype # a ctypes type
|
|
116
116
|
_vartype_ = vartype # a VARTYPE value: VT_...
|
|
@@ -378,7 +378,7 @@ def _make_safearray_type(itemtype):
|
|
|
378
378
|
return tuple(result) # for compatibility with pywin32.
|
|
379
379
|
|
|
380
380
|
@Patch(POINTER(POINTER(sa_type)))
|
|
381
|
-
class __
|
|
381
|
+
class __:
|
|
382
382
|
@classmethod
|
|
383
383
|
def from_param(cls, value):
|
|
384
384
|
if isinstance(value, cls._type_):
|
|
@@ -398,19 +398,19 @@ def _make_safearray_type(itemtype):
|
|
|
398
398
|
def _ndarray_to_variant_array(value):
|
|
399
399
|
"""Convert an ndarray to VARIANT_dtype array"""
|
|
400
400
|
# Check that variant arrays are supported
|
|
401
|
-
if comtypes.npsupport.
|
|
401
|
+
if comtypes.npsupport.VARIANT_dtype is None:
|
|
402
402
|
msg = "VARIANT ndarrays require NumPy 1.7 or newer."
|
|
403
403
|
raise RuntimeError(msg)
|
|
404
|
-
numpy = comtypes.npsupport.
|
|
404
|
+
numpy = comtypes.npsupport.numpy
|
|
405
405
|
|
|
406
406
|
# special cases
|
|
407
|
-
if numpy.issubdtype(value.dtype, comtypes.npsupport.
|
|
407
|
+
if numpy.issubdtype(value.dtype, comtypes.npsupport.datetime64):
|
|
408
408
|
return _datetime64_ndarray_to_variant_array(value)
|
|
409
409
|
|
|
410
410
|
from comtypes.automation import VARIANT
|
|
411
411
|
|
|
412
412
|
# Empty array
|
|
413
|
-
varr = numpy.zeros(value.shape, comtypes.npsupport.
|
|
413
|
+
varr = numpy.zeros(value.shape, comtypes.npsupport.VARIANT_dtype, order="F")
|
|
414
414
|
# Convert each value to a variant and put it in the array.
|
|
415
415
|
varr.flat = [VARIANT(v) for v in value.flat]
|
|
416
416
|
return varr
|
|
@@ -423,12 +423,12 @@ def _datetime64_ndarray_to_variant_array(value):
|
|
|
423
423
|
# fractional days.
|
|
424
424
|
from comtypes.automation import VT_DATE
|
|
425
425
|
|
|
426
|
-
numpy = comtypes.npsupport.
|
|
426
|
+
numpy = comtypes.npsupport.numpy
|
|
427
427
|
value = numpy.array(value, "datetime64[ns]")
|
|
428
|
-
value = value - comtypes.npsupport.
|
|
428
|
+
value = value - comtypes.npsupport.com_null_date64
|
|
429
429
|
# Convert to days
|
|
430
430
|
value = value / numpy.timedelta64(1, "D")
|
|
431
|
-
varr = numpy.zeros(value.shape, comtypes.npsupport.
|
|
431
|
+
varr = numpy.zeros(value.shape, comtypes.npsupport.VARIANT_dtype, order="F")
|
|
432
432
|
varr["vt"] = VT_DATE
|
|
433
433
|
varr["_"]["VT_R8"].flat = value.flat
|
|
434
434
|
return varr
|
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import ctypes
|
|
2
|
-
from ctypes import HRESULT, POINTER,
|
|
3
|
-
from ctypes.wintypes import DWORD, LPVOID
|
|
2
|
+
from ctypes import HRESULT, POINTER, byref
|
|
4
3
|
from typing import TYPE_CHECKING, Any, Optional, Type
|
|
5
4
|
|
|
6
5
|
import comtypes
|
|
7
6
|
import comtypes.client
|
|
8
7
|
import comtypes.client.dynamic
|
|
9
8
|
from comtypes import GUID, STDMETHOD, IUnknown
|
|
9
|
+
from comtypes import RevokeActiveObject as RevokeActiveObject
|
|
10
10
|
from comtypes.automation import IDispatch
|
|
11
|
-
from comtypes.GUID import REFCLSID
|
|
12
11
|
|
|
13
12
|
if TYPE_CHECKING:
|
|
14
13
|
from ctypes import _Pointer
|
|
@@ -64,41 +63,10 @@ class IClassFactory(IUnknown):
|
|
|
64
63
|
# STDMETHOD(HRESULT, "AddConnection", [c_ulong, c_ulong]),
|
|
65
64
|
# STDMETHOD(HRESULT, "ReleaseConnection", [c_ulong, c_ulong, c_ulong])]
|
|
66
65
|
|
|
67
|
-
# The following code is untested:
|
|
68
|
-
|
|
69
|
-
ACTIVEOBJECT_STRONG = 0x0
|
|
70
|
-
ACTIVEOBJECT_WEAK = 0x1
|
|
71
|
-
|
|
72
|
-
_oleaut32 = OleDLL("oleaut32")
|
|
73
|
-
|
|
74
|
-
_RegisterActiveObject = _oleaut32.RegisterActiveObject
|
|
75
|
-
_RegisterActiveObject.argtypes = [
|
|
76
|
-
c_void_p,
|
|
77
|
-
REFCLSID,
|
|
78
|
-
DWORD,
|
|
79
|
-
POINTER(DWORD),
|
|
80
|
-
]
|
|
81
|
-
_RegisterActiveObject.restype = HRESULT
|
|
82
|
-
|
|
83
|
-
_RevokeActiveObject = _oleaut32.RevokeActiveObject
|
|
84
|
-
_RevokeActiveObject.argtypes = [
|
|
85
|
-
DWORD,
|
|
86
|
-
LPVOID,
|
|
87
|
-
]
|
|
88
|
-
_RevokeActiveObject.restype = HRESULT
|
|
89
|
-
|
|
90
66
|
|
|
91
67
|
def RegisterActiveObject(comobj: comtypes.COMObject, weak: bool = True) -> int:
|
|
68
|
+
"""Registers a pointer as the active object for its class and returns the handle."""
|
|
92
69
|
punk = comobj._com_pointers_[IUnknown._iid_]
|
|
93
70
|
clsid = comobj._reg_clsid_
|
|
94
|
-
if weak
|
|
95
|
-
|
|
96
|
-
else:
|
|
97
|
-
flags = ACTIVEOBJECT_STRONG
|
|
98
|
-
handle = ctypes.c_ulong()
|
|
99
|
-
_RegisterActiveObject(punk, byref(clsid), flags, byref(handle))
|
|
100
|
-
return handle.value
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
def RevokeActiveObject(handle: int) -> None:
|
|
104
|
-
_RevokeActiveObject(handle, None)
|
|
71
|
+
flags = comtypes.ACTIVEOBJECT_WEAK if weak else comtypes.ACTIVEOBJECT_STRONG
|
|
72
|
+
return comtypes.RegisterActiveObject(punk, clsid, flags)
|
|
@@ -22,7 +22,7 @@ class VARIANTEnumerator(COMObject):
|
|
|
22
22
|
items # keep, so that we can restore our iterator (in Reset, and Clone).
|
|
23
23
|
)
|
|
24
24
|
self.seq = iter(self.items)
|
|
25
|
-
super(
|
|
25
|
+
super().__init__()
|
|
26
26
|
|
|
27
27
|
def Next(self, this, celt, rgVar, pCeltFetched):
|
|
28
28
|
if not rgVar:
|
|
@@ -75,7 +75,7 @@ class COMCollection(COMObject):
|
|
|
75
75
|
def __init__(self, itemtype, collection):
|
|
76
76
|
self.collection = collection
|
|
77
77
|
self.itemtype = itemtype
|
|
78
|
-
super(
|
|
78
|
+
super().__init__()
|
|
79
79
|
|
|
80
80
|
def _get_Item(self, this, pathname, pitem):
|
|
81
81
|
if not pitem:
|
|
@@ -31,7 +31,7 @@ class ConnectionPointImpl(COMObject):
|
|
|
31
31
|
def __init__(
|
|
32
32
|
self, sink_interface: Type[IUnknown], sink_typeinfo: ITypeInfo
|
|
33
33
|
) -> None:
|
|
34
|
-
super(
|
|
34
|
+
super().__init__()
|
|
35
35
|
self._connections: Dict[int, IUnknown] = {}
|
|
36
36
|
self._cookie = 0
|
|
37
37
|
self._sink_interface = sink_interface
|
|
@@ -109,7 +109,7 @@ class ConnectionPointImpl(COMObject):
|
|
|
109
109
|
yield result
|
|
110
110
|
|
|
111
111
|
|
|
112
|
-
class ConnectableObjectMixin
|
|
112
|
+
class ConnectableObjectMixin:
|
|
113
113
|
"""Mixin which implements IConnectionPointContainer.
|
|
114
114
|
|
|
115
115
|
Call Fire_Event(interface, methodname, *args, **kw) to fire an
|
|
@@ -122,7 +122,7 @@ class ConnectableObjectMixin(object):
|
|
|
122
122
|
_reg_typelib_: ClassVar[Tuple[str, int, int]]
|
|
123
123
|
|
|
124
124
|
def __init__(self) -> None:
|
|
125
|
-
super(
|
|
125
|
+
super().__init__()
|
|
126
126
|
self.__connections: Dict[Type[IDispatch], ConnectionPointImpl] = {}
|
|
127
127
|
|
|
128
128
|
tlib = LoadRegTypeLib(*self._reg_typelib_)
|
|
@@ -22,7 +22,7 @@ class ClassFactory(COMObject):
|
|
|
22
22
|
_com_interfaces_ = [IClassFactory]
|
|
23
23
|
|
|
24
24
|
def __init__(self, cls: Type[COMObject]) -> None:
|
|
25
|
-
super(
|
|
25
|
+
super().__init__()
|
|
26
26
|
self._cls = cls
|
|
27
27
|
|
|
28
28
|
def IClassFactory_CreateInstance(
|
|
@@ -92,7 +92,7 @@ def _setup_logging(clsid: GUID) -> None:
|
|
|
92
92
|
|
|
93
93
|
try:
|
|
94
94
|
hkey = winreg.OpenKey(winreg.HKEY_CLASSES_ROOT, r"CLSID\%s\Logging" % clsid)
|
|
95
|
-
except
|
|
95
|
+
except OSError:
|
|
96
96
|
return
|
|
97
97
|
from comtypes.logutil import NTDebugHandler
|
|
98
98
|
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
import queue
|
|
3
|
-
from ctypes import HRESULT,
|
|
3
|
+
from ctypes import HRESULT, OleDLL, byref, c_ulong, c_void_p
|
|
4
4
|
from ctypes.wintypes import DWORD, LPDWORD
|
|
5
5
|
from typing import TYPE_CHECKING, Any, Literal, Optional, Sequence, Type
|
|
6
6
|
|
|
7
7
|
import comtypes
|
|
8
8
|
from comtypes import GUID, COMObject, IUnknown, hresult
|
|
9
|
+
from comtypes.GUID import REFCLSID
|
|
9
10
|
from comtypes.server import IClassFactory
|
|
10
11
|
|
|
11
12
|
if TYPE_CHECKING:
|
|
@@ -23,7 +24,6 @@ REGCLS_SURROGATE = 8 # must be used when a surrogate process
|
|
|
23
24
|
|
|
24
25
|
_ole32 = OleDLL("ole32")
|
|
25
26
|
|
|
26
|
-
REFCLSID = POINTER(GUID)
|
|
27
27
|
_CoRegisterClassObject = _ole32.CoRegisterClassObject
|
|
28
28
|
_CoRegisterClassObject.argtypes = [REFCLSID, c_void_p, DWORD, DWORD, LPDWORD]
|
|
29
29
|
_CoRegisterClassObject.restype = HRESULT
|
|
@@ -45,7 +45,7 @@ class ClassFactory(COMObject):
|
|
|
45
45
|
regcls: int = REGCLS_MULTIPLEUSE
|
|
46
46
|
|
|
47
47
|
def __init__(self, cls: Type[COMObject], *args, **kw) -> None:
|
|
48
|
-
super(
|
|
48
|
+
super().__init__()
|
|
49
49
|
self._cls = cls
|
|
50
50
|
self._register_class()
|
|
51
51
|
self._args = args
|
|
@@ -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,
|
|
@@ -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):
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import doctest
|
|
2
|
+
import sys
|
|
2
3
|
import unittest
|
|
3
4
|
from ctypes import pointer
|
|
4
5
|
from typing import Any
|
|
@@ -22,7 +23,7 @@ except ImportError:
|
|
|
22
23
|
def setUpModule():
|
|
23
24
|
try:
|
|
24
25
|
register(comtypes.test.TestComServer.TestComServer)
|
|
25
|
-
except
|
|
26
|
+
except OSError as e:
|
|
26
27
|
if e.winerror != 5: # [Error 5] Access is denied
|
|
27
28
|
raise e
|
|
28
29
|
raise unittest.SkipTest(
|
|
@@ -35,7 +36,7 @@ def tearDownModule():
|
|
|
35
36
|
unregister(comtypes.test.TestComServer.TestComServer)
|
|
36
37
|
|
|
37
38
|
|
|
38
|
-
class BaseServerTest
|
|
39
|
+
class BaseServerTest:
|
|
39
40
|
def create_object(self) -> Any: ...
|
|
40
41
|
|
|
41
42
|
def _find_memleak(self, func):
|
|
@@ -116,6 +117,11 @@ class TestInproc(BaseServerTest, unittest.TestCase):
|
|
|
116
117
|
"TestComServerLib.TestComServer", clsctx=comtypes.CLSCTX_INPROC_SERVER
|
|
117
118
|
)
|
|
118
119
|
|
|
120
|
+
@unittest.skip("Fails occasionally with a memory leak on INPROC.")
|
|
121
|
+
def test_eval(self):
|
|
122
|
+
# This test sometimes leaks memory when run as an in-process server.
|
|
123
|
+
pass
|
|
124
|
+
|
|
119
125
|
|
|
120
126
|
class TestLocalServer(BaseServerTest, unittest.TestCase):
|
|
121
127
|
def create_object(self):
|
|
@@ -135,6 +141,13 @@ class TestInproc_win32com(BaseServerTest, unittest.TestCase):
|
|
|
135
141
|
def create_object(self):
|
|
136
142
|
return Dispatch("TestComServerLib.TestComServer")
|
|
137
143
|
|
|
144
|
+
if sys.version_info >= (3, 14):
|
|
145
|
+
|
|
146
|
+
@unittest.skip("Fails occasionally with a memory leak on INPROC.")
|
|
147
|
+
def test_eval(self):
|
|
148
|
+
# This test sometimes leaks memory when run as an in-process server.
|
|
149
|
+
pass
|
|
150
|
+
|
|
138
151
|
# These tests make no sense with win32com, override to disable them:
|
|
139
152
|
@unittest.skip("This test make no sense with win32com.")
|
|
140
153
|
def test_get_typeinfo(self):
|
|
@@ -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
|
|
|
@@ -127,8 +125,7 @@ PY_VER = "Python {0}.{1}.{2}".format(*sys.version_info[:3])
|
|
|
127
125
|
|
|
128
126
|
@unittest.skipIf(IMPORT_FAILED, "This depends on Excel.")
|
|
129
127
|
@unittest.skipIf(
|
|
130
|
-
sys.version_info[:2] == (3,
|
|
131
|
-
or sys.version_info[:2] == (3, 9)
|
|
128
|
+
sys.version_info[:2] == (3, 9)
|
|
132
129
|
or (sys.version_info[:2] == (3, 10) and sys.version_info < (3, 10, 10))
|
|
133
130
|
or (sys.version_info[:2] == (3, 11) and sys.version_info < (3, 11, 2)),
|
|
134
131
|
f"This fails in {PY_VER}. See https://github.com/enthought/comtypes/issues/212",
|