comtypes 1.4.10__zip → 1.4.12__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 (151) hide show
  1. {comtypes-1.4.10 → comtypes-1.4.12}/CHANGES.txt +48 -0
  2. {comtypes-1.4.10/comtypes.egg-info → comtypes-1.4.12}/PKG-INFO +4 -3
  3. {comtypes-1.4.10 → comtypes-1.4.12}/README.md +1 -1
  4. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/__init__.py +11 -5
  5. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/_comobject.py +29 -31
  6. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/_memberspec.py +107 -81
  7. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/_meta.py +1 -1
  8. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/_npsupport.py +12 -17
  9. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/_post_coinit/_cominterface_meta_patcher.py +8 -10
  10. comtypes-1.4.12/comtypes/_post_coinit/activeobj.py +61 -0
  11. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/_post_coinit/misc.py +1 -23
  12. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/_post_coinit/unknwn.py +33 -26
  13. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/_vtbl.py +55 -58
  14. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/automation.py +19 -23
  15. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/client/__init__.py +2 -1
  16. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/client/_activeobj.py +8 -0
  17. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/client/_code_cache.py +10 -24
  18. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/client/_constants.py +1 -1
  19. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/client/_events.py +92 -54
  20. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/client/_generate.py +1 -3
  21. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/client/dynamic.py +3 -3
  22. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/client/lazybind.py +3 -3
  23. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/connectionpoints.py +37 -3
  24. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/errorinfo.py +54 -16
  25. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/hints.pyi +15 -2
  26. comtypes-1.4.12/comtypes/hresult.py +159 -0
  27. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/messageloop.py +15 -13
  28. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/patcher.py +2 -2
  29. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/persist.py +9 -2
  30. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/safearray.py +10 -10
  31. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/server/__init__.py +5 -37
  32. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/server/automation.py +2 -2
  33. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/server/connectionpoints.py +71 -70
  34. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/server/inprocserver.py +10 -7
  35. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/server/localserver.py +16 -22
  36. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/server/register.py +7 -7
  37. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_GUID.py +6 -7
  38. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_agilent.py +1 -1
  39. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_basic.py +6 -3
  40. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_client_dynamic.py +1 -1
  41. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_collections.py +6 -3
  42. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_comobject.py +19 -6
  43. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_comserver.py +32 -4
  44. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_createwrappers.py +1 -1
  45. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_dict.py +2 -1
  46. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_dispifc_records.py +0 -2
  47. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_dispifc_safearrays.py +0 -2
  48. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_dispinterface.py +1 -1
  49. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_dyndispatch.py +4 -2
  50. comtypes-1.4.12/comtypes/test/test_errorinfo.py +115 -0
  51. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_excel.py +1 -3
  52. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_getactiveobj.py +19 -2
  53. comtypes-1.4.12/comtypes/test/test_hresult.py +87 -0
  54. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_inout_args.py +9 -2
  55. comtypes-1.4.12/comtypes/test/test_messageloop.py +117 -0
  56. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_midl_safearray_create.py +0 -2
  57. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_msscript.py +1 -1
  58. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_npsupport.py +22 -11
  59. comtypes-1.4.12/comtypes/test/test_persist.py +71 -0
  60. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_recordinfo.py +0 -2
  61. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_safearray.py +2 -1
  62. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_server.py +6 -6
  63. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_server_register.py +2 -1
  64. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_storage.py +1 -1
  65. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_stream.py +22 -2
  66. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_typeinfo.py +19 -2
  67. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_urlhistory.py +1 -1
  68. comtypes-1.4.12/comtypes/test/test_util.py +227 -0
  69. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_variant.py +43 -25
  70. comtypes-1.4.12/comtypes/test/test_viewobject.py +78 -0
  71. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_w_getopt.py +4 -4
  72. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_word.py +1 -1
  73. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/tools/codegenerator/codegenerator.py +1 -1
  74. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/tools/codegenerator/comments.py +1 -1
  75. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/tools/codegenerator/heads.py +5 -5
  76. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/tools/codegenerator/helpers.py +7 -7
  77. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/tools/codegenerator/namespaces.py +3 -3
  78. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/tools/codegenerator/typeannotator.py +2 -2
  79. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/tools/tlbparser.py +8 -7
  80. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/tools/typedesc.py +14 -14
  81. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/tools/typedesc_base.py +19 -19
  82. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/typeinfo.py +14 -9
  83. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/util.py +38 -6
  84. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/viewobject.py +29 -5
  85. {comtypes-1.4.10 → comtypes-1.4.12/comtypes.egg-info}/PKG-INFO +4 -3
  86. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes.egg-info/SOURCES.txt +6 -0
  87. {comtypes-1.4.10 → comtypes-1.4.12}/pyproject.toml +13 -7
  88. comtypes-1.4.10/comtypes/hresult.py +0 -81
  89. comtypes-1.4.10/comtypes/test/test_persist.py +0 -38
  90. {comtypes-1.4.10 → comtypes-1.4.12}/LICENSE.txt +0 -0
  91. {comtypes-1.4.10 → comtypes-1.4.12}/MANIFEST.in +0 -0
  92. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/GUID.py +0 -0
  93. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/_post_coinit/__init__.py +0 -0
  94. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/_post_coinit/bstr.py +0 -0
  95. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/_post_coinit/instancemethod.py +0 -0
  96. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/_safearray.py +0 -0
  97. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/_tlib_version_checker.py +0 -0
  98. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/clear_cache.py +0 -0
  99. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/client/_create.py +0 -0
  100. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/client/_managing.py +0 -0
  101. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/git.py +0 -0
  102. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/logutil.py +0 -0
  103. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/server/w_getopt.py +0 -0
  104. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/shelllink.py +0 -0
  105. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/stream.py +0 -0
  106. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/TestComServer.idl +0 -0
  107. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/TestComServer.py +0 -0
  108. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/TestComServer.tlb +0 -0
  109. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/TestDispServer.idl +0 -0
  110. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/TestDispServer.py +0 -0
  111. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/TestDispServer.tlb +0 -0
  112. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/__init__.py +0 -0
  113. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/find_memleak.py +0 -0
  114. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/mylib.idl +0 -0
  115. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/mylib.tlb +0 -0
  116. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/mytypelib.idl +0 -0
  117. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/runtests.py +0 -0
  118. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/setup.py +0 -0
  119. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_BSTR.py +0 -0
  120. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_DISPPARAMS.py +0 -0
  121. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_QueryService.py +0 -0
  122. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_avmc.py +0 -0
  123. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_casesensitivity.py +0 -0
  124. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_clear_cache.py +0 -0
  125. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_client.py +0 -0
  126. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_client_regenerate_modules.py +0 -0
  127. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_findgendir.py +0 -0
  128. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_ie.py +0 -0
  129. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_ienum.py +0 -0
  130. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_imfattributes.py +0 -0
  131. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_jscript.js +0 -0
  132. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_monikers.py +0 -0
  133. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_outparam.py +0 -0
  134. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_pump_events.py +0 -0
  135. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_sapi.py +0 -0
  136. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_shelllink.py +0 -0
  137. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_showevents.py +0 -0
  138. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_subinterface.py +0 -0
  139. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_typeannotator.py +0 -0
  140. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_win32com_interop.py +0 -0
  141. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_wmi.py +0 -0
  142. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/urlhist.tlb +0 -0
  143. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/tools/__init__.py +0 -0
  144. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/tools/codegenerator/__init__.py +0 -0
  145. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/tools/codegenerator/modulenamer.py +0 -0
  146. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/tools/codegenerator/packing.py +0 -0
  147. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes.egg-info/dependency_links.txt +0 -0
  148. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes.egg-info/entry_points.txt +0 -0
  149. {comtypes-1.4.10 → comtypes-1.4.12}/comtypes.egg-info/top_level.txt +0 -0
  150. {comtypes-1.4.10 → comtypes-1.4.12}/setup.cfg +0 -0
  151. {comtypes-1.4.10 → comtypes-1.4.12}/setup.py +0 -0
