comtypes 1.4.7__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.7 → comtypes-1.4.9}/CHANGES.txt +39 -0
- {comtypes-1.4.7/comtypes.egg-info → comtypes-1.4.9}/PKG-INFO +6 -4
- {comtypes-1.4.7 → comtypes-1.4.9}/README.md +5 -3
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/GUID.py +6 -5
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/__init__.py +16 -5
- comtypes-1.4.9/comtypes/_comobject.py +507 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/_memberspec.py +81 -9
- comtypes-1.4.9/comtypes/_meta.py +95 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/_npsupport.py +2 -1
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/_post_coinit/__init__.py +1 -0
- comtypes-1.4.9/comtypes/_post_coinit/_cominterface_meta_patcher.py +153 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/_post_coinit/misc.py +21 -40
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/_post_coinit/unknwn.py +88 -209
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/_safearray.py +1 -2
- comtypes-1.4.9/comtypes/_vtbl.py +448 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/automation.py +36 -45
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/client/__init__.py +21 -31
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/client/_code_cache.py +5 -4
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/client/_constants.py +1 -1
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/client/_events.py +1 -2
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/client/_generate.py +9 -13
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/client/lazybind.py +2 -7
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/errorinfo.py +3 -3
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/git.py +2 -2
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/hints.pyi +11 -19
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/persist.py +7 -7
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/safearray.py +12 -6
- comtypes-1.4.9/comtypes/server/__init__.py +86 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/server/inprocserver.py +22 -17
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/server/localserver.py +28 -16
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/server/register.py +62 -73
- comtypes-1.4.9/comtypes/server/w_getopt.py +48 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/shelllink.py +49 -67
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/TestComServer.py +1 -1
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/TestDispServer.py +1 -1
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/__init__.py +9 -12
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/find_memleak.py +0 -1
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_BSTR.py +4 -7
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_agilent.py +0 -1
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_avmc.py +1 -1
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_casesensitivity.py +3 -5
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_clear_cache.py +1 -0
- {comtypes-1.4.7 → 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.7 → comtypes-1.4.9}/comtypes/test/test_createwrappers.py +2 -6
- comtypes-1.4.9/comtypes/test/test_dispinterface.py +153 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_excel.py +22 -13
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_ie.py +2 -5
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_inout_args.py +8 -5
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_midl_safearray_create.py +9 -1
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_outparam.py +17 -10
- {comtypes-1.4.7 → 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.7 → comtypes-1.4.9}/comtypes/test/test_shelllink.py +10 -14
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_showevents.py +7 -17
- comtypes-1.4.9/comtypes/test/test_stream.py +131 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_typeannotator.py +1 -1
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_urlhistory.py +1 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_variant.py +0 -19
- comtypes-1.4.9/comtypes/test/test_w_getopt.py +29 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_win32com_interop.py +80 -36
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_wmi.py +0 -3
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/tools/codegenerator/codegenerator.py +62 -68
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/tools/codegenerator/helpers.py +8 -8
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/tools/codegenerator/namespaces.py +97 -27
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/tools/codegenerator/packing.py +4 -4
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/tools/codegenerator/typeannotator.py +9 -11
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/tools/tlbparser.py +33 -32
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/tools/typedesc.py +3 -8
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/typeinfo.py +32 -47
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/util.py +1 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/viewobject.py +1 -5
- {comtypes-1.4.7 → comtypes-1.4.9/comtypes.egg-info}/PKG-INFO +6 -4
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes.egg-info/SOURCES.txt +6 -3
- comtypes-1.4.9/pyproject.toml +55 -0
- comtypes-1.4.7/comtypes/_comobject.py +0 -834
- comtypes-1.4.7/comtypes/_idl_stuff.py +0 -67
- comtypes-1.4.7/comtypes/_meta.py +0 -70
- comtypes-1.4.7/comtypes/server/__init__.py +0 -69
- comtypes-1.4.7/comtypes/server/w_getopt.py +0 -75
- comtypes-1.4.7/comtypes/test/test_comserver.py +0 -239
- comtypes-1.4.7/comtypes/test/test_dispinterface.py +0 -138
- comtypes-1.4.7/comtypes/test/test_propputref.py +0 -40
- comtypes-1.4.7/comtypes/test/test_server.py +0 -348
- comtypes-1.4.7/comtypes/test/test_stream.py +0 -53
- comtypes-1.4.7/pyproject.toml +0 -3
- {comtypes-1.4.7 → comtypes-1.4.9}/LICENSE.txt +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/MANIFEST.in +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/_post_coinit/bstr.py +0 -0
- /comtypes-1.4.7/comtypes/_py_instance_method.py → /comtypes-1.4.9/comtypes/_post_coinit/instancemethod.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/_tlib_version_checker.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/clear_cache.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/client/dynamic.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/connectionpoints.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/hresult.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/logutil.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/messageloop.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/patcher.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/server/automation.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/server/connectionpoints.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/stream.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/TestComServer.idl +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/TestComServer.tlb +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/TestDispServer.idl +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/TestDispServer.tlb +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/mylib.idl +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/mylib.tlb +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/mytypelib.idl +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/runtests.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/setup.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_DISPPARAMS.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_GUID.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_QueryService.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_basic.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_client.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_client_dynamic.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_client_regenerate_modules.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_dict.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_dispifc_records.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_dispifc_safearrays.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_dyndispatch.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_findgendir.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_getactiveobj.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_ienum.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_imfattributes.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_jscript.js +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_monikers.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_msscript.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_npsupport.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_persist.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_pump_events.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_recordinfo.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_sapi.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_storage.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_subinterface.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_typeinfo.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_word.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/urlhist.tlb +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/tools/__init__.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/tools/codegenerator/__init__.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/tools/codegenerator/modulenamer.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/tools/typedesc_base.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes.egg-info/dependency_links.txt +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes.egg-info/entry_points.txt +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes.egg-info/top_level.txt +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/setup.cfg +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/setup.py +0 -0
|
@@ -1,10 +1,16 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import queue
|
|
1
3
|
import sys
|
|
2
|
-
from ctypes import
|
|
4
|
+
from ctypes import byref, c_ulong, c_void_p, oledll
|
|
5
|
+
from typing import TYPE_CHECKING, Any, Literal, Optional, Sequence, Type
|
|
6
|
+
|
|
3
7
|
import comtypes
|
|
4
|
-
from comtypes
|
|
8
|
+
from comtypes import hresult
|
|
5
9
|
from comtypes.server import IClassFactory
|
|
6
|
-
|
|
7
|
-
|
|
10
|
+
|
|
11
|
+
if TYPE_CHECKING:
|
|
12
|
+
from ctypes import _Pointer
|
|
13
|
+
|
|
8
14
|
|
|
9
15
|
logger = logging.getLogger(__name__)
|
|
10
16
|
_debug = logger.debug
|
|
@@ -16,31 +22,31 @@ REGCLS_SUSPENDED = 4 # register it as suspended, will be activated
|
|
|
16
22
|
REGCLS_SURROGATE = 8 # must be used when a surrogate process
|
|
17
23
|
|
|
18
24
|
|
|
19
|
-
def run(classes):
|
|
25
|
+
def run(classes: Sequence[Type[comtypes.COMObject]]) -> None:
|
|
20
26
|
classobjects = [ClassFactory(cls) for cls in classes]
|
|
21
27
|
comtypes.COMObject.__run_localserver__(classobjects)
|
|
22
28
|
|
|
23
29
|
|
|
24
30
|
class ClassFactory(comtypes.COMObject):
|
|
25
31
|
_com_interfaces_ = [IClassFactory]
|
|
26
|
-
_locks = 0
|
|
27
|
-
_queue = None
|
|
28
|
-
regcls = REGCLS_MULTIPLEUSE
|
|
32
|
+
_locks: int = 0
|
|
33
|
+
_queue: Optional[queue.Queue] = None
|
|
34
|
+
regcls: int = REGCLS_MULTIPLEUSE
|
|
29
35
|
|
|
30
|
-
def __init__(self, cls, *args, **kw):
|
|
36
|
+
def __init__(self, cls: Type[comtypes.COMObject], *args, **kw) -> None:
|
|
31
37
|
super(ClassFactory, self).__init__()
|
|
32
38
|
self._cls = cls
|
|
33
39
|
self._register_class()
|
|
34
40
|
self._args = args
|
|
35
41
|
self._kw = kw
|
|
36
42
|
|
|
37
|
-
def IUnknown_AddRef(self, this):
|
|
43
|
+
def IUnknown_AddRef(self, this: Any) -> int:
|
|
38
44
|
return 2
|
|
39
45
|
|
|
40
|
-
def IUnknown_Release(self, this):
|
|
46
|
+
def IUnknown_Release(self, this: Any) -> int:
|
|
41
47
|
return 1
|
|
42
48
|
|
|
43
|
-
def _register_class(self):
|
|
49
|
+
def _register_class(self) -> None:
|
|
44
50
|
regcls = getattr(self._cls, "_regcls_", self.regcls)
|
|
45
51
|
cookie = c_ulong()
|
|
46
52
|
ptr = self._com_pointers_[comtypes.IUnknown._iid_]
|
|
@@ -55,19 +61,25 @@ class ClassFactory(comtypes.COMObject):
|
|
|
55
61
|
)
|
|
56
62
|
self.cookie = cookie
|
|
57
63
|
|
|
58
|
-
def _revoke_class(self):
|
|
64
|
+
def _revoke_class(self) -> None:
|
|
59
65
|
oledll.ole32.CoRevokeClassObject(self.cookie)
|
|
60
66
|
|
|
61
|
-
def CreateInstance(
|
|
67
|
+
def CreateInstance(
|
|
68
|
+
self,
|
|
69
|
+
this: Any,
|
|
70
|
+
punkOuter: Optional[Type["_Pointer[comtypes.IUnknown]"]],
|
|
71
|
+
riid: "_Pointer[comtypes.GUID]",
|
|
72
|
+
ppv: c_void_p,
|
|
73
|
+
) -> int:
|
|
62
74
|
_debug("ClassFactory.CreateInstance(%s)", riid[0])
|
|
63
75
|
obj = self._cls(*self._args, **self._kw)
|
|
64
76
|
result = obj.IUnknown_QueryInterface(None, riid, ppv)
|
|
65
77
|
_debug("CreateInstance() -> %s", result)
|
|
66
78
|
return result
|
|
67
79
|
|
|
68
|
-
def LockServer(self, this, fLock):
|
|
80
|
+
def LockServer(self, this: Any, fLock: bool) -> Literal[0]:
|
|
69
81
|
if fLock:
|
|
70
82
|
comtypes.COMObject.__server__.Lock()
|
|
71
83
|
else:
|
|
72
84
|
comtypes.COMObject.__server__.Unlock()
|
|
73
|
-
return S_OK
|
|
85
|
+
return hresult.S_OK
|
|
@@ -35,17 +35,19 @@ Now, debug the object, and when done delete logging info:
|
|
|
35
35
|
|
|
36
36
|
python mycomobj.py /nodebug
|
|
37
37
|
"""
|
|
38
|
-
|
|
38
|
+
|
|
39
|
+
import logging
|
|
39
40
|
import os
|
|
41
|
+
import sys
|
|
40
42
|
import winreg
|
|
41
|
-
import
|
|
43
|
+
from ctypes import WinError, c_ulong, c_wchar_p, create_string_buffer, sizeof, windll
|
|
44
|
+
from typing import Iterator, Tuple
|
|
42
45
|
|
|
43
46
|
import comtypes
|
|
44
|
-
|
|
47
|
+
import comtypes.server.inprocserver
|
|
45
48
|
from comtypes.hresult import *
|
|
46
49
|
from comtypes.server import w_getopt
|
|
47
|
-
|
|
48
|
-
from ctypes import windll, c_ulong, c_wchar_p, WinError, sizeof, create_string_buffer
|
|
50
|
+
from comtypes.typeinfo import REGKIND_REGISTER, LoadTypeLibEx, UnRegisterTypeLib
|
|
49
51
|
|
|
50
52
|
_debug = logging.getLogger(__name__).debug
|
|
51
53
|
|
|
@@ -99,7 +101,7 @@ class Registrar(object):
|
|
|
99
101
|
'DeleteKey( %s\\CLSID\\%s\\Logging"'
|
|
100
102
|
% (_explain(winreg.HKEY_CLASSES_ROOT), clsid)
|
|
101
103
|
)
|
|
102
|
-
hkey = winreg.OpenKey(winreg.HKEY_CLASSES_ROOT,
|
|
104
|
+
hkey = winreg.OpenKey(winreg.HKEY_CLASSES_ROOT, rf"CLSID\{clsid}")
|
|
103
105
|
winreg.DeleteKey(hkey, "Logging")
|
|
104
106
|
except WindowsError as detail:
|
|
105
107
|
if get_winerror(detail) != 2:
|
|
@@ -114,7 +116,7 @@ class Registrar(object):
|
|
|
114
116
|
'CreateKey( %s\\CLSID\\%s\\Logging"'
|
|
115
117
|
% (_explain(winreg.HKEY_CLASSES_ROOT), clsid)
|
|
116
118
|
)
|
|
117
|
-
hkey = winreg.CreateKey(winreg.HKEY_CLASSES_ROOT,
|
|
119
|
+
hkey = winreg.CreateKey(winreg.HKEY_CLASSES_ROOT, rf"CLSID\{clsid}\Logging")
|
|
118
120
|
for item in levels:
|
|
119
121
|
name, value = item.split("=")
|
|
120
122
|
v = getattr(logging, value)
|
|
@@ -146,8 +148,7 @@ class Registrar(object):
|
|
|
146
148
|
self._register(cls, executable)
|
|
147
149
|
|
|
148
150
|
def _register(self, cls, executable=None):
|
|
149
|
-
table =
|
|
150
|
-
table.sort()
|
|
151
|
+
table = sorted(RegistryEntries(cls))
|
|
151
152
|
_debug("Registering %s", cls)
|
|
152
153
|
for hkey, subkey, valuename, value in table:
|
|
153
154
|
_debug("[%s\\%s]", _explain(hkey), subkey)
|
|
@@ -158,7 +159,7 @@ class Registrar(object):
|
|
|
158
159
|
tlib = getattr(cls, "_reg_typelib_", None)
|
|
159
160
|
if tlib is not None:
|
|
160
161
|
if hasattr(sys, "frozendllhandle"):
|
|
161
|
-
dll =
|
|
162
|
+
dll = _get_serverdll()
|
|
162
163
|
_debug("LoadTypeLibEx(%s, REGKIND_REGISTER)", dll)
|
|
163
164
|
LoadTypeLibEx(dll, REGKIND_REGISTER)
|
|
164
165
|
else:
|
|
@@ -183,7 +184,7 @@ class Registrar(object):
|
|
|
183
184
|
def _unregister(self, cls, force=False):
|
|
184
185
|
# If force==False, we only remove those entries that we
|
|
185
186
|
# actually would have written. It seems ATL does the same.
|
|
186
|
-
table = [t[:2] for t in
|
|
187
|
+
table = [t[:2] for t in RegistryEntries(cls)]
|
|
187
188
|
# only unique entries
|
|
188
189
|
table = list(set(table))
|
|
189
190
|
table.sort()
|
|
@@ -213,23 +214,29 @@ class Registrar(object):
|
|
|
213
214
|
raise
|
|
214
215
|
_debug("Done")
|
|
215
216
|
|
|
216
|
-
def _get_serverdll(self):
|
|
217
|
-
"""Return the pathname of the dll hosting the COM object."""
|
|
218
|
-
handle = getattr(sys, "frozendllhandle", None)
|
|
219
|
-
if handle is not None:
|
|
220
|
-
buf = create_string_buffer(260)
|
|
221
|
-
windll.kernel32.GetModuleFileNameA(handle, buf, sizeof(buf))
|
|
222
|
-
return buf[:]
|
|
223
|
-
import _ctypes
|
|
224
217
|
|
|
225
|
-
|
|
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
|
|
226
233
|
|
|
227
234
|
def _get_full_classname(self, cls):
|
|
228
235
|
"""Return <modulename>.<classname> for 'cls'."""
|
|
229
236
|
modname = cls.__module__
|
|
230
237
|
if modname == "__main__":
|
|
231
238
|
modname = os.path.splitext(os.path.basename(sys.argv[0]))[0]
|
|
232
|
-
return "
|
|
239
|
+
return f"{modname}.{cls.__name__}"
|
|
233
240
|
|
|
234
241
|
def _get_pythonpath(self, cls):
|
|
235
242
|
"""Return the filesystem path of the module containing 'cls'."""
|
|
@@ -237,8 +244,8 @@ class Registrar(object):
|
|
|
237
244
|
dirname = os.path.dirname(sys.modules[modname].__file__)
|
|
238
245
|
return os.path.abspath(dirname)
|
|
239
246
|
|
|
240
|
-
def
|
|
241
|
-
"""Return a
|
|
247
|
+
def __iter__(self) -> Iterator[Tuple[int, str, str, str]]:
|
|
248
|
+
"""Return a iterator of tuples containing registry entries.
|
|
242
249
|
|
|
243
250
|
The tuples must be (key, subkey, name, value).
|
|
244
251
|
|
|
@@ -258,16 +265,13 @@ class Registrar(object):
|
|
|
258
265
|
Note that the first part of the progid string is typically the
|
|
259
266
|
IDL library name of the type library containing the coclass.
|
|
260
267
|
"""
|
|
268
|
+
cls = self._cls
|
|
261
269
|
HKCR = winreg.HKEY_CLASSES_ROOT
|
|
262
270
|
|
|
263
|
-
# table format: rootkey, subkey, valuename, value
|
|
264
|
-
table = []
|
|
265
|
-
append = lambda *args: table.append(args)
|
|
266
|
-
|
|
267
271
|
# basic entry - names the comobject
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
272
|
+
|
|
273
|
+
# that's the only required attribute for registration
|
|
274
|
+
reg_clsid = str(cls._reg_clsid_)
|
|
271
275
|
reg_desc = getattr(cls, "_reg_desc_", "")
|
|
272
276
|
if not reg_desc:
|
|
273
277
|
# Simple minded algorithm to construct a description from
|
|
@@ -277,95 +281,83 @@ class Registrar(object):
|
|
|
277
281
|
)
|
|
278
282
|
if reg_desc:
|
|
279
283
|
reg_desc = reg_desc.replace(".", " ")
|
|
280
|
-
|
|
284
|
+
yield (HKCR, f"CLSID\\{reg_clsid}", "", reg_desc)
|
|
281
285
|
|
|
282
286
|
reg_progid = getattr(cls, "_reg_progid_", None)
|
|
283
287
|
if reg_progid:
|
|
284
288
|
# for ProgIDFromCLSID:
|
|
285
|
-
|
|
289
|
+
yield (HKCR, f"CLSID\\{reg_clsid}\\ProgID", "", reg_progid) # 1
|
|
286
290
|
|
|
287
291
|
# for CLSIDFromProgID
|
|
288
292
|
if reg_desc:
|
|
289
|
-
|
|
290
|
-
|
|
293
|
+
yield (HKCR, reg_progid, "", reg_desc) # 2
|
|
294
|
+
yield (HKCR, f"{reg_progid}\\CLSID", "", reg_clsid) # 3
|
|
291
295
|
|
|
292
296
|
reg_novers_progid = getattr(cls, "_reg_novers_progid_", None)
|
|
293
297
|
if reg_novers_progid:
|
|
294
|
-
|
|
298
|
+
yield (
|
|
295
299
|
HKCR,
|
|
296
|
-
"CLSID
|
|
300
|
+
f"CLSID\\{reg_clsid}\\VersionIndependentProgID", # 1a
|
|
297
301
|
"",
|
|
298
302
|
reg_novers_progid,
|
|
299
303
|
)
|
|
300
304
|
if reg_desc:
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
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
|
|
304
308
|
|
|
305
|
-
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)
|
|
306
312
|
|
|
307
|
-
if
|
|
308
|
-
sys, "frozendllhandle"
|
|
309
|
-
):
|
|
313
|
+
if localsvr_ctx and not hasattr(sys, "frozendllhandle"):
|
|
310
314
|
exe = sys.executable
|
|
311
315
|
if " " in exe:
|
|
312
|
-
exe = '"
|
|
316
|
+
exe = f'"{exe}"'
|
|
313
317
|
if not hasattr(sys, "frozen"):
|
|
314
318
|
if not __debug__:
|
|
315
|
-
exe = "
|
|
319
|
+
exe = f"{exe} -O"
|
|
316
320
|
script = os.path.abspath(sys.modules[cls.__module__].__file__)
|
|
317
321
|
if " " in script:
|
|
318
|
-
script = '"
|
|
319
|
-
|
|
320
|
-
HKCR,
|
|
321
|
-
"CLSID\\%s\\LocalServer32" % reg_clsid,
|
|
322
|
-
"",
|
|
323
|
-
"%s %s" % (exe, script),
|
|
324
|
-
)
|
|
322
|
+
script = f'"{script}"'
|
|
323
|
+
yield (HKCR, rf"CLSID\{reg_clsid}\LocalServer32", "", f"{exe} {script}")
|
|
325
324
|
else:
|
|
326
|
-
|
|
325
|
+
yield (HKCR, rf"CLSID\{reg_clsid}\LocalServer32", "", f"{exe}")
|
|
327
326
|
|
|
328
327
|
# Register InprocServer32 only when run from script or from
|
|
329
328
|
# py2exe dll server, not from py2exe exe server.
|
|
330
|
-
if
|
|
331
|
-
|
|
332
|
-
"dll",
|
|
333
|
-
):
|
|
334
|
-
append(
|
|
335
|
-
HKCR, "CLSID\\%s\\InprocServer32" % reg_clsid, "", self._get_serverdll()
|
|
336
|
-
)
|
|
329
|
+
if inprocsvr_ctx and getattr(sys, "frozen", None) in (None, "dll"):
|
|
330
|
+
yield (HKCR, rf"CLSID\{reg_clsid}\InprocServer32", "", _get_serverdll())
|
|
337
331
|
# only for non-frozen inproc servers the PythonPath/PythonClass is needed.
|
|
338
332
|
if (
|
|
339
333
|
not hasattr(sys, "frozendllhandle")
|
|
340
334
|
or not comtypes.server.inprocserver._clsid_to_class
|
|
341
335
|
):
|
|
342
|
-
|
|
336
|
+
yield (
|
|
343
337
|
HKCR,
|
|
344
|
-
"CLSID
|
|
338
|
+
rf"CLSID\{reg_clsid}\InprocServer32",
|
|
345
339
|
"PythonClass",
|
|
346
340
|
self._get_full_classname(cls),
|
|
347
341
|
)
|
|
348
|
-
|
|
342
|
+
yield (
|
|
349
343
|
HKCR,
|
|
350
|
-
"CLSID
|
|
344
|
+
rf"CLSID\{reg_clsid}\InprocServer32",
|
|
351
345
|
"PythonPath",
|
|
352
346
|
self._get_pythonpath(cls),
|
|
353
347
|
)
|
|
354
348
|
|
|
355
349
|
reg_threading = getattr(cls, "_reg_threading_", None)
|
|
356
350
|
if reg_threading is not None:
|
|
357
|
-
|
|
351
|
+
yield (
|
|
358
352
|
HKCR,
|
|
359
|
-
"CLSID
|
|
353
|
+
rf"CLSID\{reg_clsid}\InprocServer32",
|
|
360
354
|
"ThreadingModel",
|
|
361
355
|
reg_threading,
|
|
362
356
|
)
|
|
363
357
|
|
|
364
358
|
reg_tlib = getattr(cls, "_reg_typelib_", None)
|
|
365
359
|
if reg_tlib is not None:
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
return table
|
|
360
|
+
yield (HKCR, rf"CLSID\{reg_clsid}\Typelib", "", reg_tlib[0])
|
|
369
361
|
|
|
370
362
|
|
|
371
363
|
################################################################
|
|
@@ -380,10 +372,7 @@ def unregister(cls):
|
|
|
380
372
|
|
|
381
373
|
|
|
382
374
|
def UseCommandLine(*classes):
|
|
383
|
-
usage =
|
|
384
|
-
"""Usage: %s [-regserver] [-unregserver] [-nodebug] [-f logformat] [-l loggername=level]"""
|
|
385
|
-
% sys.argv[0]
|
|
386
|
-
)
|
|
375
|
+
usage = f"""Usage: {sys.argv[0]} [-regserver] [-unregserver] [-nodebug] [-f logformat] [-l loggername=level]"""
|
|
387
376
|
opts, args = w_getopt.w_getopt(
|
|
388
377
|
sys.argv[1:], "regserver unregserver embedding l: f: nodebug"
|
|
389
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
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
from __future__ import print_function
|
|
2
1
|
from ctypes import c_char_p, c_int, c_short, c_wchar_p
|
|
3
2
|
from ctypes import POINTER
|
|
4
3
|
from ctypes import byref, create_string_buffer, create_unicode_buffer
|
|
5
4
|
from ctypes.wintypes import DWORD, WIN32_FIND_DATAA, WIN32_FIND_DATAW, MAX_PATH
|
|
6
|
-
from typing import Tuple, TYPE_CHECKING
|
|
5
|
+
from typing import Tuple, TYPE_CHECKING, Literal
|
|
7
6
|
|
|
8
7
|
from comtypes import IUnknown, GUID, COMMETHOD, HRESULT, CoClass
|
|
9
8
|
|
|
@@ -18,19 +17,24 @@ SLGP_UNCPRIORITY = 0x2
|
|
|
18
17
|
SLGP_RAWPATH = 0x4
|
|
19
18
|
|
|
20
19
|
# for SetShowCmd, GetShowCmd
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
20
|
+
SW_SHOWNORMAL = 0x01
|
|
21
|
+
SW_SHOWMAXIMIZED = 0x03
|
|
22
|
+
SW_SHOWMINNOACTIVE = 0x07
|
|
25
23
|
|
|
26
24
|
# for Resolve
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
25
|
+
SLR_INVOKE_MSI = 0x0080
|
|
26
|
+
SLR_NOLINKINFO = 0x0040
|
|
27
|
+
SLR_NO_UI = 0x0001
|
|
28
|
+
SLR_NOUPDATE = 0x0008
|
|
29
|
+
SLR_NOSEARCH = 0x0010
|
|
30
|
+
SLR_NOTRACK = 0x0020
|
|
31
|
+
SLR_UPDATE = 0x0004
|
|
32
|
+
|
|
33
|
+
# for Hotkey
|
|
34
|
+
HOTKEYF_ALT = 0x04
|
|
35
|
+
HOTKEYF_CONTROL = 0x02
|
|
36
|
+
HOTKEYF_EXT = 0x08
|
|
37
|
+
HOTKEYF_SHIFT = 0x01
|
|
34
38
|
|
|
35
39
|
# fake these...
|
|
36
40
|
ITEMIDLIST = c_int
|
|
@@ -123,25 +127,26 @@ class IShellLinkA(IUnknown):
|
|
|
123
127
|
]
|
|
124
128
|
|
|
125
129
|
if TYPE_CHECKING:
|
|
126
|
-
|
|
127
|
-
def GetIDList(self) -> hints.Incomplete: ...
|
|
128
|
-
def SetIDList(self, pidl: hints.Incomplete) -> hints.Incomplete: ...
|
|
129
|
-
def SetDescription(self, pszName: bytes) -> hints.Incomplete: ...
|
|
130
|
-
def SetWorkingDirectory(self, pszDir: bytes) -> hints.Hresult: ...
|
|
131
|
-
def SetArguments(self, pszArgs: bytes) -> hints.Hresult: ...
|
|
130
|
+
|
|
131
|
+
def GetIDList(self) -> hints.Incomplete: ...
|
|
132
|
+
def SetIDList(self, pidl: hints.Incomplete) -> hints.Incomplete: ...
|
|
133
|
+
def SetDescription(self, pszName: bytes) -> hints.Incomplete: ...
|
|
134
|
+
def SetWorkingDirectory(self, pszDir: bytes) -> hints.Hresult: ...
|
|
135
|
+
def SetArguments(self, pszArgs: bytes) -> hints.Hresult: ...
|
|
132
136
|
@property
|
|
133
|
-
def Hotkey(self) -> int: ...
|
|
137
|
+
def Hotkey(self) -> int: ...
|
|
134
138
|
@Hotkey.setter
|
|
135
|
-
def Hotkey(self, pwHotkey: int) -> None: ...
|
|
139
|
+
def Hotkey(self, pwHotkey: int) -> None: ...
|
|
136
140
|
@property
|
|
137
|
-
def ShowCmd(self) -> int: ...
|
|
141
|
+
def ShowCmd(self) -> int: ...
|
|
138
142
|
@ShowCmd.setter
|
|
139
|
-
def ShowCmd(self, piShowCmd: int) -> None: ...
|
|
140
|
-
def SetIconLocation(self, pszIconPath: bytes, iIcon: int) -> hints.Hresult: ...
|
|
141
|
-
def SetRelativePath(
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
143
|
+
def ShowCmd(self, piShowCmd: int) -> None: ...
|
|
144
|
+
def SetIconLocation(self, pszIconPath: bytes, iIcon: int) -> hints.Hresult: ...
|
|
145
|
+
def SetRelativePath(
|
|
146
|
+
self, pszPathRel: bytes, dwReserved: Literal[0]
|
|
147
|
+
) -> hints.Hresult: ...
|
|
148
|
+
def Resolve(self, hwnd: int, fFlags: int) -> hints.Hresult: ...
|
|
149
|
+
def SetPath(self, pszFile: bytes) -> hints.Hresult: ...
|
|
145
150
|
|
|
146
151
|
def GetPath(self, flags: int = SLGP_SHORTPATH) -> bytes:
|
|
147
152
|
buf = create_string_buffer(MAX_PATH)
|
|
@@ -257,25 +262,26 @@ class IShellLinkW(IUnknown):
|
|
|
257
262
|
]
|
|
258
263
|
|
|
259
264
|
if TYPE_CHECKING:
|
|
260
|
-
|
|
261
|
-
def GetIDList(self) -> hints.Incomplete: ...
|
|
262
|
-
def SetIDList(self, pidl: hints.Incomplete) -> hints.Incomplete: ...
|
|
263
|
-
def SetDescription(self, pszName: str) -> hints.Incomplete: ...
|
|
264
|
-
def SetWorkingDirectory(self, pszDir: str) -> hints.Hresult: ...
|
|
265
|
-
def SetArguments(self, pszArgs: str) -> hints.Hresult: ...
|
|
265
|
+
|
|
266
|
+
def GetIDList(self) -> hints.Incomplete: ...
|
|
267
|
+
def SetIDList(self, pidl: hints.Incomplete) -> hints.Incomplete: ...
|
|
268
|
+
def SetDescription(self, pszName: str) -> hints.Incomplete: ...
|
|
269
|
+
def SetWorkingDirectory(self, pszDir: str) -> hints.Hresult: ...
|
|
270
|
+
def SetArguments(self, pszArgs: str) -> hints.Hresult: ...
|
|
266
271
|
@property
|
|
267
|
-
def Hotkey(self) -> int: ...
|
|
272
|
+
def Hotkey(self) -> int: ...
|
|
268
273
|
@Hotkey.setter
|
|
269
|
-
def Hotkey(self, pwHotkey: int) -> None: ...
|
|
274
|
+
def Hotkey(self, pwHotkey: int) -> None: ...
|
|
270
275
|
@property
|
|
271
|
-
def ShowCmd(self) -> int: ...
|
|
276
|
+
def ShowCmd(self) -> int: ...
|
|
272
277
|
@ShowCmd.setter
|
|
273
|
-
def ShowCmd(self, piShowCmd: int) -> None: ...
|
|
274
|
-
def SetIconLocation(self, pszIconPath: str, iIcon: int) -> hints.Hresult: ...
|
|
275
|
-
def SetRelativePath(
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
278
|
+
def ShowCmd(self, piShowCmd: int) -> None: ...
|
|
279
|
+
def SetIconLocation(self, pszIconPath: str, iIcon: int) -> hints.Hresult: ...
|
|
280
|
+
def SetRelativePath(
|
|
281
|
+
self, pszPathRel: str, dwReserved: Literal[0]
|
|
282
|
+
) -> hints.Hresult: ...
|
|
283
|
+
def Resolve(self, hwnd: int, fFlags: int) -> hints.Hresult: ...
|
|
284
|
+
def SetPath(self, pszFile: str) -> hints.Hresult: ...
|
|
279
285
|
|
|
280
286
|
def GetPath(self, flags: int = SLGP_SHORTPATH) -> str:
|
|
281
287
|
buf = create_unicode_buffer(MAX_PATH)
|
|
@@ -311,27 +317,3 @@ class ShellLink(CoClass):
|
|
|
311
317
|
_reg_clsid_ = GUID("{00021401-0000-0000-C000-000000000046}")
|
|
312
318
|
_idlflags_ = []
|
|
313
319
|
_com_interfaces_ = [IShellLinkW, IShellLinkA]
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
if __name__ == "__main__":
|
|
317
|
-
|
|
318
|
-
import sys
|
|
319
|
-
import comtypes
|
|
320
|
-
from comtypes.client import CreateObject
|
|
321
|
-
from comtypes.persist import IPersistFile
|
|
322
|
-
|
|
323
|
-
shortcut = CreateObject(ShellLink)
|
|
324
|
-
print(shortcut)
|
|
325
|
-
##help(shortcut)
|
|
326
|
-
|
|
327
|
-
shortcut.SetPath(sys.executable)
|
|
328
|
-
|
|
329
|
-
shortcut.SetDescription("Python %s" % sys.version)
|
|
330
|
-
shortcut.SetIconLocation(sys.executable, 1)
|
|
331
|
-
|
|
332
|
-
print(shortcut.GetPath(2))
|
|
333
|
-
print(shortcut.GetIconLocation())
|
|
334
|
-
|
|
335
|
-
pf = shortcut.QueryInterface(IPersistFile)
|
|
336
|
-
pf.Save("foo.lnk", True)
|
|
337
|
-
print(pf.GetCurFile())
|
|
@@ -33,6 +33,7 @@ from comtypes.gen import TestComServerLib
|
|
|
33
33
|
|
|
34
34
|
################################################################
|
|
35
35
|
|
|
36
|
+
|
|
36
37
|
# Implement the CoClass. Use the coclass from the wrapper as base
|
|
37
38
|
# class, and use DualDispMixin as base class which provides default
|
|
38
39
|
# implementations of IDispatch, IProvideClassInfo, IProvideClassInfo2
|
|
@@ -42,7 +43,6 @@ class TestComServer(
|
|
|
42
43
|
TestComServerLib.TestComServer, # the coclass from the typelib wrapper
|
|
43
44
|
comtypes.server.connectionpoints.ConnectableObjectMixin,
|
|
44
45
|
):
|
|
45
|
-
|
|
46
46
|
# The default interface from the typelib MUST be the first
|
|
47
47
|
# interface, other interfaces can follow
|
|
48
48
|
|
|
@@ -31,6 +31,7 @@ from comtypes.gen import TestDispServerLib
|
|
|
31
31
|
|
|
32
32
|
################################################################
|
|
33
33
|
|
|
34
|
+
|
|
34
35
|
# Implement the CoClass by defining a subclass of the
|
|
35
36
|
# TestDispServerLib.TestDispServer class in the wrapper file. The
|
|
36
37
|
# COMObject base class provides default implementations of the
|
|
@@ -42,7 +43,6 @@ class TestDispServer(
|
|
|
42
43
|
TestDispServerLib.TestDispServer, # the coclass from the typelib wrapper
|
|
43
44
|
comtypes.server.connectionpoints.ConnectableObjectMixin,
|
|
44
45
|
):
|
|
45
|
-
|
|
46
46
|
# The default interface from the typelib MUST be the first
|
|
47
47
|
# interface, other interfaces can follow
|
|
48
48
|
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
# comtypes.test package.
|
|
2
2
|
|
|
3
|
-
from __future__ import print_function
|
|
4
3
|
import ctypes
|
|
5
4
|
import getopt
|
|
6
5
|
import os
|
|
@@ -65,7 +64,7 @@ def requires(resource, msg=None):
|
|
|
65
64
|
return
|
|
66
65
|
if not is_resource_enabled(resource):
|
|
67
66
|
if msg is None:
|
|
68
|
-
msg = "Use of the
|
|
67
|
+
msg = f"Use of the `{resource}` resource not enabled"
|
|
69
68
|
raise ResourceDenied(msg)
|
|
70
69
|
|
|
71
70
|
|
|
@@ -95,12 +94,10 @@ def get_tests(package, mask, verbosity):
|
|
|
95
94
|
except ResourceDenied as detail:
|
|
96
95
|
skipped.append(modname)
|
|
97
96
|
if verbosity > 1:
|
|
98
|
-
print("Skipped
|
|
97
|
+
print(f"Skipped {modname}: {detail}", file=sys.stderr)
|
|
99
98
|
continue
|
|
100
99
|
except Exception as detail:
|
|
101
|
-
print(
|
|
102
|
-
"Warning: could not import %s: %s" % (modname, detail), file=sys.stderr
|
|
103
|
-
)
|
|
100
|
+
print(f"Warning: could not import {modname}: {detail}", file=sys.stderr)
|
|
104
101
|
continue
|
|
105
102
|
for name in dir(mod):
|
|
106
103
|
if name.startswith("_"):
|
|
@@ -150,9 +147,9 @@ def test_with_refcounts(runner, verbosity, testcase):
|
|
|
150
147
|
cleanup()
|
|
151
148
|
refcounts[i] = sys.gettotalrefcount() - rc
|
|
152
149
|
if [_f for _f in refcounts if _f]:
|
|
153
|
-
print("
|
|
150
|
+
print(f"{testcase} leaks:\n\t", refcounts)
|
|
154
151
|
elif verbosity:
|
|
155
|
-
print("
|
|
152
|
+
print(f"{testcase}: ok.")
|
|
156
153
|
|
|
157
154
|
|
|
158
155
|
class TestRunner(unittest.TextTestRunner):
|
|
@@ -181,21 +178,21 @@ class TestRunner(unittest.TextTestRunner):
|
|
|
181
178
|
len(skipped) != 1 and "s" or "",
|
|
182
179
|
)
|
|
183
180
|
)
|
|
184
|
-
self.stream.writeln("Unavailable resources:
|
|
181
|
+
self.stream.writeln(f"Unavailable resources: {', '.join(requested)}")
|
|
185
182
|
else:
|
|
186
183
|
self.stream.writeln(
|
|
187
|
-
"Ran
|
|
184
|
+
f"Ran {run} test{'s' if run != 1 else ''} in {timeTaken:.3f}s"
|
|
188
185
|
)
|
|
189
186
|
self.stream.writeln()
|
|
190
187
|
if not result.wasSuccessful():
|
|
191
188
|
self.stream.write("FAILED (")
|
|
192
189
|
failed, errored = list(map(len, (result.failures, result.errors)))
|
|
193
190
|
if failed:
|
|
194
|
-
self.stream.write("failures
|
|
191
|
+
self.stream.write(f"failures={failed}")
|
|
195
192
|
if errored:
|
|
196
193
|
if failed:
|
|
197
194
|
self.stream.write(", ")
|
|
198
|
-
self.stream.write("errors
|
|
195
|
+
self.stream.write(f"errors={errored}")
|
|
199
196
|
self.stream.writeln(")")
|
|
200
197
|
else:
|
|
201
198
|
self.stream.writeln("OK")
|