comtypes 1.4.8__zip → 1.4.9__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.8 → comtypes-1.4.9}/CHANGES.txt +21 -0
- {comtypes-1.4.8/comtypes.egg-info → comtypes-1.4.9}/PKG-INFO +2 -2
- {comtypes-1.4.8 → comtypes-1.4.9}/README.md +1 -1
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/GUID.py +6 -5
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/__init__.py +16 -5
- comtypes-1.4.9/comtypes/_comobject.py +507 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/_memberspec.py +80 -8
- comtypes-1.4.9/comtypes/_post_coinit/_cominterface_meta_patcher.py +153 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/_post_coinit/misc.py +1 -1
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/_post_coinit/unknwn.py +25 -171
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/_safearray.py +1 -2
- comtypes-1.4.9/comtypes/_vtbl.py +448 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/automation.py +36 -45
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/client/_code_cache.py +4 -4
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/client/_constants.py +1 -1
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/client/_events.py +1 -1
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/client/_generate.py +4 -8
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/client/lazybind.py +2 -2
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/errorinfo.py +3 -3
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/git.py +1 -2
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/hints.pyi +7 -15
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/safearray.py +10 -0
- comtypes-1.4.9/comtypes/server/__init__.py +86 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/server/inprocserver.py +22 -17
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/server/localserver.py +28 -16
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/server/register.py +61 -73
- comtypes-1.4.9/comtypes/server/w_getopt.py +48 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/shelllink.py +3 -26
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/__init__.py +9 -11
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_BSTR.py +4 -7
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_avmc.py +1 -1
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_casesensitivity.py +3 -5
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_collections.py +3 -3
- comtypes-1.4.9/comtypes/test/test_comobject.py +146 -0
- comtypes-1.4.9/comtypes/test/test_comserver.py +319 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_createwrappers.py +2 -4
- comtypes-1.4.9/comtypes/test/test_dispinterface.py +153 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_excel.py +22 -12
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_ie.py +2 -5
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_inout_args.py +7 -4
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_midl_safearray_create.py +9 -1
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_outparam.py +17 -10
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_safearray.py +1 -90
- comtypes-1.4.9/comtypes/test/test_server.py +350 -0
- comtypes-1.4.9/comtypes/test/test_server_register.py +536 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_showevents.py +7 -17
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_variant.py +0 -17
- comtypes-1.4.9/comtypes/test/test_w_getopt.py +29 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_win32com_interop.py +80 -36
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_wmi.py +0 -3
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/tools/codegenerator/codegenerator.py +62 -68
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/tools/codegenerator/helpers.py +8 -8
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/tools/codegenerator/packing.py +4 -4
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/tools/codegenerator/typeannotator.py +7 -7
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/tools/typedesc.py +1 -6
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/typeinfo.py +11 -22
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/viewobject.py +1 -5
- {comtypes-1.4.8 → comtypes-1.4.9/comtypes.egg-info}/PKG-INFO +2 -2
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes.egg-info/SOURCES.txt +6 -3
- {comtypes-1.4.8 → comtypes-1.4.9}/pyproject.toml +1 -0
- comtypes-1.4.8/comtypes/_comobject.py +0 -833
- comtypes-1.4.8/comtypes/_idl_stuff.py +0 -67
- comtypes-1.4.8/comtypes/server/__init__.py +0 -70
- comtypes-1.4.8/comtypes/server/w_getopt.py +0 -75
- comtypes-1.4.8/comtypes/test/test_comserver.py +0 -239
- comtypes-1.4.8/comtypes/test/test_dispinterface.py +0 -137
- comtypes-1.4.8/comtypes/test/test_propputref.py +0 -40
- comtypes-1.4.8/comtypes/test/test_server.py +0 -354
- {comtypes-1.4.8 → comtypes-1.4.9}/LICENSE.txt +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/MANIFEST.in +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/_meta.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/_npsupport.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/_post_coinit/__init__.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/_post_coinit/bstr.py +0 -0
- /comtypes-1.4.8/comtypes/_py_instance_method.py → /comtypes-1.4.9/comtypes/_post_coinit/instancemethod.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/_tlib_version_checker.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/clear_cache.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/client/__init__.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/client/dynamic.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/connectionpoints.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/hresult.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/logutil.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/messageloop.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/patcher.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/persist.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/server/automation.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/server/connectionpoints.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/stream.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/TestComServer.idl +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/TestComServer.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/TestComServer.tlb +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/TestDispServer.idl +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/TestDispServer.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/TestDispServer.tlb +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/find_memleak.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/mylib.idl +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/mylib.tlb +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/mytypelib.idl +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/runtests.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/setup.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_DISPPARAMS.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_GUID.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_QueryService.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_agilent.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_basic.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_clear_cache.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_client.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_client_dynamic.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_client_regenerate_modules.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_dict.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_dispifc_records.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_dispifc_safearrays.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_dyndispatch.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_findgendir.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_getactiveobj.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_ienum.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_imfattributes.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_jscript.js +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_monikers.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_msscript.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_npsupport.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_persist.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_pump_events.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_recordinfo.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_sapi.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_shelllink.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_storage.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_stream.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_subinterface.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_typeannotator.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_typeinfo.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_urlhistory.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_word.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/urlhist.tlb +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/tools/__init__.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/tools/codegenerator/__init__.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/tools/codegenerator/modulenamer.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/tools/codegenerator/namespaces.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/tools/tlbparser.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/tools/typedesc_base.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/util.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes.egg-info/dependency_links.txt +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes.egg-info/entry_points.txt +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes.egg-info/top_level.txt +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/setup.cfg +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/setup.py +0 -0
|
@@ -36,17 +36,18 @@ Now, debug the object, and when done delete logging info:
|
|
|
36
36
|
python mycomobj.py /nodebug
|
|
37
37
|
"""
|
|
38
38
|
|
|
39
|
-
import
|
|
39
|
+
import logging
|
|
40
40
|
import os
|
|
41
|
+
import sys
|
|
41
42
|
import winreg
|
|
42
|
-
import
|
|
43
|
+
from ctypes import WinError, c_ulong, c_wchar_p, create_string_buffer, sizeof, windll
|
|
44
|
+
from typing import Iterator, Tuple
|
|
43
45
|
|
|
44
46
|
import comtypes
|
|
45
|
-
|
|
47
|
+
import comtypes.server.inprocserver
|
|
46
48
|
from comtypes.hresult import *
|
|
47
49
|
from comtypes.server import w_getopt
|
|
48
|
-
|
|
49
|
-
from ctypes import windll, c_ulong, c_wchar_p, WinError, sizeof, create_string_buffer
|
|
50
|
+
from comtypes.typeinfo import REGKIND_REGISTER, LoadTypeLibEx, UnRegisterTypeLib
|
|
50
51
|
|
|
51
52
|
_debug = logging.getLogger(__name__).debug
|
|
52
53
|
|
|
@@ -100,7 +101,7 @@ class Registrar(object):
|
|
|
100
101
|
'DeleteKey( %s\\CLSID\\%s\\Logging"'
|
|
101
102
|
% (_explain(winreg.HKEY_CLASSES_ROOT), clsid)
|
|
102
103
|
)
|
|
103
|
-
hkey = winreg.OpenKey(winreg.HKEY_CLASSES_ROOT,
|
|
104
|
+
hkey = winreg.OpenKey(winreg.HKEY_CLASSES_ROOT, rf"CLSID\{clsid}")
|
|
104
105
|
winreg.DeleteKey(hkey, "Logging")
|
|
105
106
|
except WindowsError as detail:
|
|
106
107
|
if get_winerror(detail) != 2:
|
|
@@ -115,7 +116,7 @@ class Registrar(object):
|
|
|
115
116
|
'CreateKey( %s\\CLSID\\%s\\Logging"'
|
|
116
117
|
% (_explain(winreg.HKEY_CLASSES_ROOT), clsid)
|
|
117
118
|
)
|
|
118
|
-
hkey = winreg.CreateKey(winreg.HKEY_CLASSES_ROOT,
|
|
119
|
+
hkey = winreg.CreateKey(winreg.HKEY_CLASSES_ROOT, rf"CLSID\{clsid}\Logging")
|
|
119
120
|
for item in levels:
|
|
120
121
|
name, value = item.split("=")
|
|
121
122
|
v = getattr(logging, value)
|
|
@@ -147,8 +148,7 @@ class Registrar(object):
|
|
|
147
148
|
self._register(cls, executable)
|
|
148
149
|
|
|
149
150
|
def _register(self, cls, executable=None):
|
|
150
|
-
table =
|
|
151
|
-
table.sort()
|
|
151
|
+
table = sorted(RegistryEntries(cls))
|
|
152
152
|
_debug("Registering %s", cls)
|
|
153
153
|
for hkey, subkey, valuename, value in table:
|
|
154
154
|
_debug("[%s\\%s]", _explain(hkey), subkey)
|
|
@@ -159,7 +159,7 @@ class Registrar(object):
|
|
|
159
159
|
tlib = getattr(cls, "_reg_typelib_", None)
|
|
160
160
|
if tlib is not None:
|
|
161
161
|
if hasattr(sys, "frozendllhandle"):
|
|
162
|
-
dll =
|
|
162
|
+
dll = _get_serverdll()
|
|
163
163
|
_debug("LoadTypeLibEx(%s, REGKIND_REGISTER)", dll)
|
|
164
164
|
LoadTypeLibEx(dll, REGKIND_REGISTER)
|
|
165
165
|
else:
|
|
@@ -184,7 +184,7 @@ class Registrar(object):
|
|
|
184
184
|
def _unregister(self, cls, force=False):
|
|
185
185
|
# If force==False, we only remove those entries that we
|
|
186
186
|
# actually would have written. It seems ATL does the same.
|
|
187
|
-
table = [t[:2] for t in
|
|
187
|
+
table = [t[:2] for t in RegistryEntries(cls)]
|
|
188
188
|
# only unique entries
|
|
189
189
|
table = list(set(table))
|
|
190
190
|
table.sort()
|
|
@@ -214,23 +214,29 @@ class Registrar(object):
|
|
|
214
214
|
raise
|
|
215
215
|
_debug("Done")
|
|
216
216
|
|
|
217
|
-
def _get_serverdll(self):
|
|
218
|
-
"""Return the pathname of the dll hosting the COM object."""
|
|
219
|
-
handle = getattr(sys, "frozendllhandle", None)
|
|
220
|
-
if handle is not None:
|
|
221
|
-
buf = create_string_buffer(260)
|
|
222
|
-
windll.kernel32.GetModuleFileNameA(handle, buf, sizeof(buf))
|
|
223
|
-
return buf[:]
|
|
224
|
-
import _ctypes
|
|
225
217
|
|
|
226
|
-
|
|
218
|
+
def _get_serverdll():
|
|
219
|
+
"""Return the pathname of the dll hosting the COM object."""
|
|
220
|
+
handle = getattr(sys, "frozendllhandle", None)
|
|
221
|
+
if handle is not None:
|
|
222
|
+
buf = create_string_buffer(260)
|
|
223
|
+
windll.kernel32.GetModuleFileNameA(handle, buf, sizeof(buf))
|
|
224
|
+
return buf[:]
|
|
225
|
+
import _ctypes
|
|
226
|
+
|
|
227
|
+
return _ctypes.__file__
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
class RegistryEntries(object):
|
|
231
|
+
def __init__(self, cls):
|
|
232
|
+
self._cls = cls
|
|
227
233
|
|
|
228
234
|
def _get_full_classname(self, cls):
|
|
229
235
|
"""Return <modulename>.<classname> for 'cls'."""
|
|
230
236
|
modname = cls.__module__
|
|
231
237
|
if modname == "__main__":
|
|
232
238
|
modname = os.path.splitext(os.path.basename(sys.argv[0]))[0]
|
|
233
|
-
return "
|
|
239
|
+
return f"{modname}.{cls.__name__}"
|
|
234
240
|
|
|
235
241
|
def _get_pythonpath(self, cls):
|
|
236
242
|
"""Return the filesystem path of the module containing 'cls'."""
|
|
@@ -238,8 +244,8 @@ class Registrar(object):
|
|
|
238
244
|
dirname = os.path.dirname(sys.modules[modname].__file__)
|
|
239
245
|
return os.path.abspath(dirname)
|
|
240
246
|
|
|
241
|
-
def
|
|
242
|
-
"""Return a
|
|
247
|
+
def __iter__(self) -> Iterator[Tuple[int, str, str, str]]:
|
|
248
|
+
"""Return a iterator of tuples containing registry entries.
|
|
243
249
|
|
|
244
250
|
The tuples must be (key, subkey, name, value).
|
|
245
251
|
|
|
@@ -259,16 +265,13 @@ class Registrar(object):
|
|
|
259
265
|
Note that the first part of the progid string is typically the
|
|
260
266
|
IDL library name of the type library containing the coclass.
|
|
261
267
|
"""
|
|
268
|
+
cls = self._cls
|
|
262
269
|
HKCR = winreg.HKEY_CLASSES_ROOT
|
|
263
270
|
|
|
264
|
-
# table format: rootkey, subkey, valuename, value
|
|
265
|
-
table = []
|
|
266
|
-
append = lambda *args: table.append(args)
|
|
267
|
-
|
|
268
271
|
# basic entry - names the comobject
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
+
|
|
273
|
+
# that's the only required attribute for registration
|
|
274
|
+
reg_clsid = str(cls._reg_clsid_)
|
|
272
275
|
reg_desc = getattr(cls, "_reg_desc_", "")
|
|
273
276
|
if not reg_desc:
|
|
274
277
|
# Simple minded algorithm to construct a description from
|
|
@@ -278,95 +281,83 @@ class Registrar(object):
|
|
|
278
281
|
)
|
|
279
282
|
if reg_desc:
|
|
280
283
|
reg_desc = reg_desc.replace(".", " ")
|
|
281
|
-
|
|
284
|
+
yield (HKCR, f"CLSID\\{reg_clsid}", "", reg_desc)
|
|
282
285
|
|
|
283
286
|
reg_progid = getattr(cls, "_reg_progid_", None)
|
|
284
287
|
if reg_progid:
|
|
285
288
|
# for ProgIDFromCLSID:
|
|
286
|
-
|
|
289
|
+
yield (HKCR, f"CLSID\\{reg_clsid}\\ProgID", "", reg_progid) # 1
|
|
287
290
|
|
|
288
291
|
# for CLSIDFromProgID
|
|
289
292
|
if reg_desc:
|
|
290
|
-
|
|
291
|
-
|
|
293
|
+
yield (HKCR, reg_progid, "", reg_desc) # 2
|
|
294
|
+
yield (HKCR, f"{reg_progid}\\CLSID", "", reg_clsid) # 3
|
|
292
295
|
|
|
293
296
|
reg_novers_progid = getattr(cls, "_reg_novers_progid_", None)
|
|
294
297
|
if reg_novers_progid:
|
|
295
|
-
|
|
298
|
+
yield (
|
|
296
299
|
HKCR,
|
|
297
|
-
"CLSID
|
|
300
|
+
f"CLSID\\{reg_clsid}\\VersionIndependentProgID", # 1a
|
|
298
301
|
"",
|
|
299
302
|
reg_novers_progid,
|
|
300
303
|
)
|
|
301
304
|
if reg_desc:
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
+
yield (HKCR, reg_novers_progid, "", reg_desc) # 2a
|
|
306
|
+
yield (HKCR, f"{reg_novers_progid}\\CurVer", "", reg_progid) #
|
|
307
|
+
yield (HKCR, f"{reg_novers_progid}\\CLSID", "", reg_clsid) # 3a
|
|
305
308
|
|
|
306
|
-
clsctx = getattr(cls, "_reg_clsctx_", 0)
|
|
309
|
+
clsctx: int = getattr(cls, "_reg_clsctx_", 0)
|
|
310
|
+
localsvr_ctx = bool(clsctx & comtypes.CLSCTX_LOCAL_SERVER)
|
|
311
|
+
inprocsvr_ctx = bool(clsctx & comtypes.CLSCTX_INPROC_SERVER)
|
|
307
312
|
|
|
308
|
-
if
|
|
309
|
-
sys, "frozendllhandle"
|
|
310
|
-
):
|
|
313
|
+
if localsvr_ctx and not hasattr(sys, "frozendllhandle"):
|
|
311
314
|
exe = sys.executable
|
|
312
315
|
if " " in exe:
|
|
313
|
-
exe = '"
|
|
316
|
+
exe = f'"{exe}"'
|
|
314
317
|
if not hasattr(sys, "frozen"):
|
|
315
318
|
if not __debug__:
|
|
316
|
-
exe = "
|
|
319
|
+
exe = f"{exe} -O"
|
|
317
320
|
script = os.path.abspath(sys.modules[cls.__module__].__file__)
|
|
318
321
|
if " " in script:
|
|
319
|
-
script = '"
|
|
320
|
-
|
|
321
|
-
HKCR,
|
|
322
|
-
"CLSID\\%s\\LocalServer32" % reg_clsid,
|
|
323
|
-
"",
|
|
324
|
-
"%s %s" % (exe, script),
|
|
325
|
-
)
|
|
322
|
+
script = f'"{script}"'
|
|
323
|
+
yield (HKCR, rf"CLSID\{reg_clsid}\LocalServer32", "", f"{exe} {script}")
|
|
326
324
|
else:
|
|
327
|
-
|
|
325
|
+
yield (HKCR, rf"CLSID\{reg_clsid}\LocalServer32", "", f"{exe}")
|
|
328
326
|
|
|
329
327
|
# Register InprocServer32 only when run from script or from
|
|
330
328
|
# py2exe dll server, not from py2exe exe server.
|
|
331
|
-
if
|
|
332
|
-
|
|
333
|
-
"dll",
|
|
334
|
-
):
|
|
335
|
-
append(
|
|
336
|
-
HKCR, "CLSID\\%s\\InprocServer32" % reg_clsid, "", self._get_serverdll()
|
|
337
|
-
)
|
|
329
|
+
if inprocsvr_ctx and getattr(sys, "frozen", None) in (None, "dll"):
|
|
330
|
+
yield (HKCR, rf"CLSID\{reg_clsid}\InprocServer32", "", _get_serverdll())
|
|
338
331
|
# only for non-frozen inproc servers the PythonPath/PythonClass is needed.
|
|
339
332
|
if (
|
|
340
333
|
not hasattr(sys, "frozendllhandle")
|
|
341
334
|
or not comtypes.server.inprocserver._clsid_to_class
|
|
342
335
|
):
|
|
343
|
-
|
|
336
|
+
yield (
|
|
344
337
|
HKCR,
|
|
345
|
-
"CLSID
|
|
338
|
+
rf"CLSID\{reg_clsid}\InprocServer32",
|
|
346
339
|
"PythonClass",
|
|
347
340
|
self._get_full_classname(cls),
|
|
348
341
|
)
|
|
349
|
-
|
|
342
|
+
yield (
|
|
350
343
|
HKCR,
|
|
351
|
-
"CLSID
|
|
344
|
+
rf"CLSID\{reg_clsid}\InprocServer32",
|
|
352
345
|
"PythonPath",
|
|
353
346
|
self._get_pythonpath(cls),
|
|
354
347
|
)
|
|
355
348
|
|
|
356
349
|
reg_threading = getattr(cls, "_reg_threading_", None)
|
|
357
350
|
if reg_threading is not None:
|
|
358
|
-
|
|
351
|
+
yield (
|
|
359
352
|
HKCR,
|
|
360
|
-
"CLSID
|
|
353
|
+
rf"CLSID\{reg_clsid}\InprocServer32",
|
|
361
354
|
"ThreadingModel",
|
|
362
355
|
reg_threading,
|
|
363
356
|
)
|
|
364
357
|
|
|
365
358
|
reg_tlib = getattr(cls, "_reg_typelib_", None)
|
|
366
359
|
if reg_tlib is not None:
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
return table
|
|
360
|
+
yield (HKCR, rf"CLSID\{reg_clsid}\Typelib", "", reg_tlib[0])
|
|
370
361
|
|
|
371
362
|
|
|
372
363
|
################################################################
|
|
@@ -381,10 +372,7 @@ def unregister(cls):
|
|
|
381
372
|
|
|
382
373
|
|
|
383
374
|
def UseCommandLine(*classes):
|
|
384
|
-
usage =
|
|
385
|
-
"""Usage: %s [-regserver] [-unregserver] [-nodebug] [-f logformat] [-l loggername=level]"""
|
|
386
|
-
% sys.argv[0]
|
|
387
|
-
)
|
|
375
|
+
usage = f"""Usage: {sys.argv[0]} [-regserver] [-unregserver] [-nodebug] [-f logformat] [-l loggername=level]"""
|
|
388
376
|
opts, args = w_getopt.w_getopt(
|
|
389
377
|
sys.argv[1:], "regserver unregserver embedding l: f: nodebug"
|
|
390
378
|
)
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
from typing import Sequence, Tuple
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class GetoptError(Exception):
|
|
5
|
+
pass
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def w_getopt(
|
|
9
|
+
args: Sequence[str], options: str
|
|
10
|
+
) -> Tuple[Sequence[Tuple[str, str]], Sequence[str]]:
|
|
11
|
+
"""A getopt for Windows.
|
|
12
|
+
|
|
13
|
+
Options may start with either '-' or '/', the option names may
|
|
14
|
+
have more than one letter (/tlb or -RegServer), and option names
|
|
15
|
+
are case insensitive.
|
|
16
|
+
|
|
17
|
+
Returns two elements, just as getopt.getopt. The first is a list
|
|
18
|
+
of (option, value) pairs in the same way getopt.getopt does, but
|
|
19
|
+
there is no '-' or '/' prefix to the option name, and the option
|
|
20
|
+
name is always lower case. The second is the list of arguments
|
|
21
|
+
which do not belong to an option.
|
|
22
|
+
|
|
23
|
+
Different from getopt.getopt, a single argument not belonging to an option
|
|
24
|
+
does not terminate parsing.
|
|
25
|
+
"""
|
|
26
|
+
opts = []
|
|
27
|
+
arguments = []
|
|
28
|
+
while args:
|
|
29
|
+
if args[0][:1] in "/-":
|
|
30
|
+
arg = args[0][1:] # strip the '-' or '/'
|
|
31
|
+
arg = arg.lower()
|
|
32
|
+
|
|
33
|
+
if arg + ":" in options:
|
|
34
|
+
try:
|
|
35
|
+
opts.append((arg, args[1]))
|
|
36
|
+
except IndexError:
|
|
37
|
+
raise GetoptError(f"option '{args[0]}' requires an argument")
|
|
38
|
+
args = args[1:]
|
|
39
|
+
elif arg in options:
|
|
40
|
+
opts.append((arg, ""))
|
|
41
|
+
else:
|
|
42
|
+
raise GetoptError(f"invalid option '{args[0]}'")
|
|
43
|
+
args = args[1:]
|
|
44
|
+
else:
|
|
45
|
+
arguments.append(args[0])
|
|
46
|
+
args = args[1:]
|
|
47
|
+
|
|
48
|
+
return opts, arguments
|
|
@@ -2,7 +2,7 @@ from ctypes import c_char_p, c_int, c_short, c_wchar_p
|
|
|
2
2
|
from ctypes import POINTER
|
|
3
3
|
from ctypes import byref, create_string_buffer, create_unicode_buffer
|
|
4
4
|
from ctypes.wintypes import DWORD, WIN32_FIND_DATAA, WIN32_FIND_DATAW, MAX_PATH
|
|
5
|
-
from typing import Tuple, TYPE_CHECKING
|
|
5
|
+
from typing import Tuple, TYPE_CHECKING, Literal
|
|
6
6
|
|
|
7
7
|
from comtypes import IUnknown, GUID, COMMETHOD, HRESULT, CoClass
|
|
8
8
|
|
|
@@ -143,7 +143,7 @@ class IShellLinkA(IUnknown):
|
|
|
143
143
|
def ShowCmd(self, piShowCmd: int) -> None: ...
|
|
144
144
|
def SetIconLocation(self, pszIconPath: bytes, iIcon: int) -> hints.Hresult: ...
|
|
145
145
|
def SetRelativePath(
|
|
146
|
-
self, pszPathRel: bytes, dwReserved:
|
|
146
|
+
self, pszPathRel: bytes, dwReserved: Literal[0]
|
|
147
147
|
) -> hints.Hresult: ...
|
|
148
148
|
def Resolve(self, hwnd: int, fFlags: int) -> hints.Hresult: ...
|
|
149
149
|
def SetPath(self, pszFile: bytes) -> hints.Hresult: ...
|
|
@@ -278,7 +278,7 @@ class IShellLinkW(IUnknown):
|
|
|
278
278
|
def ShowCmd(self, piShowCmd: int) -> None: ...
|
|
279
279
|
def SetIconLocation(self, pszIconPath: str, iIcon: int) -> hints.Hresult: ...
|
|
280
280
|
def SetRelativePath(
|
|
281
|
-
self, pszPathRel: str, dwReserved:
|
|
281
|
+
self, pszPathRel: str, dwReserved: Literal[0]
|
|
282
282
|
) -> hints.Hresult: ...
|
|
283
283
|
def Resolve(self, hwnd: int, fFlags: int) -> hints.Hresult: ...
|
|
284
284
|
def SetPath(self, pszFile: str) -> hints.Hresult: ...
|
|
@@ -317,26 +317,3 @@ class ShellLink(CoClass):
|
|
|
317
317
|
_reg_clsid_ = GUID("{00021401-0000-0000-C000-000000000046}")
|
|
318
318
|
_idlflags_ = []
|
|
319
319
|
_com_interfaces_ = [IShellLinkW, IShellLinkA]
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
if __name__ == "__main__":
|
|
323
|
-
import sys
|
|
324
|
-
import comtypes
|
|
325
|
-
from comtypes.client import CreateObject
|
|
326
|
-
from comtypes.persist import IPersistFile
|
|
327
|
-
|
|
328
|
-
shortcut = CreateObject(ShellLink)
|
|
329
|
-
print(shortcut)
|
|
330
|
-
##help(shortcut)
|
|
331
|
-
|
|
332
|
-
shortcut.SetPath(sys.executable)
|
|
333
|
-
|
|
334
|
-
shortcut.SetDescription("Python %s" % sys.version)
|
|
335
|
-
shortcut.SetIconLocation(sys.executable, 1)
|
|
336
|
-
|
|
337
|
-
print(shortcut.GetPath(2))
|
|
338
|
-
print(shortcut.GetIconLocation())
|
|
339
|
-
|
|
340
|
-
pf = shortcut.QueryInterface(IPersistFile)
|
|
341
|
-
pf.Save("foo.lnk", True)
|
|
342
|
-
print(pf.GetCurFile())
|
|
@@ -64,7 +64,7 @@ def requires(resource, msg=None):
|
|
|
64
64
|
return
|
|
65
65
|
if not is_resource_enabled(resource):
|
|
66
66
|
if msg is None:
|
|
67
|
-
msg = "Use of the
|
|
67
|
+
msg = f"Use of the `{resource}` resource not enabled"
|
|
68
68
|
raise ResourceDenied(msg)
|
|
69
69
|
|
|
70
70
|
|
|
@@ -94,12 +94,10 @@ def get_tests(package, mask, verbosity):
|
|
|
94
94
|
except ResourceDenied as detail:
|
|
95
95
|
skipped.append(modname)
|
|
96
96
|
if verbosity > 1:
|
|
97
|
-
print("Skipped
|
|
97
|
+
print(f"Skipped {modname}: {detail}", file=sys.stderr)
|
|
98
98
|
continue
|
|
99
99
|
except Exception as detail:
|
|
100
|
-
print(
|
|
101
|
-
"Warning: could not import %s: %s" % (modname, detail), file=sys.stderr
|
|
102
|
-
)
|
|
100
|
+
print(f"Warning: could not import {modname}: {detail}", file=sys.stderr)
|
|
103
101
|
continue
|
|
104
102
|
for name in dir(mod):
|
|
105
103
|
if name.startswith("_"):
|
|
@@ -149,9 +147,9 @@ def test_with_refcounts(runner, verbosity, testcase):
|
|
|
149
147
|
cleanup()
|
|
150
148
|
refcounts[i] = sys.gettotalrefcount() - rc
|
|
151
149
|
if [_f for _f in refcounts if _f]:
|
|
152
|
-
print("
|
|
150
|
+
print(f"{testcase} leaks:\n\t", refcounts)
|
|
153
151
|
elif verbosity:
|
|
154
|
-
print("
|
|
152
|
+
print(f"{testcase}: ok.")
|
|
155
153
|
|
|
156
154
|
|
|
157
155
|
class TestRunner(unittest.TextTestRunner):
|
|
@@ -180,21 +178,21 @@ class TestRunner(unittest.TextTestRunner):
|
|
|
180
178
|
len(skipped) != 1 and "s" or "",
|
|
181
179
|
)
|
|
182
180
|
)
|
|
183
|
-
self.stream.writeln("Unavailable resources:
|
|
181
|
+
self.stream.writeln(f"Unavailable resources: {', '.join(requested)}")
|
|
184
182
|
else:
|
|
185
183
|
self.stream.writeln(
|
|
186
|
-
"Ran
|
|
184
|
+
f"Ran {run} test{'s' if run != 1 else ''} in {timeTaken:.3f}s"
|
|
187
185
|
)
|
|
188
186
|
self.stream.writeln()
|
|
189
187
|
if not result.wasSuccessful():
|
|
190
188
|
self.stream.write("FAILED (")
|
|
191
189
|
failed, errored = list(map(len, (result.failures, result.errors)))
|
|
192
190
|
if failed:
|
|
193
|
-
self.stream.write("failures
|
|
191
|
+
self.stream.write(f"failures={failed}")
|
|
194
192
|
if errored:
|
|
195
193
|
if failed:
|
|
196
194
|
self.stream.write(", ")
|
|
197
|
-
self.stream.write("errors
|
|
195
|
+
self.stream.write(f"errors={errored}")
|
|
198
196
|
self.stream.writeln(")")
|
|
199
197
|
else:
|
|
200
198
|
self.stream.writeln("OK")
|
|
@@ -1,17 +1,14 @@
|
|
|
1
|
-
import unittest
|
|
2
|
-
from ctypes import
|
|
3
|
-
from comtypes import BSTR
|
|
4
|
-
from comtypes.test import requires
|
|
5
|
-
|
|
6
|
-
##requires("memleaks")
|
|
1
|
+
import unittest
|
|
2
|
+
from ctypes import WINFUNCTYPE, c_uint, c_void_p, oledll, windll
|
|
7
3
|
|
|
4
|
+
from comtypes import BSTR
|
|
8
5
|
from comtypes.test.find_memleak import find_memleak
|
|
9
6
|
|
|
10
7
|
|
|
11
8
|
class Test(unittest.TestCase):
|
|
12
9
|
def check_leaks(self, func, limit=0):
|
|
13
10
|
bytes = find_memleak(func)
|
|
14
|
-
self.assertFalse(bytes > limit, "Leaks
|
|
11
|
+
self.assertFalse(bytes > limit, f"Leaks {bytes} bytes")
|
|
15
12
|
|
|
16
13
|
def test_creation(self):
|
|
17
14
|
def doit():
|
|
@@ -37,7 +37,7 @@ class Test(unittest.TestCase):
|
|
|
37
37
|
|
|
38
38
|
def check_leaks(self, func, limit=0):
|
|
39
39
|
bytes = find_memleak(func)
|
|
40
|
-
self.assertFalse(bytes > limit, "Leaks
|
|
40
|
+
self.assertFalse(bytes > limit, f"Leaks {bytes} bytes")
|
|
41
41
|
|
|
42
42
|
|
|
43
43
|
if __name__ == "__main__":
|
|
@@ -31,13 +31,11 @@ class TestCase(unittest.TestCase):
|
|
|
31
31
|
# names in the base class __map_case__ must also appear in the
|
|
32
32
|
# subclass.
|
|
33
33
|
for name in iem.IWebBrowser.__map_case__:
|
|
34
|
-
self.assertTrue(
|
|
35
|
-
|
|
36
|
-
)
|
|
37
|
-
self.assertTrue(name in iem.IWebBrowser2.__map_case__, "%s missing" % name)
|
|
34
|
+
self.assertTrue(name in iem.IWebBrowserApp.__map_case__, f"{name} missing")
|
|
35
|
+
self.assertTrue(name in iem.IWebBrowser2.__map_case__, f"{name} missing")
|
|
38
36
|
|
|
39
37
|
for name in iem.IWebBrowserApp.__map_case__:
|
|
40
|
-
self.assertTrue(name in iem.IWebBrowser2.__map_case__, "
|
|
38
|
+
self.assertTrue(name in iem.IWebBrowser2.__map_case__, f"{name} missing")
|
|
41
39
|
|
|
42
40
|
|
|
43
41
|
if __name__ == "__main__":
|
|
@@ -74,7 +74,7 @@ class Test(unittest.TestCase):
|
|
|
74
74
|
item.ProcessImageFileName
|
|
75
75
|
|
|
76
76
|
bytes = find_memleak(doit, (20, 20))
|
|
77
|
-
self.assertFalse(bytes, "Leaks
|
|
77
|
+
self.assertFalse(bytes, f"Leaks {bytes} bytes")
|
|
78
78
|
|
|
79
79
|
@unittest.skip("This test takes a long time. Do we need it? Can it be rewritten?")
|
|
80
80
|
def test_leaks_2(self):
|
|
@@ -87,7 +87,7 @@ class Test(unittest.TestCase):
|
|
|
87
87
|
iter(apps).Next(99)
|
|
88
88
|
|
|
89
89
|
bytes = find_memleak(doit, (20, 20))
|
|
90
|
-
self.assertFalse(bytes, "Leaks
|
|
90
|
+
self.assertFalse(bytes, f"Leaks {bytes} bytes")
|
|
91
91
|
|
|
92
92
|
@unittest.skip("This test takes a long time. Do we need it? Can it be rewritten?")
|
|
93
93
|
def test_leaks_3(self):
|
|
@@ -102,7 +102,7 @@ class Test(unittest.TestCase):
|
|
|
102
102
|
pass
|
|
103
103
|
|
|
104
104
|
bytes = find_memleak(doit, (20, 20))
|
|
105
|
-
self.assertFalse(bytes, "Leaks
|
|
105
|
+
self.assertFalse(bytes, f"Leaks {bytes} bytes")
|
|
106
106
|
|
|
107
107
|
|
|
108
108
|
class TestCollectionInterface(unittest.TestCase):
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import ctypes
|
|
2
|
+
import unittest as ut
|
|
3
|
+
from ctypes import POINTER, byref, pointer
|
|
4
|
+
from unittest import mock
|
|
5
|
+
|
|
6
|
+
import comtypes
|
|
7
|
+
import comtypes.client
|
|
8
|
+
from comtypes import COMObject, IUnknown, hresult
|
|
9
|
+
from comtypes.automation import IDispatch
|
|
10
|
+
|
|
11
|
+
comtypes.client.GetModule("UIAutomationCore.dll")
|
|
12
|
+
comtypes.client.GetModule("scrrun.dll")
|
|
13
|
+
from comtypes.gen import Scripting as scrrun
|
|
14
|
+
from comtypes.gen import UIAutomationClient as uiac
|
|
15
|
+
from comtypes.gen import stdole
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class Test_QueryInterface(ut.TestCase):
|
|
19
|
+
def test_custom_interface(self):
|
|
20
|
+
iuia = uiac.CUIAutomation().QueryInterface(uiac.IUIAutomation)
|
|
21
|
+
self.assertTrue(bool(iuia))
|
|
22
|
+
self.assertEqual(iuia.AddRef(), 2)
|
|
23
|
+
punk = iuia.QueryInterface(IUnknown)
|
|
24
|
+
self.assertEqual(iuia.AddRef(), 4)
|
|
25
|
+
self.assertEqual(punk.AddRef(), 5)
|
|
26
|
+
self.assertEqual(iuia.Release(), 4)
|
|
27
|
+
del iuia
|
|
28
|
+
self.assertEqual(punk.Release(), 2)
|
|
29
|
+
self.assertEqual(punk.Release(), 1)
|
|
30
|
+
|
|
31
|
+
def test_dispatch_interface(self):
|
|
32
|
+
dic = scrrun.Dictionary().QueryInterface(scrrun.IDictionary)
|
|
33
|
+
self.assertTrue(bool(dic))
|
|
34
|
+
self.assertEqual(dic.GetTypeInfoCount(), 1)
|
|
35
|
+
self.assertEqual(
|
|
36
|
+
dic.GetTypeInfo(0).GetTypeAttr().guid,
|
|
37
|
+
scrrun.IDictionary._iid_,
|
|
38
|
+
)
|
|
39
|
+
self.assertEqual(dic.GetIDsOfNames("Add"), [1])
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class Test_IUnknown_QueryInterface(ut.TestCase):
|
|
43
|
+
def test_e_pointer(self):
|
|
44
|
+
hr = scrrun.Dictionary().IUnknown_QueryInterface(
|
|
45
|
+
None, pointer(scrrun.IDictionary._iid_), ctypes.c_void_p()
|
|
46
|
+
)
|
|
47
|
+
self.assertEqual(hr, hresult.E_POINTER)
|
|
48
|
+
|
|
49
|
+
def test_e_no_interface(self):
|
|
50
|
+
hr = scrrun.Dictionary().IUnknown_QueryInterface(
|
|
51
|
+
None, pointer(uiac.IUIAutomation._iid_), ctypes.c_void_p()
|
|
52
|
+
)
|
|
53
|
+
self.assertEqual(hr, hresult.E_NOINTERFACE)
|
|
54
|
+
|
|
55
|
+
def test_valid_pointer(self):
|
|
56
|
+
ptr = ctypes.c_void_p()
|
|
57
|
+
ctypes.oledll.ole32.CoCreateInstance(
|
|
58
|
+
byref(scrrun.Dictionary._reg_clsid_),
|
|
59
|
+
None,
|
|
60
|
+
comtypes.CLSCTX_SERVER,
|
|
61
|
+
byref(scrrun.IDictionary._iid_),
|
|
62
|
+
byref(ptr),
|
|
63
|
+
)
|
|
64
|
+
before_val = ptr.value
|
|
65
|
+
hr = scrrun.Dictionary().IUnknown_QueryInterface(
|
|
66
|
+
None, pointer(scrrun.IDictionary._iid_), ptr
|
|
67
|
+
)
|
|
68
|
+
self.assertEqual(hr, hresult.S_OK)
|
|
69
|
+
self.assertEqual(ptr.value, before_val)
|
|
70
|
+
|
|
71
|
+
def test_valid_interface(self):
|
|
72
|
+
dic = POINTER(IDispatch)()
|
|
73
|
+
hr = scrrun.Dictionary().IUnknown_QueryInterface(
|
|
74
|
+
None, pointer(scrrun.IDictionary._iid_), byref(dic)
|
|
75
|
+
)
|
|
76
|
+
self.assertEqual(hr, hresult.S_OK)
|
|
77
|
+
self.assertEqual(dic.AddRef(), 2) # type: ignore
|
|
78
|
+
self.assertEqual(dic.Release(), 1) # type: ignore
|
|
79
|
+
self.assertEqual(dic.GetTypeInfoCount(), 1) # type: ignore
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
class Test_IUnknown_AddRef_IUnknown_Release(ut.TestCase):
|
|
83
|
+
def test(self):
|
|
84
|
+
cuia = uiac.CUIAutomation()
|
|
85
|
+
self.assertEqual(cuia.IUnknown_AddRef(None), 1)
|
|
86
|
+
self.assertEqual(cuia.IUnknown_AddRef(None), 2)
|
|
87
|
+
with mock.patch.object(COMObject, "_final_release_") as release:
|
|
88
|
+
self.assertEqual(cuia.IUnknown_Release(None), 1)
|
|
89
|
+
release.assert_not_called()
|
|
90
|
+
self.assertEqual(cuia.IUnknown_Release(None), 0)
|
|
91
|
+
release.assert_called_once_with()
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
class Test_ISupportErrorInfo_InterfaceSupportsErrorInfo(ut.TestCase):
|
|
95
|
+
def test_s_ok(self):
|
|
96
|
+
cuia = uiac.CUIAutomation()
|
|
97
|
+
self.assertEqual(
|
|
98
|
+
cuia.ISupportErrorInfo_InterfaceSupportsErrorInfo(
|
|
99
|
+
None, pointer(IUnknown._iid_)
|
|
100
|
+
),
|
|
101
|
+
hresult.S_OK,
|
|
102
|
+
)
|
|
103
|
+
self.assertEqual(
|
|
104
|
+
cuia.ISupportErrorInfo_InterfaceSupportsErrorInfo(
|
|
105
|
+
None, pointer(uiac.IUIAutomation._iid_)
|
|
106
|
+
),
|
|
107
|
+
hresult.S_OK,
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
def test_s_false(self):
|
|
111
|
+
cuia = uiac.CUIAutomation()
|
|
112
|
+
self.assertEqual(
|
|
113
|
+
cuia.ISupportErrorInfo_InterfaceSupportsErrorInfo(
|
|
114
|
+
None, pointer(IDispatch._iid_)
|
|
115
|
+
),
|
|
116
|
+
hresult.S_FALSE,
|
|
117
|
+
)
|
|
118
|
+
self.assertEqual(
|
|
119
|
+
cuia.ISupportErrorInfo_InterfaceSupportsErrorInfo(
|
|
120
|
+
None, pointer(scrrun.IDictionary._iid_)
|
|
121
|
+
),
|
|
122
|
+
hresult.S_FALSE,
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
class Test_IProvideClassInfo_GetClassInfo(ut.TestCase):
|
|
127
|
+
def test(self):
|
|
128
|
+
tinfo = uiac.CUIAutomation().IProvideClassInfo_GetClassInfo()
|
|
129
|
+
self.assertEqual(tinfo.GetTypeAttr().guid, uiac.CUIAutomation._reg_clsid_)
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
class Test_IProvideClassInfo2_GetGUID(ut.TestCase):
|
|
133
|
+
def test(self):
|
|
134
|
+
# GUIDKIND_DEFAULT_SOURCE_DISP_IID = 1
|
|
135
|
+
self.assertEqual(
|
|
136
|
+
stdole.StdFont().IProvideClassInfo2_GetGUID(1),
|
|
137
|
+
stdole.FontEvents._iid_,
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
class Test_IPersist_GetClassID(ut.TestCase):
|
|
142
|
+
def test(self):
|
|
143
|
+
self.assertEqual(
|
|
144
|
+
uiac.CUIAutomation().IPersist_GetClassID(),
|
|
145
|
+
uiac.CUIAutomation._reg_clsid_,
|
|
146
|
+
)
|