@@ -1,7 +1,8 @@
1
1
  import ctypes
2
2
  import logging
3
3
  import traceback
4
- from ctypes import HRESULT, POINTER, WINFUNCTYPE, OleDLL, Structure, WinDLL
4
+ from _ctypes import COMError
5
+ from ctypes import HRESULT, POINTER, WINFUNCTYPE, OleDLL, Structure, WinDLL, byref
5
6
  from ctypes.wintypes import (
6
7
  BOOL,
7
8
  DWORD,
@@ -12,13 +13,16 @@ from ctypes.wintypes import (
12
13
  LPVOID,
13
14
  ULONG,
14
15
  )
16
+ from typing import Any, Callable, Optional, Type
17
+ from typing import Union as _UnionT
15
18
 
16
19
  import comtypes
17
- import comtypes.automation
18
- import comtypes.connectionpoints
19
- import comtypes.hresult
20
- import comtypes.typeinfo
20
+ from comtypes import COMObject, IUnknown, hresult
21
+ from comtypes._comobject import _MethodFinder
22
+ from comtypes.automation import DISPATCH_METHOD, IDispatch
21
23
  from comtypes.client._generate import GetModule
24
+ from comtypes.connectionpoints import IConnectionPoint, IConnectionPointContainer
25
+ from comtypes.typeinfo import GUIDKIND_DEFAULT_SOURCE_DISP_IID, IProvideClassInfo2
22
26
 
23
27
  logger = logging.getLogger(__name__)
24
28
 
@@ -57,46 +61,62 @@ _CloseHandle = _kernel32.CloseHandle
57
61
  _CloseHandle.argtypes = [HANDLE]
58
62
  _CloseHandle.restype = BOOL
59
63
 
64
+ _ReceiverType = _UnionT[COMObject, IUnknown]
65
+
66
+
67
+ class _AdviseConnection:
68
+ cp: Optional[IConnectionPoint]
69
+ cookie: Optional[int]
70
+ receiver: Optional[_ReceiverType]
60
71
 
61
- class _AdviseConnection(object):
62
- def __init__(self, source, interface, receiver):
72
+ def __init__(
73
+ self, source: IUnknown, interface: Type[IUnknown], receiver: _ReceiverType
74
+ ) -> None:
75
+ # Pre-initializing attributes to avoid AttributeError after failed connection.
63
76
  self.cp = None
64
77
  self.cookie = None
65
78
  self.receiver = None
66
79
  self._connect(source, interface, receiver)
67
80
 
68
- def _connect(self, source, interface, receiver):
69
- cpc = source.QueryInterface(comtypes.connectionpoints.IConnectionPointContainer)
70
- 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_))
71
86
  logger.debug("Start advise %s", interface)
