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.
Files changed (148) hide show
  1. {comtypes-1.4.9 → comtypes-1.4.11}/CHANGES.txt +41 -0
  2. {comtypes-1.4.9/comtypes.egg-info → comtypes-1.4.11}/PKG-INFO +4 -2
  3. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/GUID.py +34 -13
  4. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/__init__.py +25 -16
  5. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/_comobject.py +92 -39
  6. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/_memberspec.py +112 -78
  7. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/_meta.py +2 -1
  8. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/_post_coinit/_cominterface_meta_patcher.py +3 -6
  9. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/_post_coinit/bstr.py +12 -5
  10. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/_post_coinit/instancemethod.py +1 -2
  11. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/_post_coinit/misc.py +59 -24
  12. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/_post_coinit/unknwn.py +30 -25
  13. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/_safearray.py +2 -2
  14. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/_vtbl.py +52 -55
  15. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/automation.py +19 -14
  16. comtypes-1.4.11/comtypes/client/__init__.py +42 -0
  17. comtypes-1.4.11/comtypes/client/_activeobj.py +46 -0
  18. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/client/_code_cache.py +15 -24
  19. comtypes-1.4.11/comtypes/client/_create.py +147 -0
  20. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/client/_events.py +140 -57
  21. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/client/_generate.py +3 -5
  22. comtypes-1.4.11/comtypes/client/_managing.py +114 -0
  23. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/client/dynamic.py +2 -3
  24. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/client/lazybind.py +10 -11
  25. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/connectionpoints.py +38 -3
  26. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/errorinfo.py +72 -21
  27. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/git.py +4 -3
  28. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/hints.pyi +15 -2
  29. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/hresult.py +16 -6
  30. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/logutil.py +15 -3
  31. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/messageloop.py +15 -13
  32. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/persist.py +3 -5
  33. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/safearray.py +8 -6
  34. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/server/__init__.py +22 -4
  35. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/server/automation.py +1 -2
  36. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/server/connectionpoints.py +71 -70
  37. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/server/inprocserver.py +14 -8
  38. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/server/localserver.py +28 -16
  39. comtypes-1.4.11/comtypes/server/register.py +478 -0
  40. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/shelllink.py +13 -7
  41. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/stream.py +7 -4
  42. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/TestComServer.py +6 -7
  43. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/TestDispServer.py +4 -2
  44. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/__init__.py +1 -1
  45. comtypes-1.4.11/comtypes/test/find_memleak.py +72 -0
  46. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/runtests.py +1 -0
  47. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/setup.py +2 -1
  48. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_BSTR.py +7 -17
  49. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_GUID.py +7 -7
  50. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_QueryService.py +1 -0
  51. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_agilent.py +4 -3
  52. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_basic.py +18 -9
  53. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_clear_cache.py +1 -1
  54. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_client.py +2 -2
  55. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_client_dynamic.py +2 -2
  56. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_client_regenerate_modules.py +2 -2
  57. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_collections.py +7 -4
  58. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_comobject.py +22 -9
  59. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_comserver.py +56 -3
  60. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_dict.py +2 -1
  61. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_dispifc_records.py +1 -1
  62. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_dispifc_safearrays.py +1 -1
  63. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_dyndispatch.py +5 -2
  64. comtypes-1.4.11/comtypes/test/test_errorinfo.py +115 -0
  65. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_findgendir.py +1 -2
  66. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_getactiveobj.py +4 -4
  67. comtypes-1.4.11/comtypes/test/test_hresult.py +48 -0
  68. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_ie.py +19 -6
  69. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_ienum.py +2 -2
  70. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_imfattributes.py +13 -3
  71. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_inout_args.py +10 -3
  72. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_midl_safearray_create.py +6 -4
  73. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_monikers.py +23 -9
  74. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_msscript.py +2 -1
  75. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_npsupport.py +4 -4
  76. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_outparam.py +22 -6
  77. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_persist.py +2 -4
  78. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_recordinfo.py +1 -1
  79. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_safearray.py +2 -1
  80. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_sapi.py +4 -1
  81. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_server_register.py +114 -125
  82. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_shelllink.py +2 -3
  83. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_storage.py +12 -6
  84. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_stream.py +16 -5
  85. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_subinterface.py +4 -2
  86. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_typeannotator.py +1 -2
  87. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_typeinfo.py +36 -7
  88. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_urlhistory.py +7 -4
  89. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_variant.py +5 -3
  90. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_w_getopt.py +4 -4
  91. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_word.py +1 -1
  92. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/tools/codegenerator/codegenerator.py +167 -435
  93. comtypes-1.4.11/comtypes/tools/codegenerator/comments.py +79 -0
  94. comtypes-1.4.11/comtypes/tools/codegenerator/heads.py +192 -0
  95. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/tools/codegenerator/helpers.py +3 -6
  96. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/tools/codegenerator/namespaces.py +13 -5
  97. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/tools/codegenerator/typeannotator.py +13 -3
  98. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/tools/tlbparser.py +25 -25
  99. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/tools/typedesc.py +3 -2
  100. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/tools/typedesc_base.py +2 -2
  101. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/typeinfo.py +163 -51
  102. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/viewobject.py +2 -4
  103. {comtypes-1.4.9 → comtypes-1.4.11/comtypes.egg-info}/PKG-INFO +4 -2
  104. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes.egg-info/SOURCES.txt +7 -0
  105. {comtypes-1.4.9 → comtypes-1.4.11}/pyproject.toml +10 -23
  106. comtypes-1.4.9/comtypes/client/__init__.py +0 -323
  107. comtypes-1.4.9/comtypes/server/register.py +0 -419
  108. comtypes-1.4.9/comtypes/test/find_memleak.py +0 -76
  109. {comtypes-1.4.9 → comtypes-1.4.11}/LICENSE.txt +0 -0
  110. {comtypes-1.4.9 → comtypes-1.4.11}/MANIFEST.in +0 -0
  111. {comtypes-1.4.9 → comtypes-1.4.11}/README.md +0 -0
  112. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/_npsupport.py +0 -0
  113. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/_post_coinit/__init__.py +0 -0
  114. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/_tlib_version_checker.py +0 -0
  115. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/clear_cache.py +0 -0
  116. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/client/_constants.py +0 -0
  117. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/patcher.py +0 -0
  118. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/server/w_getopt.py +0 -0
  119. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/TestComServer.idl +0 -0
  120. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/TestComServer.tlb +0 -0
  121. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/TestDispServer.idl +0 -0
  122. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/TestDispServer.tlb +0 -0
  123. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/mylib.idl +0 -0
  124. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/mylib.tlb +0 -0
  125. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/mytypelib.idl +0 -0
  126. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_DISPPARAMS.py +0 -0
  127. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_avmc.py +0 -0
  128. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_casesensitivity.py +0 -0
  129. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_createwrappers.py +0 -0
  130. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_dispinterface.py +0 -0
  131. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_excel.py +0 -0
  132. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_jscript.js +0 -0
  133. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_pump_events.py +0 -0
  134. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_server.py +0 -0
  135. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_showevents.py +0 -0
  136. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_win32com_interop.py +0 -0
  137. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_wmi.py +0 -0
  138. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/urlhist.tlb +0 -0
  139. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/tools/__init__.py +0 -0
  140. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/tools/codegenerator/__init__.py +0 -0
  141. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/tools/codegenerator/modulenamer.py +0 -0
  142. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/tools/codegenerator/packing.py +0 -0
  143. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/util.py +0 -0
  144. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes.egg-info/dependency_links.txt +0 -0
  145. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes.egg-info/entry_points.txt +0 -0
  146. {comtypes-1.4.9 → comtypes-1.4.11}/comtypes.egg-info/top_level.txt +0 -0
  147. {comtypes-1.4.9 → comtypes-1.4.11}/setup.cfg +0 -0
  148. {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 comtypes.hresult
5
- import comtypes.automation
6
- import comtypes.typeinfo
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 logging
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
- def __init__(self, source, interface, receiver):
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(self, source, interface, receiver):
22
- cpc = source.QueryInterface(comtypes.connectionpoints.IConnectionPointContainer)
23
- self.cp = cpc.FindConnectionPoint(ctypes.byref(interface._iid_))
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
- self.cookie = self.cp.Advise(receiver)
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 (comtypes.COMError, WindowsError):
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(comtypes.typeinfo.IProvideClassInfo2)
51
- guid = pci.GetGUID(1)
52
- except comtypes.COMError:
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(comtypes.connectionpoints.IConnectionPointContainer)
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 error_printer(self, this, *args, **kw):
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 error_printer(*args, **kw):
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
- return error_printer
131
-
199
+ error_printer = without_this
132
200
 
133
- from comtypes._comobject import _MethodFinder
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(comtypes.COMObject):
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, comtypes.automation.IDispatch) and not hasattr(
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
- impl = finder.get_impl(interface, mthname, paramflags, idlflags)
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, comtypes.automation.DISPATCH_METHOD)] = impl
264
+ dispimpl[(dispid, DISPATCH_METHOD)] = impl
199
265
 
