comtypes 1.4.9__zip → 1.4.11__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.9 → comtypes-1.4.11}/CHANGES.txt +41 -0
- {comtypes-1.4.9/comtypes.egg-info → comtypes-1.4.11}/PKG-INFO +4 -2
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/GUID.py +34 -13
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/__init__.py +25 -16
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/_comobject.py +92 -39
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/_memberspec.py +112 -78
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/_meta.py +2 -1
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/_post_coinit/_cominterface_meta_patcher.py +3 -6
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/_post_coinit/bstr.py +12 -5
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/_post_coinit/instancemethod.py +1 -2
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/_post_coinit/misc.py +59 -24
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/_post_coinit/unknwn.py +30 -25
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/_safearray.py +2 -2
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/_vtbl.py +52 -55
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/automation.py +19 -14
- comtypes-1.4.11/comtypes/client/__init__.py +42 -0
- comtypes-1.4.11/comtypes/client/_activeobj.py +46 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/client/_code_cache.py +15 -24
- comtypes-1.4.11/comtypes/client/_create.py +147 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/client/_events.py +140 -57
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/client/_generate.py +3 -5
- comtypes-1.4.11/comtypes/client/_managing.py +114 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/client/dynamic.py +2 -3
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/client/lazybind.py +10 -11
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/connectionpoints.py +38 -3
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/errorinfo.py +72 -21
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/git.py +4 -3
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/hints.pyi +15 -2
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/hresult.py +16 -6
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/logutil.py +15 -3
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/messageloop.py +15 -13
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/persist.py +3 -5
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/safearray.py +8 -6
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/server/__init__.py +22 -4
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/server/automation.py +1 -2
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/server/connectionpoints.py +71 -70
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/server/inprocserver.py +14 -8
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/server/localserver.py +28 -16
- comtypes-1.4.11/comtypes/server/register.py +478 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/shelllink.py +13 -7
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/stream.py +7 -4
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/TestComServer.py +6 -7
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/TestDispServer.py +4 -2
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/__init__.py +1 -1
- comtypes-1.4.11/comtypes/test/find_memleak.py +72 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/runtests.py +1 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/setup.py +2 -1
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_BSTR.py +7 -17
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_GUID.py +7 -7
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_QueryService.py +1 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_agilent.py +4 -3
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_basic.py +18 -9
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_clear_cache.py +1 -1
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_client.py +2 -2
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_client_dynamic.py +2 -2
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_client_regenerate_modules.py +2 -2
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_collections.py +7 -4
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_comobject.py +22 -9
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_comserver.py +56 -3
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_dict.py +2 -1
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_dispifc_records.py +1 -1
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_dispifc_safearrays.py +1 -1
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_dyndispatch.py +5 -2
- comtypes-1.4.11/comtypes/test/test_errorinfo.py +115 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_findgendir.py +1 -2
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_getactiveobj.py +4 -4
- comtypes-1.4.11/comtypes/test/test_hresult.py +48 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_ie.py +19 -6
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_ienum.py +2 -2
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_imfattributes.py +13 -3
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_inout_args.py +10 -3
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_midl_safearray_create.py +6 -4
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_monikers.py +23 -9
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_msscript.py +2 -1
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_npsupport.py +4 -4
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_outparam.py +22 -6
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_persist.py +2 -4
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_recordinfo.py +1 -1
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_safearray.py +2 -1
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_sapi.py +4 -1
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_server_register.py +114 -125
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_shelllink.py +2 -3
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_storage.py +12 -6
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_stream.py +16 -5
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_subinterface.py +4 -2
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_typeannotator.py +1 -2
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_typeinfo.py +36 -7
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_urlhistory.py +7 -4
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_variant.py +5 -3
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_w_getopt.py +4 -4
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_word.py +1 -1
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/tools/codegenerator/codegenerator.py +167 -435
- comtypes-1.4.11/comtypes/tools/codegenerator/comments.py +79 -0
- comtypes-1.4.11/comtypes/tools/codegenerator/heads.py +192 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/tools/codegenerator/helpers.py +3 -6
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/tools/codegenerator/namespaces.py +13 -5
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/tools/codegenerator/typeannotator.py +13 -3
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/tools/tlbparser.py +25 -25
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/tools/typedesc.py +3 -2
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/tools/typedesc_base.py +2 -2
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/typeinfo.py +163 -51
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/viewobject.py +2 -4
- {comtypes-1.4.9 → comtypes-1.4.11/comtypes.egg-info}/PKG-INFO +4 -2
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes.egg-info/SOURCES.txt +7 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/pyproject.toml +10 -23
- comtypes-1.4.9/comtypes/client/__init__.py +0 -323
- comtypes-1.4.9/comtypes/server/register.py +0 -419
- comtypes-1.4.9/comtypes/test/find_memleak.py +0 -76
- {comtypes-1.4.9 → comtypes-1.4.11}/LICENSE.txt +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/MANIFEST.in +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/README.md +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/_npsupport.py +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/_post_coinit/__init__.py +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/_tlib_version_checker.py +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/clear_cache.py +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/client/_constants.py +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/patcher.py +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/server/w_getopt.py +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/TestComServer.idl +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/TestComServer.tlb +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/TestDispServer.idl +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/TestDispServer.tlb +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/mylib.idl +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/mylib.tlb +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/mytypelib.idl +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_DISPPARAMS.py +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_avmc.py +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_casesensitivity.py +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_createwrappers.py +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_dispinterface.py +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_excel.py +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_jscript.js +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_pump_events.py +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_server.py +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_showevents.py +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_win32com_interop.py +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_wmi.py +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/urlhist.tlb +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/tools/__init__.py +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/tools/codegenerator/__init__.py +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/tools/codegenerator/modulenamer.py +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/tools/codegenerator/packing.py +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/util.py +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes.egg-info/dependency_links.txt +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes.egg-info/entry_points.txt +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes.egg-info/top_level.txt +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/setup.cfg +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/setup.py +0 -0
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from typing import TYPE_CHECKING, Any, Optional, Type, TypeVar, overload
|
|
3
|
+
from typing import Union as _UnionT
|
|
4
|
+
|
|
5
|
+
import comtypes
|
|
6
|
+
import comtypes.client.dynamic
|
|
7
|
+
from comtypes import COSERVERINFO, GUID, CoClass, IUnknown, automation
|
|
8
|
+
from comtypes.client._managing import _manage
|
|
9
|
+
|
|
10
|
+
if TYPE_CHECKING:
|
|
11
|
+
from comtypes import hints # type: ignore
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
_T_IUnknown = TypeVar("_T_IUnknown", bound=IUnknown)
|
|
15
|
+
logger = logging.getLogger(__name__)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
################################################################
|
|
19
|
+
#
|
|
20
|
+
# Object creation
|
|
21
|
+
#
|
|
22
|
+
if TYPE_CHECKING:
|
|
23
|
+
|
|
24
|
+
@overload
|
|
25
|
+
def GetClassObject(
|
|
26
|
+
progid: _UnionT[str, Type[CoClass], GUID],
|
|
27
|
+
clsctx: Optional[int] = None,
|
|
28
|
+
pServerInfo: Optional[COSERVERINFO] = None,
|
|
29
|
+
interface: None = None,
|
|
30
|
+
) -> hints.IClassFactory: ...
|
|
31
|
+
@overload
|
|
32
|
+
def GetClassObject(
|
|
33
|
+
progid: _UnionT[str, Type[CoClass], GUID],
|
|
34
|
+
clsctx: Optional[int] = None,
|
|
35
|
+
pServerInfo: Optional[COSERVERINFO] = None,
|
|
36
|
+
interface: Type[_T_IUnknown] = hints.IClassFactory,
|
|
37
|
+
) -> _T_IUnknown: ...
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def GetClassObject(progid, clsctx=None, pServerInfo=None, interface=None):
|
|
41
|
+
# type: (_UnionT[str, Type[CoClass], GUID], Optional[int], Optional[COSERVERINFO], Optional[Type[IUnknown]]) -> IUnknown
|
|
42
|
+
"""Create and return the class factory for a COM object.
|
|
43
|
+
|
|
44
|
+
'clsctx' specifies how to create the object, use the CLSCTX_... constants.
|
|
45
|
+
'pServerInfo', if used, must be a pointer to a comtypes.COSERVERINFO instance
|
|
46
|
+
'interface' may be used to request an interface other than IClassFactory
|
|
47
|
+
"""
|
|
48
|
+
clsid = GUID.from_progid(progid)
|
|
49
|
+
return comtypes.CoGetClassObject(clsid, clsctx, pServerInfo, interface)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
@overload
|
|
53
|
+
def CreateObject(progid: _UnionT[str, Type[CoClass], GUID]) -> Any: ...
|
|
54
|
+
@overload
|
|
55
|
+
def CreateObject(
|
|
56
|
+
progid: _UnionT[str, Type[CoClass], GUID],
|
|
57
|
+
clsctx: Optional[int] = None,
|
|
58
|
+
machine: Optional[str] = None,
|
|
59
|
+
interface: Optional[Type[_T_IUnknown]] = None,
|
|
60
|
+
dynamic: bool = ...,
|
|
61
|
+
pServerInfo: Optional[COSERVERINFO] = None,
|
|
62
|
+
) -> _T_IUnknown: ...
|
|
63
|
+
def CreateObject(
|
|
64
|
+
progid: _UnionT[str, Type[CoClass], GUID], # which object to create
|
|
65
|
+
clsctx: Optional[int] = None, # how to create the object
|
|
66
|
+
machine: Optional[str] = None, # where to create the object
|
|
67
|
+
interface: Optional[Type[IUnknown]] = None, # the interface we want
|
|
68
|
+
dynamic: bool = False, # use dynamic dispatch
|
|
69
|
+
pServerInfo: Optional[COSERVERINFO] = None, # server info struct for remoting
|
|
70
|
+
) -> Any:
|
|
71
|
+
"""Create a COM object from 'progid', and try to QueryInterface()
|
|
72
|
+
it to the most useful interface, generating typelib support on
|
|
73
|
+
demand. A pointer to this interface is returned.
|
|
74
|
+
|
|
75
|
+
'progid' may be a string like "InternetExplorer.Application",
|
|
76
|
+
a string specifying a clsid, a GUID instance, or an object with
|
|
77
|
+
a _clsid_ attribute which should be any of the above.
|
|
78
|
+
'clsctx' specifies how to create the object, use the CLSCTX_... constants.
|
|
79
|
+
'machine' allows to specify a remote machine to create the object on.
|
|
80
|
+
'interface' allows to force a certain interface
|
|
81
|
+
'dynamic=True' will return a dynamic dispatch object
|
|
82
|
+
'pServerInfo', if used, must be a pointer to a comtypes.COSERVERINFO instance
|
|
83
|
+
This supercedes 'machine'.
|
|
84
|
+
|
|
85
|
+
You can also later request to receive events with GetEvents().
|
|
86
|
+
"""
|
|
87
|
+
clsid = GUID.from_progid(progid)
|
|
88
|
+
logger.debug("%s -> %s", progid, clsid)
|
|
89
|
+
if dynamic:
|
|
90
|
+
if interface:
|
|
91
|
+
raise ValueError("interface and dynamic are mutually exclusive")
|
|
92
|
+
interface = automation.IDispatch
|
|
93
|
+
elif interface is None:
|
|
94
|
+
interface = getattr(progid, "_com_interfaces_", [None])[0]
|
|
95
|
+
if machine is None and pServerInfo is None:
|
|
96
|
+
logger.debug(
|
|
97
|
+
"CoCreateInstance(%s, clsctx=%s, interface=%s)", clsid, clsctx, interface
|
|
98
|
+
)
|
|
99
|
+
obj = comtypes.CoCreateInstance(clsid, clsctx=clsctx, interface=interface)
|
|
100
|
+
else:
|
|
101
|
+
logger.debug(
|
|
102
|
+
"CoCreateInstanceEx(%s, clsctx=%s, interface=%s, machine=%s,\
|
|
103
|
+
pServerInfo=%s)",
|
|
104
|
+
clsid,
|
|
105
|
+
clsctx,
|
|
106
|
+
interface,
|
|
107
|
+
machine,
|
|
108
|
+
pServerInfo,
|
|
109
|
+
)
|
|
110
|
+
if machine is not None and pServerInfo is not None:
|
|
111
|
+
msg = "You cannot set both the machine name and server info."
|
|
112
|
+
raise ValueError(msg)
|
|
113
|
+
obj = comtypes.CoCreateInstanceEx(
|
|
114
|
+
clsid,
|
|
115
|
+
clsctx=clsctx,
|
|
116
|
+
interface=interface,
|
|
117
|
+
machine=machine,
|
|
118
|
+
pServerInfo=pServerInfo,
|
|
119
|
+
)
|
|
120
|
+
if dynamic:
|
|
121
|
+
return comtypes.client.dynamic.Dispatch(obj)
|
|
122
|
+
return _manage(obj, clsid, interface=interface)
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
@overload
|
|
126
|
+
def CoGetObject(displayname: str, interface: Type[_T_IUnknown]) -> _T_IUnknown: ...
|
|
127
|
+
@overload
|
|
128
|
+
def CoGetObject(
|
|
129
|
+
displayname: str, interface: None = None, dynamic: bool = False
|
|
130
|
+
) -> Any: ...
|
|
131
|
+
def CoGetObject(
|
|
132
|
+
displayname: str,
|
|
133
|
+
interface: Optional[Type[IUnknown]] = None,
|
|
134
|
+
dynamic: bool = False,
|
|
135
|
+
) -> Any:
|
|
136
|
+
"""Create an object by calling CoGetObject(displayname).
|
|
137
|
+
|
|
138
|
+
Additional parameters have the same meaning as in CreateObject().
|
|
139
|
+
"""
|
|
140
|
+
if dynamic:
|
|
141
|
+
if interface is not None:
|
|
142
|
+
raise ValueError("interface and dynamic are mutually exclusive")
|
|
143
|
+
interface = automation.IDispatch
|
|
144
|
+
punk = comtypes.CoGetObject(displayname, interface)
|
|
145
|
+
if dynamic:
|
|
146
|
+
return comtypes.client.dynamic.Dispatch(punk)
|
|
147
|
+
return _manage(punk, clsid=None, interface=interface)
|
|
@@ -1,55 +1,122 @@
|
|
|
1
1
|
import ctypes
|
|
2
|
+
import logging
|
|
2
3
|
import traceback
|
|
4
|
+
from _ctypes import COMError
|
|
5
|
+
from ctypes import HRESULT, POINTER, WINFUNCTYPE, OleDLL, Structure, WinDLL, byref
|
|
6
|
+
from ctypes.wintypes import (
|
|
7
|
+
BOOL,
|
|
8
|
+
DWORD,
|
|
9
|
+
HANDLE,
|
|
10
|
+
LPCSTR,
|
|
11
|
+
LPDWORD,
|
|
12
|
+
LPHANDLE,
|
|
13
|
+
LPVOID,
|
|
14
|
+
ULONG,
|
|
15
|
+
)
|
|
16
|
+
from typing import Any, Callable, Optional, Type
|
|
17
|
+
from typing import Union as _UnionT
|
|
18
|
+
|
|
3
19
|
import comtypes
|
|
4
|
-
import
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
import comtypes.connectionpoints
|
|
20
|
+
from comtypes import COMObject, IUnknown, hresult
|
|
21
|
+
from comtypes._comobject import _MethodFinder
|
|
22
|
+
from comtypes.automation import DISPATCH_METHOD, IDispatch
|
|
8
23
|
from comtypes.client._generate import GetModule
|
|
9
|
-
import
|
|
24
|
+
from comtypes.connectionpoints import IConnectionPoint, IConnectionPointContainer
|
|
25
|
+
from comtypes.typeinfo import GUIDKIND_DEFAULT_SOURCE_DISP_IID, IProvideClassInfo2
|
|
10
26
|
|
|
11
27
|
logger = logging.getLogger(__name__)
|
|
12
28
|
|
|
13
29
|
|
|
30
|
+
class SECURITY_ATTRIBUTES(Structure):
|
|
31
|
+
_fields_ = [
|
|
32
|
+
("nLength", DWORD),
|
|
33
|
+
("lpSecurityDescriptor", LPVOID),
|
|
34
|
+
("bInheritHandle", BOOL),
|
|
35
|
+
]
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
_ole32 = OleDLL("ole32")
|
|
39
|
+
|
|
40
|
+
_CoWaitForMultipleHandles = _ole32.CoWaitForMultipleHandles
|
|
41
|
+
_CoWaitForMultipleHandles.argtypes = [DWORD, DWORD, ULONG, LPHANDLE, LPDWORD]
|
|
42
|
+
_CoWaitForMultipleHandles.restype = HRESULT
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
_kernel32 = WinDLL("kernel32")
|
|
46
|
+
|
|
47
|
+
_CreateEventA = _kernel32.CreateEventA
|
|
48
|
+
_CreateEventA.argtypes = [POINTER(SECURITY_ATTRIBUTES), BOOL, BOOL, LPCSTR]
|
|
49
|
+
_CreateEventA.restype = HANDLE
|
|
50
|
+
|
|
51
|
+
_SetEvent = _kernel32.SetEvent
|
|
52
|
+
_SetEvent.argtypes = [HANDLE]
|
|
53
|
+
_SetEvent.restype = BOOL
|
|
54
|
+
|
|
55
|
+
PHANDLER_ROUTINE = WINFUNCTYPE(BOOL, DWORD)
|
|
56
|
+
_SetConsoleCtrlHandler = _kernel32.SetConsoleCtrlHandler
|
|
57
|
+
_SetConsoleCtrlHandler.argtypes = [PHANDLER_ROUTINE, BOOL]
|
|
58
|
+
_SetConsoleCtrlHandler.restype = BOOL
|
|
59
|
+
|
|
60
|
+
_CloseHandle = _kernel32.CloseHandle
|
|
61
|
+
_CloseHandle.argtypes = [HANDLE]
|
|
62
|
+
_CloseHandle.restype = BOOL
|
|
63
|
+
|
|
64
|
+
_ReceiverType = _UnionT[COMObject, IUnknown]
|
|
65
|
+
|
|
66
|
+
|
|
14
67
|
class _AdviseConnection(object):
|
|
15
|
-
|
|
68
|
+
cp: Optional[IConnectionPoint]
|
|
69
|
+
cookie: Optional[int]
|
|
70
|
+
receiver: Optional[_ReceiverType]
|
|
71
|
+
|
|
72
|
+
def __init__(
|
|
73
|
+
self, source: IUnknown, interface: Type[IUnknown], receiver: _ReceiverType
|
|
74
|
+
) -> None:
|
|
75
|
+
# Pre-initializing attributes to avoid AttributeError after failed connection.
|
|
16
76
|
self.cp = None
|
|
17
77
|
self.cookie = None
|
|
18
78
|
self.receiver = None
|
|
19
79
|
self._connect(source, interface, receiver)
|
|
20
80
|
|
|
21
|
-
def _connect(
|
|
22
|
-
|
|
23
|
-
|
|
81
|
+
def _connect(
|
|
82
|
+
self, source: IUnknown, interface: Type[IUnknown], receiver: _ReceiverType
|
|
83
|
+
) -> None:
|
|
84
|
+
cpc = source.QueryInterface(IConnectionPointContainer)
|
|
85
|
+
self.cp = cpc.FindConnectionPoint(byref(interface._iid_))
|
|
24
86
|
logger.debug("Start advise %s", interface)
|
|
25
|
-
|
|
87
|
+
# Since `POINTER(IUnknown).from_param`(`_compointer_base.from_param`)
|
|
88
|
+
# can accept a `COMObject` instance, `IConnectionPoint.Advise` can
|
|
89
|
+
# take either a COM object or a COM interface pointer.
|
|
90
|
+
self.cookie = self.cp.Advise(receiver) # type: ignore
|
|
26
91
|
self.receiver = receiver
|
|
27
92
|
|
|
28
|
-
def disconnect(self):
|
|
93
|
+
def disconnect(self) -> None:
|
|
29
94
|
if self.cookie:
|
|
95
|
+
assert self.cp is not None
|
|
30
96
|
self.cp.Unadvise(self.cookie)
|
|
31
97
|
logger.debug("Unadvised %s", self.cp)
|
|
32
98
|
self.cp = None
|
|
33
99
|
self.cookie = None
|
|
34
100
|
del self.receiver
|
|
35
101
|
|
|
36
|
-
def __del__(self):
|
|
102
|
+
def __del__(self) -> None:
|
|
37
103
|
try:
|
|
38
104
|
if self.cookie is not None:
|
|
105
|
+
assert self.cp is not None
|
|
39
106
|
self.cp.Unadvise(self.cookie)
|
|
40
|
-
except (
|
|
107
|
+
except (COMError, WindowsError):
|
|
41
108
|
# Are we sure we want to ignore errors here?
|
|
42
109
|
pass
|
|
43
110
|
|
|
44
111
|
|
|
45
|
-
def FindOutgoingInterface(source):
|
|
112
|
+
def FindOutgoingInterface(source: IUnknown) -> Type[IUnknown]:
|
|
46
113
|
"""XXX Describe the strategy that is used..."""
|
|
47
114
|
# If the COM object implements IProvideClassInfo2, it is easy to
|
|
48
115
|
# find the default outgoing interface.
|
|
49
116
|
try:
|
|
50
|
-
pci = source.QueryInterface(
|
|
51
|
-
guid = pci.GetGUID(
|
|
52
|
-
except
|
|
117
|
+
pci = source.QueryInterface(IProvideClassInfo2)
|
|
118
|
+
guid = pci.GetGUID(GUIDKIND_DEFAULT_SOURCE_DISP_IID)
|
|
119
|
+
except COMError:
|
|
53
120
|
pass
|
|
54
121
|
else:
|
|
55
122
|
# another try: block needed?
|
|
@@ -68,7 +135,7 @@ def FindOutgoingInterface(source):
|
|
|
68
135
|
# comtypes.client):
|
|
69
136
|
clsid = source.__dict__.get("__clsid")
|
|
70
137
|
try:
|
|
71
|
-
interface = comtypes.com_coclass_registry[clsid]._outgoing_interfaces_[0]
|
|
138
|
+
interface = comtypes.com_coclass_registry[clsid]._outgoing_interfaces_[0] # type: ignore
|
|
72
139
|
except KeyError:
|
|
73
140
|
pass
|
|
74
141
|
else:
|
|
@@ -86,7 +153,7 @@ def find_single_connection_interface(source):
|
|
|
86
153
|
# Enumerate the connection interfaces. If we find a single one,
|
|
87
154
|
# return it, if there are more, we give up since we cannot
|
|
88
155
|
# determine which one to use.
|
|
89
|
-
cpc = source.QueryInterface(
|
|
156
|
+
cpc = source.QueryInterface(IConnectionPointContainer)
|
|
90
157
|
enum = cpc.EnumConnectionPoints()
|
|
91
158
|
iid = enum.next().GetConnectionInterface()
|
|
92
159
|
try:
|
|
@@ -105,32 +172,33 @@ def find_single_connection_interface(source):
|
|
|
105
172
|
return None
|
|
106
173
|
|
|
107
174
|
|
|
108
|
-
def report_errors(func):
|
|
175
|
+
def report_errors(func: Callable[..., Any]) -> Callable[..., Any]:
|
|
109
176
|
# This decorator preserves parts of the decorated function
|
|
110
177
|
# signature, so that the comtypes special-casing for the 'this'
|
|
111
178
|
# parameter still works.
|
|
112
179
|
if func.__code__.co_varnames[:2] == ("self", "this"):
|
|
113
180
|
|
|
114
|
-
def
|
|
181
|
+
def with_this(self, this, *args, **kw):
|
|
115
182
|
try:
|
|
116
183
|
return func(self, this, *args, **kw)
|
|
117
184
|
except:
|
|
118
185
|
traceback.print_exc()
|
|
119
186
|
raise
|
|
120
187
|
|
|
188
|
+
error_printer = with_this
|
|
189
|
+
|
|
121
190
|
else:
|
|
122
191
|
|
|
123
|
-
def
|
|
192
|
+
def without_this(*args, **kw):
|
|
124
193
|
try:
|
|
125
194
|
return func(*args, **kw)
|
|
126
195
|
except:
|
|
127
196
|
traceback.print_exc()
|
|
128
197
|
raise
|
|
129
198
|
|
|
130
|
-
|
|
131
|
-
|
|
199
|
+
error_printer = without_this
|
|
132
200
|
|
|
133
|
-
|
|
201
|
+
return error_printer
|
|
134
202
|
|
|
135
203
|
|
|
136
204
|
class _SinkMethodFinder(_MethodFinder):
|
|
@@ -140,11 +208,11 @@ class _SinkMethodFinder(_MethodFinder):
|
|
|
140
208
|
event handlers.
|
|
141
209
|
"""
|
|
142
210
|
|
|
143
|
-
def __init__(self, inst, sink):
|
|
211
|
+
def __init__(self, inst: COMObject, sink: Any) -> None:
|
|
144
212
|
super(_SinkMethodFinder, self).__init__(inst)
|
|
145
213
|
self.sink = sink
|
|
146
214
|
|
|
147
|
-
def find_method(self, fq_name, mthname):
|
|
215
|
+
def find_method(self, fq_name: str, mthname: str) -> Callable[..., Any]:
|
|
148
216
|
impl = self._find_method(fq_name, mthname)
|
|
149
217
|
# Caller of this method catches AttributeError,
|
|
150
218
|
# so we need to be careful in the following code
|
|
@@ -159,7 +227,7 @@ class _SinkMethodFinder(_MethodFinder):
|
|
|
159
227
|
except AttributeError as details:
|
|
160
228
|
raise RuntimeError(details)
|
|
161
229
|
|
|
162
|
-
def _find_method(self, fq_name, mthname):
|
|
230
|
+
def _find_method(self, fq_name: str, mthname: str) -> Callable[..., Any]:
|
|
163
231
|
try:
|
|
164
232
|
return super(_SinkMethodFinder, self).find_method(fq_name, mthname)
|
|
165
233
|
except AttributeError:
|
|
@@ -169,11 +237,11 @@ class _SinkMethodFinder(_MethodFinder):
|
|
|
169
237
|
return getattr(self.sink, mthname)
|
|
170
238
|
|
|
171
239
|
|
|
172
|
-
def CreateEventReceiver(interface, handler):
|
|
173
|
-
class Sink(
|
|
240
|
+
def CreateEventReceiver(interface: Type[IUnknown], handler: Any) -> COMObject:
|
|
241
|
+
class Sink(COMObject):
|
|
174
242
|
_com_interfaces_ = [interface]
|
|
175
243
|
|
|
176
|
-
def _get_method_finder_(self, itf):
|
|
244
|
+
def _get_method_finder_(self, itf: Type[IUnknown]) -> _MethodFinder:
|
|
177
245
|
# Use a special MethodFinder that will first try 'self',
|
|
178
246
|
# then the sink.
|
|
179
247
|
return _SinkMethodFinder(self, handler)
|
|
@@ -182,25 +250,25 @@ def CreateEventReceiver(interface, handler):
|
|
|
182
250
|
|
|
183
251
|
# Since our Sink object doesn't have typeinfo, it needs a
|
|
184
252
|
# _dispimpl_ dictionary to dispatch events received via Invoke.
|
|
185
|
-
if issubclass(interface,
|
|
186
|
-
sink, "_dispimpl_"
|
|
187
|
-
):
|
|
253
|
+
if issubclass(interface, IDispatch) and not hasattr(sink, "_dispimpl_"):
|
|
188
254
|
finder = sink._get_method_finder_(interface)
|
|
189
255
|
dispimpl = sink._dispimpl_ = {}
|
|
190
256
|
for m in interface._methods_:
|
|
191
|
-
restype, mthname, argtypes, paramflags, idlflags, helptext = m
|
|
192
257
|
# Can dispid be at a different index? Should check code generator...
|
|
193
258
|
# ...but hand-written code should also work...
|
|
194
|
-
dispid = idlflags[0]
|
|
195
|
-
|
|
259
|
+
dispid = m.idlflags[0]
|
|
260
|
+
assert isinstance(dispid, comtypes.dispid)
|
|
261
|
+
impl = finder.get_impl(interface, m.name, m.paramflags, m.idlflags)
|
|
196
262
|
# XXX Wouldn't work for 'propget', 'propput', 'propputref'
|
|
197
263
|
# methods - are they allowed on event interfaces?
|
|
198
|
-
dispimpl[(dispid,
|
|
264
|
+
dispimpl[(dispid, DISPATCH_METHOD)] = impl
|
|
199
265
|
|
|
200
266
|
return sink
|
|
201
267
|
|
|
202
268
|
|
|
203
|
-
def GetEvents(
|
|
269
|
+
def GetEvents(
|
|
270
|
+
source: IUnknown, sink: Any, interface: Optional[Type[IUnknown]] = None
|
|
271
|
+
) -> _AdviseConnection:
|
|
204
272
|
"""Receive COM events from 'source'. Events will call methods on
|
|
205
273
|
the 'sink' object. 'interface' is the source interface to use.
|
|
206
274
|
"""
|
|
@@ -218,7 +286,7 @@ def GetEvents(source, sink, interface=None):
|
|
|
218
286
|
class EventDumper(object):
|
|
219
287
|
"""Universal sink for COM events."""
|
|
220
288
|
|
|
221
|
-
def __getattr__(self, name):
|
|
289
|
+
def __getattr__(self, name: str) -> Callable[..., Any]:
|
|
222
290
|
"Create event handler methods on demand"
|
|
223
291
|
if name.startswith("__") and name.endswith("__"):
|
|
224
292
|
raise AttributeError(name)
|
|
@@ -232,13 +300,15 @@ class EventDumper(object):
|
|
|
232
300
|
return comtypes.instancemethod(handler, self, EventDumper)
|
|
233
301
|
|
|
234
302
|
|
|
235
|
-
def ShowEvents(
|
|
303
|
+
def ShowEvents(
|
|
304
|
+
source: IUnknown, interface: Optional[Type[IUnknown]] = None
|
|
305
|
+
) -> _AdviseConnection:
|
|
236
306
|
"""Receive COM events from 'source'. A special event sink will be
|
|
237
307
|
used that first prints the names of events that are found in the
|
|
238
308
|
outgoing interface, and will also print out the events when they
|
|
239
309
|
are fired.
|
|
240
310
|
"""
|
|
241
|
-
return
|
|
311
|
+
return GetEvents(source, sink=EventDumper(), interface=interface)
|
|
242
312
|
|
|
243
313
|
|
|
244
314
|
# This type is used inside 'PumpEvents', but if we create the type
|
|
@@ -246,8 +316,24 @@ def ShowEvents(source, interface=None):
|
|
|
246
316
|
# garbage for each call. So we define it here instead.
|
|
247
317
|
_handles_type = ctypes.c_void_p * 1
|
|
248
318
|
|
|
319
|
+
# The type of control signal received by the handler.
|
|
320
|
+
CTRL_C_EVENT = 0
|
|
321
|
+
CTRL_BREAK_EVENT = 1
|
|
322
|
+
CTRL_CLOSE_EVENT = 2
|
|
323
|
+
CTRL_LOGOFF_EVENT = 5
|
|
324
|
+
CTRL_SHUTDOWN_EVENT = 6
|
|
249
325
|
|
|
250
|
-
|
|
326
|
+
# Specifiers for the behavior of the CoWaitForMultipleHandles function.
|
|
327
|
+
# tagCOWAIT_FLAGS = ctypes.c_int
|
|
328
|
+
COWAIT_DEFAULT = 0
|
|
329
|
+
COWAIT_WAITALL = 1
|
|
330
|
+
COWAIT_ALERTABLE = 2
|
|
331
|
+
COWAIT_INPUTAVAILABLE = 4
|
|
332
|
+
COWAIT_DISPATCH_CALLS = 8
|
|
333
|
+
COWAIT_DISPATCH_WINDOW_MESSAGES = 16
|
|
334
|
+
|
|
335
|
+
|
|
336
|
+
def PumpEvents(timeout: Any) -> None:
|
|
251
337
|
"""This following code waits for 'timeout' seconds in the way
|
|
252
338
|
required for COM, internally doing the correct things depending
|
|
253
339
|
on the COM appartment of the current thread. It is possible to
|
|
@@ -274,35 +360,32 @@ def PumpEvents(timeout):
|
|
|
274
360
|
# CoWaitForMultipleHandles calls the Win32 function
|
|
275
361
|
# MsgWaitForMultipleObjects.
|
|
276
362
|
|
|
277
|
-
hevt =
|
|
363
|
+
hevt = _CreateEventA(None, True, False, None)
|
|
278
364
|
handles = _handles_type(hevt)
|
|
279
|
-
RPC_S_CALLPENDING = -2147417835
|
|
280
365
|
|
|
281
|
-
# @ctypes.WINFUNCTYPE(
|
|
366
|
+
# @ctypes.WINFUNCTYPE(BOOL, DWORD)
|
|
282
367
|
def HandlerRoutine(dwCtrlType):
|
|
283
|
-
if dwCtrlType ==
|
|
284
|
-
|
|
368
|
+
if dwCtrlType == CTRL_C_EVENT: # CTRL+C
|
|
369
|
+
_SetEvent(hevt)
|
|
285
370
|
return 1
|
|
286
371
|
return 0
|
|
287
372
|
|
|
288
|
-
HandlerRoutine
|
|
289
|
-
|
|
290
|
-
ctypes.windll.kernel32.SetConsoleCtrlHandler(HandlerRoutine, 1)
|
|
373
|
+
_SetConsoleCtrlHandler(PHANDLER_ROUTINE(HandlerRoutine), 1)
|
|
291
374
|
|
|
292
375
|
try:
|
|
293
376
|
try:
|
|
294
|
-
|
|
295
|
-
|
|
377
|
+
_CoWaitForMultipleHandles(
|
|
378
|
+
COWAIT_DEFAULT,
|
|
296
379
|
int(timeout * 1000),
|
|
297
380
|
len(handles),
|
|
298
381
|
handles,
|
|
299
|
-
|
|
382
|
+
byref(ctypes.c_ulong()),
|
|
300
383
|
)
|
|
301
384
|
except WindowsError as details:
|
|
302
|
-
if details.winerror != RPC_S_CALLPENDING: # timeout expired
|
|
385
|
+
if details.winerror != hresult.RPC_S_CALLPENDING: # timeout expired
|
|
303
386
|
raise
|
|
304
387
|
else:
|
|
305
388
|
raise KeyboardInterrupt
|
|
306
389
|
finally:
|
|
307
|
-
|
|
308
|
-
|
|
390
|
+
_CloseHandle(hevt)
|
|
391
|
+
_SetConsoleCtrlHandler(PHANDLER_ROUTINE(HandlerRoutine), 0)
|
|
@@ -5,18 +5,16 @@ import logging
|
|
|
5
5
|
import os
|
|
6
6
|
import sys
|
|
7
7
|
import types
|
|
8
|
-
from typing import Any, Tuple, List, Mapping, Optional, Dict, Union as _UnionT
|
|
9
8
|
import winreg
|
|
9
|
+
from typing import Any, Dict, List, Mapping, Optional, Tuple
|
|
10
|
+
from typing import Union as _UnionT
|
|
10
11
|
|
|
11
|
-
from comtypes import GUID, typeinfo
|
|
12
12
|
import comtypes.client
|
|
13
|
+
from comtypes import GUID, typeinfo
|
|
13
14
|
from comtypes.tools import codegenerator, tlbparser
|
|
14
15
|
|
|
15
|
-
|
|
16
16
|
logger = logging.getLogger(__name__)
|
|
17
17
|
|
|
18
|
-
PATH = os.environ["PATH"].split(os.pathsep)
|
|
19
|
-
|
|
20
18
|
|
|
21
19
|
def _my_import(fullname: str) -> types.ModuleType:
|
|
22
20
|
"""helper function to import dotted modules"""
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from _ctypes import COMError
|
|
3
|
+
from typing import Any, Optional, Type
|
|
4
|
+
|
|
5
|
+
import comtypes
|
|
6
|
+
import comtypes.client.dynamic
|
|
7
|
+
from comtypes import GUID, IUnknown, automation, typeinfo
|
|
8
|
+
from comtypes.client._generate import GetModule
|
|
9
|
+
|
|
10
|
+
logger = logging.getLogger(__name__)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def wrap_outparam(punk: Any) -> Any:
|
|
14
|
+
logger.debug("wrap_outparam(%s)", punk)
|
|
15
|
+
if not punk:
|
|
16
|
+
return None
|
|
17
|
+
if punk.__com_interface__ == automation.IDispatch:
|
|
18
|
+
return GetBestInterface(punk)
|
|
19
|
+
return punk
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def GetBestInterface(punk: Any) -> Any:
|
|
23
|
+
"""Try to QueryInterface a COM pointer to the 'most useful'
|
|
24
|
+
interface.
|
|
25
|
+
|
|
26
|
+
Get type information for the provided object, either via
|
|
27
|
+
IDispatch.GetTypeInfo(), or via IProvideClassInfo.GetClassInfo().
|
|
28
|
+
Generate a wrapper module for the typelib, and QI for the
|
|
29
|
+
interface found.
|
|
30
|
+
"""
|
|
31
|
+
if not punk: # NULL COM pointer
|
|
32
|
+
return punk # or should we return None?
|
|
33
|
+
# find the typelib and the interface name
|
|
34
|
+
logger.debug("GetBestInterface(%s)", punk)
|
|
35
|
+
try:
|
|
36
|
+
try:
|
|
37
|
+
pci = punk.QueryInterface(typeinfo.IProvideClassInfo)
|
|
38
|
+
logger.debug("Does implement IProvideClassInfo")
|
|
39
|
+
except COMError:
|
|
40
|
+
# Some COM objects support IProvideClassInfo2, but not IProvideClassInfo.
|
|
41
|
+
# These objects are broken, but we support them anyway.
|
|
42
|
+
logger.debug(
|
|
43
|
+
"Does NOT implement IProvideClassInfo, trying IProvideClassInfo2"
|
|
44
|
+
)
|
|
45
|
+
pci = punk.QueryInterface(typeinfo.IProvideClassInfo2)
|
|
46
|
+
logger.debug("Does implement IProvideClassInfo2")
|
|
47
|
+
tinfo = pci.GetClassInfo() # TypeInfo for the CoClass
|
|
48
|
+
# find the interface marked as default
|
|
49
|
+
ta = tinfo.GetTypeAttr()
|
|
50
|
+
for index in range(ta.cImplTypes):
|
|
51
|
+
if tinfo.GetImplTypeFlags(index) == 1:
|
|
52
|
+
break
|
|
53
|
+
else:
|
|
54
|
+
if ta.cImplTypes != 1:
|
|
55
|
+
# Hm, should we use dynamic now?
|
|
56
|
+
raise TypeError("No default interface found")
|
|
57
|
+
# Only one interface implemented, use that (even if
|
|
58
|
+
# not marked as default).
|
|
59
|
+
index = 0
|
|
60
|
+
href = tinfo.GetRefTypeOfImplType(index)
|
|
61
|
+
tinfo = tinfo.GetRefTypeInfo(href)
|
|
62
|
+
except COMError:
|
|
63
|
+
logger.debug("Does NOT implement IProvideClassInfo/IProvideClassInfo2")
|
|
64
|
+
try:
|
|
65
|
+
pdisp = punk.QueryInterface(automation.IDispatch)
|
|
66
|
+
except COMError:
|
|
67
|
+
logger.debug("No Dispatch interface: %s", punk)
|
|
68
|
+
return punk
|
|
69
|
+
try:
|
|
70
|
+
tinfo = pdisp.GetTypeInfo(0)
|
|
71
|
+
except COMError:
|
|
72
|
+
pdisp = comtypes.client.dynamic.Dispatch(pdisp)
|
|
73
|
+
logger.debug("IDispatch.GetTypeInfo(0) failed: %s" % pdisp)
|
|
74
|
+
return pdisp
|
|
75
|
+
typeattr = tinfo.GetTypeAttr()
|
|
76
|
+
logger.debug("Default interface is %s", typeattr.guid)
|
|
77
|
+
try:
|
|
78
|
+
punk.QueryInterface(IUnknown, typeattr.guid)
|
|
79
|
+
except COMError:
|
|
80
|
+
logger.debug("Does not implement default interface, returning dynamic object")
|
|
81
|
+
return comtypes.client.dynamic.Dispatch(punk)
|
|
82
|
+
|
|
83
|
+
itf_name = tinfo.GetDocumentation(-1)[0] # interface name
|
|
84
|
+
tlib = tinfo.GetContainingTypeLib()[0] # typelib
|
|
85
|
+
|
|
86
|
+
# import the wrapper, generating it on demand
|
|
87
|
+
mod = GetModule(tlib)
|
|
88
|
+
# Python interface class
|
|
89
|
+
interface = getattr(mod, itf_name)
|
|
90
|
+
logger.debug("Implements default interface from typeinfo %s", interface)
|
|
91
|
+
# QI for this interface
|
|
92
|
+
# XXX
|
|
93
|
+
# What to do if this fails?
|
|
94
|
+
# In the following example the engine.Eval() call returns
|
|
95
|
+
# such an object.
|
|
96
|
+
#
|
|
97
|
+
# engine = CreateObject("MsScriptControl.ScriptControl")
|
|
98
|
+
# engine.Language = "JScript"
|
|
99
|
+
# engine.Eval("[1, 2, 3]")
|
|
100
|
+
#
|
|
101
|
+
# Could the above code, as an optimization, check that QI works,
|
|
102
|
+
# *before* generating the wrapper module?
|
|
103
|
+
result = punk.QueryInterface(interface)
|
|
104
|
+
logger.debug("Final result is %s", result)
|
|
105
|
+
return result
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def _manage(
|
|
109
|
+
obj: Any, clsid: Optional[GUID], interface: Optional[Type[IUnknown]]
|
|
110
|
+
) -> Any:
|
|
111
|
+
obj.__dict__["__clsid"] = str(clsid)
|
|
112
|
+
if interface is None:
|
|
113
|
+
obj = GetBestInterface(obj)
|
|
114
|
+
return obj
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import ctypes
|
|
2
2
|
from typing import Any, Dict, Optional, Set, Type, TypeVar
|
|
3
3
|
|
|
4
|
-
from comtypes import automation
|
|
4
|
+
from comtypes import GUID, COMError, IUnknown, _is_object, automation
|
|
5
|
+
from comtypes import hresult as hres
|
|
5
6
|
from comtypes.client import lazybind
|
|
6
|
-
from comtypes import COMError, GUID, IUnknown, hresult as hres, _is_object
|
|
7
|
-
|
|
8
7
|
|
|
9
8
|
_T_IUnknown = TypeVar("_T_IUnknown", bound=IUnknown)
|
|
10
9
|
# These errors generally mean the property or method exists,
|
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
import comtypes
|
|
2
2
|
import comtypes.automation
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
from comtypes.typeinfo import FUNC_PUREVIRTUAL, FUNC_DISPATCH
|
|
3
|
+
from comtypes.automation import (
|
|
4
|
+
DISPATCH_METHOD,
|
|
5
|
+
DISPATCH_PROPERTYGET,
|
|
6
|
+
DISPATCH_PROPERTYPUT,
|
|
7
|
+
DISPATCH_PROPERTYPUTREF,
|
|
8
|
+
DISPID_NEWENUM,
|
|
9
|
+
DISPID_VALUE,
|
|
10
|
+
IEnumVARIANT,
|
|
11
|
+
)
|
|
12
|
+
from comtypes.typeinfo import FUNC_DISPATCH, FUNC_PUREVIRTUAL
|
|
14
13
|
|
|
15
14
|
|
|
16
15
|
class FuncDesc(object):
|