72
- 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
73
91
  self.receiver = receiver
74
92
 
75
- def disconnect(self):
93
+ def disconnect(self) -> None:
76
94
  if self.cookie:
95
+ assert self.cp is not None
77
96
  self.cp.Unadvise(self.cookie)
78
97
  logger.debug("Unadvised %s", self.cp)
79
98
  self.cp = None
80
99
  self.cookie = None
81
100
  del self.receiver
82
101
 
83
- def __del__(self):
102
+ def __del__(self) -> None:
84
103
  try:
85
104
  if self.cookie is not None:
105
+ assert self.cp is not None
86
106
  self.cp.Unadvise(self.cookie)
87
- except (comtypes.COMError, WindowsError):
107
+ except (OSError, COMError):
88
108
  # Are we sure we want to ignore errors here?
89
109
  pass
90
110
 
91
111
 
92
- def FindOutgoingInterface(source):
112
+ def FindOutgoingInterface(source: IUnknown) -> Type[IUnknown]:
93
113
  """XXX Describe the strategy that is used..."""
94
114
  # If the COM object implements IProvideClassInfo2, it is easy to
95
115
  # find the default outgoing interface.
96
116
  try:
97
- pci = source.QueryInterface(comtypes.typeinfo.IProvideClassInfo2)
98
- guid = pci.GetGUID(1)
99
- except comtypes.COMError:
117
+ pci = source.QueryInterface(IProvideClassInfo2)
118
+ guid = pci.GetGUID(GUIDKIND_DEFAULT_SOURCE_DISP_IID)
119
+ except COMError:
100
120
  pass
101
121
  else:
102
122
  # another try: block needed?
@@ -115,7 +135,7 @@ def FindOutgoingInterface(source):
115
135
  # comtypes.client):
116
136
  clsid = source.__dict__.get("__clsid")
117
137
  try:
118
- interface = comtypes.com_coclass_registry[clsid]._outgoing_interfaces_[0]
138
+ interface = comtypes.com_coclass_registry[clsid]._outgoing_interfaces_[0] # type: ignore
119
139
  except KeyError:
120
140
  pass
121
141
  else:
@@ -133,7 +153,7 @@ def find_single_connection_interface(source):
133
153
  # Enumerate the connection interfaces. If we find a single one,
134
154
  # return it, if there are more, we give up since we cannot
135
155
  # determine which one to use.
136
- cpc = source.QueryInterface(comtypes.connectionpoints.IConnectionPointContainer)
156
+ cpc = source.QueryInterface(IConnectionPointContainer)
137
157
  enum = cpc.EnumConnectionPoints()
138
158
  iid = enum.next().GetConnectionInterface()
139
159
  try:
@@ -152,32 +172,33 @@ def find_single_connection_interface(source):
152
172
  return None
153
173
 
154
174
 
155
- def report_errors(func):
175
+ def report_errors(func: Callable[..., Any]) -> Callable[..., Any]:
156
176
  # This decorator preserves parts of the decorated function
157
177
  # signature, so that the comtypes special-casing for the 'this'
158
178
  # parameter still works.
159
179
  if func.__code__.co_varnames[:2] == ("self", "this"):
160
180
 
161
- def error_printer(self, this, *args, **kw):
181
+ def with_this(self, this, *args, **kw):
162
182
  try:
163
183
  return func(self, this, *args, **kw)
164
184
  except:
165
185
  traceback.print_exc()
166
186
  raise
167
187
 
188
+ error_printer = with_this
189
+
168
190
  else:
169
191
 
170
- def error_printer(*args, **kw):
192
+ def without_this(*args, **kw):
171
193
  try:
172
194
  return func(*args, **kw)
173
195
  except:
174
196
  traceback.print_exc()
175
197
  raise
176
198
 
177
- return error_printer
178
-
199
+ error_printer = without_this
179
200
 
180
- from comtypes._comobject import _MethodFinder
201
+ return error_printer
181
202
 
182
203
 
183
204
  class _SinkMethodFinder(_MethodFinder):
@@ -187,11 +208,11 @@ class _SinkMethodFinder(_MethodFinder):
187
208
  event handlers.
188
209
  """
189
210
 
190
- def __init__(self, inst, sink):
191
- super(_SinkMethodFinder, self).__init__(inst)
211
+ def __init__(self, inst: COMObject, sink: Any) -> None:
212
+ super().__init__(inst)
192
213
  self.sink = sink
193
214
 
194
- def find_method(self, fq_name, mthname):
215
+ def find_method(self, fq_name: str, mthname: str) -> Callable[..., Any]:
195
216
  impl = self._find_method(fq_name, mthname)
196
217
  # Caller of this method catches AttributeError,
197
218
  # so we need to be careful in the following code
@@ -206,9 +227,9 @@ class _SinkMethodFinder(_MethodFinder):
206
227
  except AttributeError as details:
207
228
  raise RuntimeError(details)
208
229
 
209
- def _find_method(self, fq_name, mthname):
230
+ def _find_method(self, fq_name: str, mthname: str) -> Callable[..., Any]:
210
231
  try:
211
- return super(_SinkMethodFinder, self).find_method(fq_name, mthname)
232
+ return super().find_method(fq_name, mthname)
212
233
  except AttributeError:
213
234
  try:
214
235
  return getattr(self.sink, fq_name)
@@ -216,11 +237,11 @@ class _SinkMethodFinder(_MethodFinder):
216
237
  return getattr(self.sink, mthname)
217
238
 
218
239
 
219
- def CreateEventReceiver(interface, handler):
220
- class Sink(comtypes.COMObject):
240
+ def CreateEventReceiver(interface: Type[IUnknown], handler: Any) -> COMObject:
241
+ class Sink(COMObject):
221
242
  _com_interfaces_ = [interface]
222
243
 
223
- def _get_method_finder_(self, itf):
244
+ def _get_method_finder_(self, itf: Type[IUnknown]) -> _MethodFinder:
224
245
  # Use a special MethodFinder that will first try 'self',
225
246
  # then the sink.
226
247
  return _SinkMethodFinder(self, handler)
@@ -229,25 +250,25 @@ def CreateEventReceiver(interface, handler):
229
250
 
230
251
  # Since our Sink object doesn't have typeinfo, it needs a
231
252
  # _dispimpl_ dictionary to dispatch events received via Invoke.
232
- if issubclass(interface, comtypes.automation.IDispatch) and not hasattr(
233
- sink, "_dispimpl_"
234
- ):
253
+ if issubclass(interface, IDispatch) and not hasattr(sink, "_dispimpl_"):
235
254
  finder = sink._get_method_finder_(interface)
236
255
  dispimpl = sink._dispimpl_ = {}
237
256
  for m in interface._methods_:
238
- restype, mthname, argtypes, paramflags, idlflags, helptext = m
239
257
  # Can dispid be at a different index? Should check code generator...
240
258
  # ...but hand-written code should also work...
241
- dispid = idlflags[0]
242
- 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)
243
262
  # XXX Wouldn't work for 'propget', 'propput', 'propputref'
244
263
  # methods - are they allowed on event interfaces?
245
- dispimpl[(dispid, comtypes.automation.DISPATCH_METHOD)] = impl
264
+ dispimpl[(dispid, DISPATCH_METHOD)] = impl
246
265
 
247
266
  return sink
248
267
 
249
268
 
250
- def GetEvents(source, sink, interface=None):
269
+ def GetEvents(
270
+ source: IUnknown, sink: Any, interface: Optional[Type[IUnknown]] = None
271
+ ) -> _AdviseConnection:
251
272
  """Receive COM events from 'source'. Events will call methods on
252
273
  the 'sink' object. 'interface' is the source interface to use.