200
266
  return sink
201
267
 
202
268
 
203
- def GetEvents(source, sink, interface=None):
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(source, interface=None):
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 comtypes.client.GetEvents(source, sink=EventDumper(), interface=interface)
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
- def PumpEvents(timeout):
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 = ctypes.windll.kernel32.CreateEventA(None, True, False, None)
363
+ hevt = _CreateEventA(None, True, False, None)
278
364
  handles = _handles_type(hevt)
279
- RPC_S_CALLPENDING = -2147417835
280
365
 
281
- # @ctypes.WINFUNCTYPE(ctypes.c_int, ctypes.c_uint)
366
+ # @ctypes.WINFUNCTYPE(BOOL, DWORD)
282
367
  def HandlerRoutine(dwCtrlType):
283
- if dwCtrlType == 0: # CTRL+C
284
- ctypes.windll.kernel32.SetEvent(hevt)
368
+ if dwCtrlType == CTRL_C_EVENT: # CTRL+C
369
+ _SetEvent(hevt)
285
370
  return 1
286
371
  return 0
287
372
 
288
- HandlerRoutine = ctypes.WINFUNCTYPE(ctypes.c_int, ctypes.c_uint)(HandlerRoutine)
289
-
290
- ctypes.windll.kernel32.SetConsoleCtrlHandler(HandlerRoutine, 1)
373
+ _SetConsoleCtrlHandler(PHANDLER_ROUTINE(HandlerRoutine), 1)
291
374
 
292
375
  try:
293
376
  try:
294
- res = ctypes.oledll.ole32.CoWaitForMultipleHandles(
295
- 0,
377
+ _CoWaitForMultipleHandles(
378
+ COWAIT_DEFAULT,
296
379
  int(timeout * 1000),
297
380
  len(handles),
298
381
  handles,
299
- ctypes.byref(ctypes.c_ulong()),
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
- ctypes.windll.kernel32.CloseHandle(hevt)
308
- ctypes.windll.kernel32.SetConsoleCtrlHandler(HandlerRoutine, 0)
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
- from comtypes.automation import IEnumVARIANT
5
- from comtypes.automation import DISPATCH_METHOD
6
- from comtypes.automation import DISPATCH_PROPERTYGET
7
- from comtypes.automation import DISPATCH_PROPERTYPUT
8
- from comtypes.automation import DISPATCH_PROPERTYPUTREF
9
-
10
- from comtypes.automation import DISPID_VALUE
11
- from comtypes.automation import DISPID_NEWENUM
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):