253
274
  """
@@ -262,10 +283,10 @@ def GetEvents(source, sink, interface=None):
262
283
  return _AdviseConnection(source, interface, rcv)
263
284
 
264
285
 
265
- class EventDumper(object):
286
+ class EventDumper:
266
287
  """Universal sink for COM events."""
267
288
 
268
- def __getattr__(self, name):
289
+ def __getattr__(self, name: str) -> Callable[..., Any]:
269
290
  "Create event handler methods on demand"
270
291
  if name.startswith("__") and name.endswith("__"):
271
292
  raise AttributeError(name)
@@ -279,13 +300,15 @@ class EventDumper(object):
279
300
  return comtypes.instancemethod(handler, self, EventDumper)
280
301
 
281
302
 
282
- def ShowEvents(source, interface=None):
303
+ def ShowEvents(
304
+ source: IUnknown, interface: Optional[Type[IUnknown]] = None
305
+ ) -> _AdviseConnection:
283
306
  """Receive COM events from 'source'. A special event sink will be
284
307
  used that first prints the names of events that are found in the
285
308
  outgoing interface, and will also print out the events when they
286
309
  are fired.
287
310
  """
288
- return comtypes.client.GetEvents(source, sink=EventDumper(), interface=interface)
311
+ return GetEvents(source, sink=EventDumper(), interface=interface)
289
312
 
290
313
 
291
314
  # This type is used inside 'PumpEvents', but if we create the type
@@ -293,8 +316,24 @@ def ShowEvents(source, interface=None):
293
316
  # garbage for each call. So we define it here instead.
294
317
  _handles_type = ctypes.c_void_p * 1
295
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
325
+
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
+
296
335
 
297
- def PumpEvents(timeout):
336
+ def PumpEvents(timeout: Any) -> None:
298
337
  """This following code waits for 'timeout' seconds in the way
299
338
  required for COM, internally doing the correct things depending
300
339
  on the COM appartment of the current thread. It is possible to
@@ -323,11 +362,10 @@ def PumpEvents(timeout):
323
362
 
324
363
  hevt = _CreateEventA(None, True, False, None)
325
364
  handles = _handles_type(hevt)
326
- RPC_S_CALLPENDING = -2147417835
327
365
 
328
366
  # @ctypes.WINFUNCTYPE(BOOL, DWORD)
329
367
  def HandlerRoutine(dwCtrlType):
330
- if dwCtrlType == 0: # CTRL+C
368
+ if dwCtrlType == CTRL_C_EVENT: # CTRL+C
331
369
  _SetEvent(hevt)
332
370
  return 1
333
371
  return 0
@@ -336,15 +374,15 @@ def PumpEvents(timeout):
336
374
 
337
375
  try:
338
376
  try:
339
- res = _CoWaitForMultipleHandles(
340
- 0,
377
+ _CoWaitForMultipleHandles(
378
+ COWAIT_DEFAULT,
341
379
  int(timeout * 1000),
342
380
  len(handles),
343
381
  handles,
344
- ctypes.byref(ctypes.c_ulong()),
382
+ byref(ctypes.c_ulong()),
345
383
  )
346
- except WindowsError as details:
347
- if details.winerror != RPC_S_CALLPENDING: # timeout expired
384
+ except OSError as details:
385
+ if details.winerror != hresult.RPC_S_CALLPENDING: # timeout expired
348
386
  raise
349
387
  else:
350
388
  raise KeyboardInterrupt
@@ -15,8 +15,6 @@ from comtypes.tools import codegenerator, tlbparser
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"""
@@ -213,7 +211,7 @@ def _create_module(modulename: str, code: str) -> types.ModuleType:
213
211
  return _my_import(modulename)
214
212
 
215
213
 
216
- class ModuleGenerator(object):
214
+ class ModuleGenerator:
217
215
  def __init__(self, tlib: typeinfo.ITypeLib, pathname: Optional[str]) -> None:
218
216
  self.wrapper_name = codegenerator.name_wrapper_module(tlib)
219
217
  self.friendly_name = codegenerator.name_friendly_module(tlib)
@@ -27,7 +27,7 @@ def Dispatch(obj):
27
27
  if isinstance(obj, ctypes.POINTER(automation.IDispatch)):
28
28
  try:
29
29
  tinfo = obj.GetTypeInfo(0)
30
- except (COMError, WindowsError):
30
+ except (OSError, COMError):
31
31
  return _Dispatch(obj)
32
32
  return lazybind.Dispatch(obj, tinfo)
33
33
  return obj
@@ -59,7 +59,7 @@ class MethodCaller:
59
59
  )
60
60
 
61
61
 
62
- class _Dispatch(object):
62
+ class _Dispatch:
63
63
  """Expose methods and properties via fully dynamic dispatch."""
64
64
 
65
65
  _comobj: automation.IDispatch
@@ -160,7 +160,7 @@ class _Dispatch(object):
160
160
  # )
161
161
 
162
162
 
163
- class _Collection(object):
163
+ class _Collection:
164
164
  def __init__(self, enum: automation.IEnumVARIANT):
165
165
  self.enum = enum
166
166
 
@@ -12,7 +12,7 @@ from comtypes.automation import (
12
12
  from comtypes.typeinfo import FUNC_DISPATCH, FUNC_PUREVIRTUAL
13
13
 
14
14
 
15
- class FuncDesc(object):
15
+ class FuncDesc:
16
16
  """Stores important FUNCDESC properties by copying them from a
17
17
  real FUNCDESC instance.
18
18
  """
@@ -28,7 +28,7 @@ class FuncDesc(object):
28
28
  _all_slice = slice(None, None, None)
29
29
 
30
30
 
31
- class NamedProperty(object):
31
+ class NamedProperty:
32
32
  def __init__(self, disp, get, put, putref):
33
33
  self.get = get
34
34
  self.put = put
@@ -83,7 +83,7 @@ class NamedProperty(object):
83
83
  # objects do not (could be added, would probably be expensive)
84
84
 
85
85
 
86
- class Dispatch(object):
86
+ class Dispatch:
87
87
  """Dynamic dispatch for an object the exposes type information.
88
88
  Binding at runtime is done via ITypeComp::Bind calls.
89
89
  """
@@ -1,7 +1,15 @@
1
- import sys
2
- from ctypes import *
1
+ from ctypes import POINTER, Structure, c_ulong
2
+ from typing import TYPE_CHECKING, Tuple
3
+ from typing import Union as _UnionT
3
4
 
4
- from comtypes import COMMETHOD, GUID, HRESULT, IUnknown, dispid
5
+ from comtypes import COMMETHOD, GUID, HRESULT, IUnknown
6
+
7
+ if TYPE_CHECKING:
8
+ from ctypes import _CArgObject, _Pointer
9
+
10
+ from comtypes import hints # noqa # type: ignore
11
+
12
+ REFIID = _UnionT[_Pointer[GUID], _CArgObject]
5
13
 
6
14
  _GUID = GUID
7
15
 
@@ -22,16 +30,35 @@ class IConnectionPointContainer(IUnknown):
22
30
  _iid_ = GUID("{B196B284-BAB4-101A-B69C-00AA00341D07}")
23
31
  _idlflags_ = []
24
32
 
33
+ if TYPE_CHECKING:
34
+
35
+ def EnumConnectionPoints(self) -> "IEnumConnectionPoints": ...
36
+ def FindConnectionPoint(self, riid: REFIID) -> "IConnectionPoint": ...
37
+
25
38
 
26
39
  class IConnectionPoint(IUnknown):
27
40
  _iid_ = GUID("{B196B286-BAB4-101A-B69C-00AA00341D07}")
28
41
  _idlflags_ = []
29
42
 
43
+ if TYPE_CHECKING:
44
+
45
+ def GetConnectionPointContainer(self) -> IConnectionPointContainer: ...
46
+ def Advise(self, pUnkSink: IUnknown) -> int: ...
47
+ def Unadvise(self, dwCookie: int) -> hints.Hresult: ...
48
+ def EnumConnections(self) -> "IEnumConnections": ...
49
+
30
50
 
31
51
  class IEnumConnections(IUnknown):
32
52
  _iid_ = GUID("{B196B287-BAB4-101A-B69C-00AA00341D07}")
33
53
  _idlflags_ = []
34
54
 
55
+ if TYPE_CHECKING:
56
+
57
+ def Next(self, cConnections: int) -> Tuple[tagCONNECTDATA, int]: ...
58
+ def Skip(self, cConnections: int) -> hints.Hresult: ...
59
+ def Reset(self) -> hints.Hresult: ...
60
+ def Clone(self) -> "IEnumConnections": ...
61
+
35
62
  def __iter__(self):
36
63
  return self
37
64
 
@@ -46,6 +73,13 @@ class IEnumConnectionPoints(IUnknown):
46
73
  _iid_ = GUID("{B196B285-BAB4-101A-B69C-00AA00341D07}")
47
74
  _idlflags_ = []
48
75
 
76
+ if TYPE_CHECKING:
77
+
78
+ def Next(self, cConnections: int) -> Tuple[IConnectionPoint, int]: ...
79
+ def Skip(self, cConnections: int) -> hints.Hresult: ...
80
+ def Reset(self) -> hints.Hresult: ...
81
+ def Clone(self) -> "IEnumConnectionPoints": ...
82
+
49
83
  def __iter__(self):
50
84
  return self
51
85
 
@@ -1,9 +1,14 @@
1
1
  import sys
2
- from ctypes import *
2
+ from ctypes import POINTER, OleDLL, byref, c_wchar_p
3
3
  from ctypes.wintypes import DWORD, ULONG
4
+ from typing import TYPE_CHECKING, Optional
5
+ from typing import Union as _UnionT
4
6
 
5
7
  from comtypes import BSTR, COMMETHOD, GUID, HRESULT, IUnknown
6
- from comtypes.hresult import *
8
+ from comtypes.hresult import DISP_E_EXCEPTION, S_OK
9
+
10
+ if TYPE_CHECKING:
11
+ from comtypes import hints # type: ignore
7
12
 
8
13
  LPCOLESTR = c_wchar_p
9
14
 
@@ -17,6 +22,13 @@ class ICreateErrorInfo(IUnknown):
17
22
  COMMETHOD([], HRESULT, "SetHelpFile", (["in"], LPCOLESTR, "szHelpFile")),
18
23
  COMMETHOD([], HRESULT, "SetHelpContext", (["in"], DWORD, "dwHelpContext")),
19
24
  ]
25
+ if TYPE_CHECKING:
26
+
27
+ def SetGUID(self, rguid: GUID) -> hints.Hresult: ...
28
+ def SetSource(self, szSource: str) -> hints.Hresult: ...
29
+ def SetDescription(self, szDescription: str) -> hints.Hresult: ...
30
+ def SetHelpFile(self, szHelpFile: str) -> hints.Hresult: ...
31
+ def SetHelpContext(self, dwHelpContext: int) -> hints.Hresult: ...
20
32
 
21
33
 
22
34
  class IErrorInfo(IUnknown):
@@ -34,6 +46,13 @@ class IErrorInfo(IUnknown):
34
46
  [], HRESULT, "GetHelpContext", (["out"], POINTER(DWORD), "pdwHelpContext")
35
47
  ),
36
48
  ]
49
+ if TYPE_CHECKING:
50
+
51
+ def GetGUID(self) -> GUID: ...
52
+ def GetSource(self) -> str: ...
53
+ def GetDescription(self) -> str: ...
54
+ def GetHelpFile(self) -> str: ...
55
+ def GetHelpContext(self) -> int: ...
37
56
 
38
57
 
39
58
  class ISupportErrorInfo(IUnknown):
@@ -43,6 +62,9 @@ class ISupportErrorInfo(IUnknown):
43
62
  [], HRESULT, "InterfaceSupportsErrorInfo", (["in"], POINTER(GUID), "riid")
44
63
  )
45
64
  ]
65
+ if TYPE_CHECKING:
66
+
67
+ def InterfaceSupportsErrorInfo(self, riid: GUID) -> hints.Hresult: ...
46
68
 
47
69
 
48
70
  ################################################################
@@ -61,28 +83,36 @@ _SetErrorInfo.argtypes = [ULONG, POINTER(IErrorInfo)]
61
83
  _SetErrorInfo.restype = HRESULT
62
84
 
63
85
 
64
- def CreateErrorInfo():
86
+ def CreateErrorInfo() -> ICreateErrorInfo:
87
+ """Creates an instance of a generic error object."""
65
88
  cei = POINTER(ICreateErrorInfo)()
66
89
  _CreateErrorInfo(byref(cei))
67
- return cei
90
+ return cei # type: ignore
68
91
 
69
92
 
70
- def GetErrorInfo():
93
+ def GetErrorInfo() -> Optional[IErrorInfo]:
71
94
  """Get the error information for the current thread."""
72
95
  errinfo = POINTER(IErrorInfo)()
73
96
  if S_OK == _GetErrorInfo(0, byref(errinfo)):
74
- return errinfo
97
+ return errinfo # type: ignore
75
98
  return None
76
99
 
77
100
 
78
- def SetErrorInfo(errinfo):
101
+ def SetErrorInfo(errinfo: _UnionT[IErrorInfo, ICreateErrorInfo]) -> "hints.Hresult":
79
102
  """Set error information for the current thread."""
103
+ # ICreateErrorInfo can QueryInterface with IErrorInfo, so both types are
104
+ # accepted, thanks to the magic of from_param.
80
105
  return _SetErrorInfo(0, errinfo)
81
106
 
82
107
 
83
108
  def ReportError(
84
- text, iid, clsid=None, helpfile=None, helpcontext=0, hresult=DISP_E_EXCEPTION
85
- ):
109
+ text: str,
110
+ iid: GUID,
111
+ clsid: _UnionT[None, str, GUID] = None,
112
+ helpfile: Optional[str] = None,
113
+ helpcontext: Optional[int] = 0,
114
+ hresult: int = DISP_E_EXCEPTION,
115
+ ) -> int:
86
116
  """Report a COM error. Returns the passed in hresult value."""
87
117
  ei = CreateErrorInfo()
88
118
  ei.SetDescription(text)
@@ -96,24 +126,32 @@ def ReportError(
96
126
  clsid = GUID(clsid)
97
127
  try:
98
128
  progid = clsid.as_progid()
99
- except WindowsError:
129
+ except OSError:
100
130
  pass
101
131
  else:
102
- ei.SetSource(
103
- progid
104
- ) # progid for the class or application that created the error
105
- _SetErrorInfo(0, ei)
132
+ # progid for the class or application that created the error
133
+ ei.SetSource(progid)
134
+ SetErrorInfo(ei)
106
135
  return hresult
107
136
 
108
137
 
109
138
  def ReportException(
110
- hresult, iid, clsid=None, helpfile=None, helpcontext=None, stacklevel=None
111
- ):
139
+ hresult: int,
140
+ iid: GUID,
141
+ clsid: _UnionT[None, str, GUID] = None,
142
+ helpfile: Optional[str] = None,
143
+ helpcontext: Optional[int] = None,
144
+ stacklevel: Optional[int] = None,
145
+ ) -> int:
112
146
  """Report a COM exception. Returns the passed in hresult value."""
113
147
  typ, value, tb = sys.exc_info()
114
148
  if stacklevel is not None:
115
149
  for _ in range(stacklevel):
150
+ if tb is None:
151
+ raise ValueError("'stacklevel' exceeds the available depth.")
116
152
  tb = tb.tb_next
153
+ if tb is None:
154
+ raise ValueError("'stacklevel' is specified, but no error information.")
117
155
  line = tb.tb_frame.f_lineno
118
156
  name = tb.tb_frame.f_globals["__name__"]
119
157
  text = f"{typ}: {value} ({name}, line {line:d})"
@@ -3,9 +3,10 @@
3
3
  # - utilities for type hints.
4
4
  import ctypes
5
5
  import sys
6
+ from ctypes import _CData, _CDataType
6
7
  from typing import Any as Any, ClassVar, Generic, NoReturn, Protocol, TypeVar, overload
7
8
  from typing import Optional, Union as _UnionT
8
- from typing import Tuple as Tuple, Type
9
+ from typing import List, Tuple as Tuple, Type
9
10
  from typing import Callable, Iterator, Sequence
10
11
 
11
12
  if sys.version_info >= (3, 9):
@@ -20,8 +21,10 @@ else:
20
21
  from typing_extensions import TypeGuard as TypeGuard
21
22
  if sys.version_info >= (3, 11):
22
23
  from typing import Self as Self
24
+ from typing import Unpack as Unpack
23
25
  else:
24
26
  from typing_extensions import Self as Self
27
+ from typing_extensions import Unpack as Unpack
25
28
 
26
29
  import comtypes
27
30
  from comtypes import IUnknown as IUnknown, COMObject as COMObject, GUID as GUID
@@ -41,7 +44,10 @@ Hresult: TypeAlias = int
41
44
  arguments and with `HRESULT` as its return type in its COM method definition.
42
45
  """
43
46
 
44
- _CT = TypeVar("_CT", bound=ctypes._CData)
47
+ LP_LP_Vtbl: TypeAlias = ctypes._Pointer[ctypes._Pointer[ctypes.Structure]]
48
+ """A pointer to a pointer to a virtual function table."""
49
+
50
+ _CT = TypeVar("_CT", bound=_CData)
45
51
  _T_IUnknown = TypeVar("_T_IUnknown", bound=IUnknown)
46
52
  _T_Struct = TypeVar("_T_Struct", bound=ctypes.Structure)
47
53
 
@@ -285,3 +291,10 @@ def to_dunder_setitem(
285
291
  ) -> Callable[Concatenate[_T_Inst, _P_Set], Any]: ...
286
292
  @overload
287
293
  def to_dunder_setitem(item: Any) -> Callable[..., NoReturn]: ...
294
+
295
+ _PosParamFlagType: TypeAlias = Tuple[int, Optional[str]]
296
+ _OptParamFlagType: TypeAlias = Tuple[int, Optional[str], Any]
297
+ ParamFlagType: TypeAlias = _UnionT[_PosParamFlagType, _OptParamFlagType]
298
+ _PosArgSpecElmType: TypeAlias = Tuple[List[str], Type[_CDataType], str]
299
+ _OptArgSpecElmType: TypeAlias = Tuple[List[str], Type[_CDataType], str, Any]
300
+ ArgSpecElmType: TypeAlias = _UnionT[_PosArgSpecElmType, _OptArgSpecElmType]