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
@@ -1,28 +1,29 @@
1
1
  # https://learn.microsoft.com/en-us/windows/win32/api/unknwn/
2
2
 
3
3
  import logging
4
- import sys
5
4
  from ctypes import HRESULT, POINTER, byref, c_ulong, c_void_p
6
- from typing import TYPE_CHECKING, ClassVar, List, Optional, Type, TypeVar
5
+ from typing import TYPE_CHECKING, Any, ClassVar, List, Optional, Type, TypeVar
7
6
 
8
- from comtypes import GUID, _ole32_nohresult, com_interface_registry
7
+ import comtypes
8
+ from comtypes import GUID, _CoUninitialize
9
9
  from comtypes._memberspec import STDMETHOD, ComMemberGenerator, DispMemberGenerator
10
10
  from comtypes._post_coinit import _cominterface_meta_patcher as _meta_patch
11
11
  from comtypes._post_coinit.instancemethod import instancemethod
12
12
 
13
13
  if TYPE_CHECKING:
14
+ from typing import Literal
15
+ from typing import Union as _UnionT
16
+
17
+ from comtypes import hints # type: ignore
14
18
  from comtypes._memberspec import _ComMemberSpec, _DispMemberSpec
15
19
 
16
20
  logger = logging.getLogger(__name__)
17
21
 
18
22
 
19
23
  def _shutdown(
20
- func=_ole32_nohresult.CoUninitialize,
24
+ func=_CoUninitialize,
21
25
  _debug=logger.debug,
22
- _exc_clear=getattr(sys, "exc_clear", lambda: None),
23
- ):
24
- # Make sure no COM pointers stay in exception frames.
25
- _exc_clear()
26
+ ) -> None:
26
27
  # Sometimes, CoUninitialize, running at Python shutdown,
27
28
  # raises an exception. We suppress this when __debug__ is
28
29
  # False.
@@ -135,7 +136,7 @@ class _cominterface_meta(type):
135
136
 
136
137
  return self
137
138
 
138
- def __setattr__(self, name, value):
139
+ def __setattr__(self, name: str, value: Any) -> None:
139
140
  if name == "_methods_":
140
141
  # XXX I'm no longer sure why the code generator generates
141
142
  # "_methods_ = []" in the interface definition, and later
@@ -149,11 +150,11 @@ class _cominterface_meta(type):
149
150
  self._make_specials()
150
151
  type.__setattr__(self, name, value)
151
152
 
152
- def _make_specials(self):
153
+ def _make_specials(self) -> None:
153
154
  # This call installs methods that forward the Python protocols
154
155
  # to COM protocols.
155
156
 
156
- def has_name(name):
157
+ def has_name(name: str) -> bool:
157
158
  # Determine whether a property or method named 'name'
158
159
  # exists
159
160
  if self._case_insensitive_:
@@ -168,7 +169,7 @@ class _cominterface_meta(type):
168
169
  if has_name("_NewEnum"):
169
170
  _meta_patch.iterator(self)
170
171
 
171
- def _make_case_insensitive(self):
172
+ def _make_case_insensitive(self) -> None:
172
173
  # The __map_case__ dictionary maps lower case names to the
173
174
  # names in the original spelling to enable case insensitive
174
175
  # method and attribute access.
@@ -201,7 +202,7 @@ class _cominterface_meta(type):
201
202
  if self._case_insensitive_:
202
203
  self.__map_case__[name.lower()] = name
203
204
 
204
- def __get_baseinterface_methodcount(self):
205
+ def __get_baseinterface_methodcount(self) -> int:
205
206
  "Return the number of com methods in the base interfaces"
206
207
  result = 0
207
208
  for itf in self.mro()[1:-1]:
@@ -220,7 +221,7 @@ class _cominterface_meta(type):
220
221
  except KeyError:
221
222
  raise AttributeError("this class must define an _iid_")
222
223
  else:
223
- com_interface_registry[str(iid)] = self
224
+ comtypes.com_interface_registry[str(iid)] = self # type: ignore
224
225
  # create members
225
226
  vtbl_offset = self.__get_baseinterface_methodcount()
226
227
  member_gen = ComMemberGenerator(self.__name__, vtbl_offset, self._iid_)
@@ -265,7 +266,10 @@ class _compointer_meta(type(c_void_p), _cominterface_meta):
265
266
  class _compointer_base(c_void_p, metaclass=_compointer_meta):
266
267
  "base class for COM interface pointer classes"
267
268
 
268
- def __del__(self, _debug=logger.debug):
269
+ if TYPE_CHECKING:
270
+ __com_interface__: ClassVar[Type["IUnknown"]]
271
+
272
+ def __del__(self, _debug=logger.debug) -> None:
269
273
  "Release the COM refcount we own."
270
274
  if self:
271
275
  # comtypes calls CoUninitialize() when the atexit handlers
@@ -279,7 +283,7 @@ class _compointer_base(c_void_p, metaclass=_compointer_meta):
279
283
  _debug("Release %s", self)
280
284
  self.Release() # type: ignore
281
285
 
282
- def __eq__(self, other):
286
+ def __eq__(self, other) -> bool:
283
287
  if not isinstance(other, _compointer_base):
284
288
  return False
285
289
  # get the value property of the c_void_p baseclass, this is the pointer value
@@ -287,18 +291,18 @@ class _compointer_base(c_void_p, metaclass=_compointer_meta):
287
291
  super(_compointer_base, self).value == super(_compointer_base, other).value
288
292
  )
289
293
 
290
- def __hash__(self):
294
+ def __hash__(self) -> int:
291
295
  """Return the hash value of the pointer."""
292
296
  # hash the pointer values
293
297
  return hash(super(_compointer_base, self).value)
294
298
 
295
299
  # redefine the .value property; return the object itself.
296
- def __get_value(self):
300
+ def __get_value(self) -> "hints.Self":
297
301
  return self
298
302
 
299
303
  value = property(__get_value, doc="""Return self.""")
300
304
 
301
- def __repr__(self):
305
+ def __repr__(self) -> str:
302
306
  ptr = super(_compointer_base, self).value
303
307
  return f"<{self.__class__.__name__} ptr=0x{ptr or 0:x} at {id(self):x}>"
304
308
 
@@ -306,13 +310,14 @@ class _compointer_base(c_void_p, metaclass=_compointer_meta):
306
310
  # wrapping the same COM interface. This could happen because some interfaces
307
311
  # are contained in multiple typelibs.
308
312
  #
309
- # It also allows to pass a CoClass instance to an api
310
- # expecting a COM interface.
313
+ # It also allows to pass a COMObject instance to an api expecting a COM interface.
311
314
  @classmethod
312
- def from_param(cls, value):
315
+ def from_param(
316
+ cls, value: "_UnionT[None, Literal[0], hints.Self, IUnknown, hints.COMObject]"
317
+ ) -> Any:
313
318
  """Convert 'value' into a COM pointer to the interface.
314
319
 
315
- This method accepts a COM pointer, or a CoClass instance
320
+ This method accepts a COM pointer, or a COMObject/CoClass instance
316
321
  which is QueryInterface()d."""
317
322
  if value is None:
318
323
  return None
@@ -326,9 +331,9 @@ class _compointer_base(c_void_p, metaclass=_compointer_meta):
326
331
  # Do we need more checks here?
327
332
  if cls._iid_ == getattr(value, "_iid_", None):
328
333
  return value
329
- # Accept an CoClass instance which exposes the interface required.
334
+ # Accept an COMObject instance which exposes the interface required.
330
335
  try:
331
- table = value._com_pointers_
336
+ table = value._com_pointers_ # type: ignore
332
337
  except AttributeError:
333
338
  pass
334
339
  else:
@@ -1,9 +1,9 @@
1
1
  """SAFEARRAY api functions, data types, and constants."""
2
2
 
3
- from ctypes import c_uint, c_ushort, c_void_p, POINTER, Structure, WinDLL
3
+ from ctypes import POINTER, Structure, WinDLL, c_uint, c_ushort, c_void_p
4
4
  from ctypes.wintypes import DWORD, LONG, UINT, USHORT
5
5
 
6
- from comtypes import HRESULT, GUID
6
+ from comtypes import GUID, HRESULT
7
7
 
8
8
  ################################################################
9
9
  # if __debug__:
@@ -17,29 +17,26 @@ from typing import Union as _UnionT
17
17
 
18
18
  import comtypes
19
19
  from comtypes import GUID, IUnknown, hresult
20
- from comtypes._memberspec import _encode_idl
20
+ from comtypes._memberspec import (
21
+ DISPATCH_METHOD,
22
+ DISPATCH_PROPERTYGET,
23
+ DISPATCH_PROPERTYPUT,
24
+ DISPATCH_PROPERTYPUTREF,
25
+ _encode_idl,
26
+ )
21
27
  from comtypes.errorinfo import ReportError, ReportException
22
28
 
23
29
  if TYPE_CHECKING:
24
30
  from ctypes import _FuncPointer
25
31
 
26
32
  from comtypes import hints # type: ignore
27
- from comtypes._memberspec import _ArgSpecElmType, _DispMemberSpec, _ParamFlagType
33
+ from comtypes._memberspec import _ComIdlFlags, _DispIdlFlags, _DispMemberSpec
28
34
 
29
35
  logger = logging.getLogger(__name__)
30
36
  _debug = logger.debug
31
37
  _warning = logger.warning
32
38
  _error = logger.error
33
39
 
34
- ################################################################
35
- # COM object implementation
36
-
37
- # so we don't have to import comtypes.automation
38
- DISPATCH_METHOD = 1
39
- DISPATCH_PROPERTYGET = 2
40
- DISPATCH_PROPERTYPUT = 4
41
- DISPATCH_PROPERTYPUTREF = 8
42
-
43
40
 
44
41
  class E_NotImplemented(Exception):
45
42
  """COM method is not implemented"""
@@ -84,7 +81,7 @@ def _do_implement(interface_name: str, method_name: str) -> Callable[..., int]:
84
81
  def catch_errors(
85
82
  obj: "hints.COMObject",
86
83
  mth: Callable[..., Any],
87
- paramflags: Optional[Tuple["_ParamFlagType", ...]],
84
+ paramflags: Optional[Tuple["hints.ParamFlagType", ...]],
88
85
  interface: Type[IUnknown],
89
86
  mthname: str,
90
87
  ) -> Callable[..., Any]:
@@ -133,7 +130,7 @@ def catch_errors(
133
130
  def hack(
134
131
  inst: "hints.COMObject",
135
132
  mth: Callable[..., Any],
136
- paramflags: Optional[Tuple["_ParamFlagType", ...]],
133
+ paramflags: Optional[Tuple["hints.ParamFlagType", ...]],
137
134
  interface: Type[IUnknown],
138
135
  mthname: str,
139
136
  ) -> Callable[..., Any]:
@@ -241,8 +238,8 @@ class _MethodFinder(object):
241
238
  self,
242
239
  interface: Type[IUnknown],
243
240
  mthname: str,
244
- paramflags: Optional[Tuple["_ParamFlagType", ...]],
245
- idlflags: Tuple[_UnionT[str, int], ...],
241
+ paramflags: Optional[Tuple["hints.ParamFlagType", ...]],
242
+ idlflags: _UnionT["_ComIdlFlags", "_DispIdlFlags"],
246
243
  ) -> Callable[..., Any]:
247
244
  mth = self.find_impl(interface, mthname, paramflags, idlflags)
248
245
  if mth is None:
@@ -263,8 +260,8 @@ class _MethodFinder(object):
263
260
  self,
264
261
  interface: Type[IUnknown],
265
262
  mthname: str,
266
- paramflags: Optional[Tuple["_ParamFlagType", ...]],
267
- idlflags: Tuple[_UnionT[str, int], ...],
263
+ paramflags: Optional[Tuple["hints.ParamFlagType", ...]],
264
+ idlflags: _UnionT["_ComIdlFlags", "_DispIdlFlags"],
268
265
  ) -> Optional[Callable[..., Any]]:
269
266
  fq_name = f"{interface.__name__}_{mthname}"
270
267
  if interface._case_insensitive_:
@@ -340,25 +337,29 @@ def create_vtbl_mapping(
340
337
  methods: List[Callable[..., Any]] = [] # method implementations
341
338
  fields: List[Tuple[str, Type["_FuncPointer"]]] = [] # virtual function table
342
339
  iids: List[GUID] = [] # interface identifiers.
343
- # iterate over interface inheritance in reverse order to build the
344
- # virtual function table, and leave out the 'object' base class.
345
- for interface in itf.__mro__[-2::-1]:
340
+ for interface in _walk_itf_bases(itf):
346
341
  iids.append(interface._iid_)
347
342
  for m in interface._methods_:
348
- restype, mthname, argtypes, paramflags, idlflags, helptext = m
349
- proto = WINFUNCTYPE(restype, c_void_p, *argtypes)
350
- fields.append((mthname, proto))
351
- mth = finder.get_impl(interface, mthname, paramflags, idlflags)
343
+ proto = WINFUNCTYPE(m.restype, c_void_p, *m.argtypes)
344
+ fields.append((m.name, proto))
345
+ mth = finder.get_impl(interface, m.name, m.paramflags, m.idlflags)
352
346
  methods.append(proto(mth))
353
347
  Vtbl = _create_vtbl_type(tuple(fields), itf)
354
348
  vtbl = Vtbl(*methods)
355
349
  return (iids, vtbl)
356
350
 
357
351
 
352
+ def _walk_itf_bases(itf: Type[IUnknown]) -> Iterator[Type[IUnknown]]:
353
+ """Iterates over interface inheritance in reverse order to build the
354
+ virtual function table, and leave out the 'object' base class.
355
+ """
356
+ yield from itf.__mro__[-2::-1]
357
+
358
+
358
359
  def create_dispimpl(
359
360
  itf: Type[IUnknown], finder: _MethodFinder
360
- ) -> Dict[Tuple[int, int], Callable[..., Any]]:
361
- dispimpl: Dict[Tuple[int, int], Callable[..., Any]] = {}
361
+ ) -> Dict[Tuple[comtypes.dispid, int], Callable[..., Any]]:
362
+ dispimpl: Dict[Tuple[comtypes.dispid, int], Callable[..., Any]] = {}
362
363
  for m in itf._disp_methods_:
363
364
  #################
364
365
  # What we have:
@@ -374,13 +375,6 @@ def create_dispimpl(
374
375
  #
375
376
  # paramflags must be a sequence
376
377
  # of (F_IN|F_OUT|F_RETVAL, paramname[, default-value]) tuples
377
- #
378
- # comtypes has this function which helps:
379
- # def _encode_idl(names):
380
- # # convert to F_xxx and sum up "in", "out",
381
- # # "retval" values found in _PARAMFLAGS, ignoring
382
- # # other stuff.
383
- # return sum([_PARAMFLAGS.get(n, 0) for n in names])
384
378
  #################
385
379
 
386
380
  if m.what == "DISPMETHOD":
@@ -392,37 +386,40 @@ def create_dispimpl(
392
386
 
393
387
  def _make_dispmthentry(
394
388
  itf: Type[IUnknown], finder: _MethodFinder, m: "_DispMemberSpec"
395
- ) -> Iterator[Tuple[Tuple[int, int], Callable[..., Any]]]:
396
- _, mthname, idlflags, restype, argspec = m
397
- if "propget" in idlflags:
389
+ ) -> Iterator[Tuple[Tuple[comtypes.dispid, int], Callable[..., Any]]]:
390
+ if "propget" in m.idlflags:
398
391
  invkind = DISPATCH_PROPERTYGET
399
- mthname = f"_get_{mthname}"
400
- elif "propput" in idlflags:
392
+ mthname = f"_get_{m.name}"
393
+ elif "propput" in m.idlflags:
401
394
  invkind = DISPATCH_PROPERTYPUT
402
- mthname = f"_set_{mthname}"
403
- elif "propputref" in idlflags:
395
+ mthname = f"_set_{m.name}"
396
+ elif "propputref" in m.idlflags:
404
397
  invkind = DISPATCH_PROPERTYPUTREF
405
- mthname = f"_setref_{mthname}"
398
+ mthname = f"_setref_{m.name}"
406
399
  else:
407
400
  invkind = DISPATCH_METHOD
408
- if restype:
409
- argspec = argspec + ((["out"], restype, ""),)
410
- yield from _make_dispentry(finder, itf, mthname, idlflags, argspec, invkind)
401
+ if m.restype:
402
+ argspec = m.argspec + ((["out"], m.restype, ""),)
403
+ else:
404
+ argspec = m.argspec
405
+ mthname = m.name
406
+ yield from _make_dispentry(finder, itf, mthname, m.idlflags, argspec, invkind)
411
407
 
412
408
 
413
409
  def _make_disppropentry(
414
410
  itf: Type[IUnknown], finder: _MethodFinder, m: "_DispMemberSpec"
415
- ) -> Iterator[Tuple[Tuple[int, int], Callable[..., Any]]]:
416
- _, mthname, idlflags, restype, argspec = m
417
- # DISPPROPERTY have implicit "out"
418
- if restype:
419
- argspec += ((["out"], restype, ""),)
411
+ ) -> Iterator[Tuple[Tuple[comtypes.dispid, int], Callable[..., Any]]]:
412
+ if m.restype:
413
+ # DISPPROPERTY have implicit "out"
414
+ argspec = m.argspec + ((["out"], m.restype, ""),)
415
+ else:
416
+ argspec = m.argspec
420
417
  yield from _make_dispentry(
421
- finder, itf, f"_get_{mthname}", idlflags, argspec, DISPATCH_PROPERTYGET
418
+ finder, itf, f"_get_{m.name}", m.idlflags, argspec, DISPATCH_PROPERTYGET
422
419
  )
423
- if "readonly" not in idlflags:
420
+ if "readonly" not in m.idlflags:
424
421
  yield from _make_dispentry(
425
- finder, itf, f"_set_{mthname}", idlflags, argspec, DISPATCH_PROPERTYPUT
422
+ finder, itf, f"_set_{m.name}", m.idlflags, argspec, DISPATCH_PROPERTYPUT
426
423
  )
427
424
  # Add DISPATCH_PROPERTYPUTREF also?
428
425
 
@@ -431,10 +428,10 @@ def _make_dispentry(
431
428
  finder: _MethodFinder,
432
429
  interface: Type[IUnknown],
433
430
  mthname: str,
434
- idlflags: Tuple[_UnionT[str, int], ...],
435
- argspec: Tuple["_ArgSpecElmType", ...],
431
+ idlflags: "_DispIdlFlags",
432
+ argspec: Tuple["hints.ArgSpecElmType", ...],
436
433
  invkind: int,
437
- ) -> Iterator[Tuple[Tuple[int, int], Callable[..., Any]]]:
434
+ ) -> Iterator[Tuple[Tuple[comtypes.dispid, int], Callable[..., Any]]]:
438
435
  # We build a _dispmap_ entry now that maps invkind and dispid to
439
436
  # implementations that the finder finds; IDispatch_Invoke will later call it.
440
437
  paramflags = tuple(((_encode_idl(x[0]), x[1]) + tuple(x[3:])) for x in argspec)
@@ -11,12 +11,16 @@ from typing import TYPE_CHECKING, Any, ClassVar, Dict, List, Optional, Type
11
11
 
12
12
  import comtypes
13
13
  import comtypes.patcher
14
- from comtypes import BSTR, COMMETHOD, GUID, IID, STDMETHOD, IUnknown, _CData, _safearray
14
+ from comtypes import BSTR, COMMETHOD, GUID, IID, STDMETHOD, IUnknown, _safearray
15
15
  from comtypes import hresult as hresult
16
+ from comtypes._memberspec import DISPATCH_METHOD as DISPATCH_METHOD
17
+ from comtypes._memberspec import DISPATCH_PROPERTYGET as DISPATCH_PROPERTYGET
18
+ from comtypes._memberspec import DISPATCH_PROPERTYPUT as DISPATCH_PROPERTYPUT
19
+ from comtypes._memberspec import DISPATCH_PROPERTYPUTREF as DISPATCH_PROPERTYPUTREF
16
20
  from comtypes.safearray import _midlSAFEARRAY
17
21
 
18
22
  if TYPE_CHECKING:
19
- from ctypes import _CArgObject
23
+ from ctypes import _CArgObject, _CDataType
20
24
 
21
25
  from comtypes import hints # type: ignore
22
26
  from comtypes._memberspec import _DispMemberSpec
@@ -30,11 +34,6 @@ SCODE = LONG
30
34
 
31
35
  VARTYPE = c_ushort
32
36
 
33
- DISPATCH_METHOD = 1
34
- DISPATCH_PROPERTYGET = 2
35
- DISPATCH_PROPERTYPUT = 4
36
- DISPATCH_PROPERTYPUTREF = 8
37
-
38
37
  tagINVOKEKIND = c_int
39
38
  INVOKE_FUNC = DISPATCH_METHOD
40
39
  INVOKE_PROPERTYGET = DISPATCH_PROPERTYGET
@@ -575,23 +574,29 @@ class tagVARIANT(Structure):
575
574
  VARIANT = tagVARIANT
576
575
  VARIANTARG = VARIANT
577
576
 
577
+ _oleaut32_nohresult = WinDLL("oleaut32")
578
+
579
+ _SysAllocStringLen = _oleaut32_nohresult.SysAllocStringLen
580
+ _SysAllocStringLen.argtypes = c_wchar_p, c_uint
581
+ _SysAllocStringLen.restype = c_void_p
582
+
578
583
  _oleaut32 = OleDLL("oleaut32")
579
584
 
580
585
  _VariantChangeType = _oleaut32.VariantChangeType
581
586
  _VariantChangeType.argtypes = (POINTER(VARIANT), POINTER(VARIANT), c_ushort, VARTYPE)
587
+ _VariantChangeType.restype = HRESULT
582
588
 
583
589
  _VariantClear = _oleaut32.VariantClear
584
590
  _VariantClear.argtypes = (POINTER(VARIANT),)
585
-
586
- _SysAllocStringLen = windll.oleaut32.SysAllocStringLen
587
- _SysAllocStringLen.argtypes = c_wchar_p, c_uint
588
- _SysAllocStringLen.restype = c_void_p
591
+ _VariantClear.restype = HRESULT
589
592
 
590
593
  _VariantCopy = _oleaut32.VariantCopy
591
594
  _VariantCopy.argtypes = POINTER(VARIANT), POINTER(VARIANT)
595
+ _VariantCopy.restype = HRESULT
592
596
 
593
597
  _VariantCopyInd = _oleaut32.VariantCopyInd
594
598
  _VariantCopyInd.argtypes = POINTER(VARIANT), POINTER(VARIANT)
599
+ _VariantCopyInd.restype = HRESULT
595
600
 
596
601
  # some commonly used VARIANT instances
597
602
  VARIANT.null = VARIANT(None)
@@ -872,7 +877,7 @@ class IDispatch(IUnknown):
872
877
  # objects referred to by rgvarg[ ] or placed in *pVarResult.
873
878
  #
874
879
  # For comtypes this is handled in DISPPARAMS.__del__ and VARIANT.__del__.
875
- _invkind = kw.pop("_invkind", 1) # DISPATCH_METHOD
880
+ _invkind = kw.pop("_invkind", DISPATCH_METHOD)
876
881
  _lcid = kw.pop("_lcid", 0)
877
882
  if kw:
878
883
  raise ValueError("named parameters not yet implemented")
@@ -943,7 +948,7 @@ _arraycode_to_vartype = {
943
948
  "B": VT_UI1,
944
949
  }
945
950
 
946
- _ctype_to_vartype: Dict[Type[_CData], int] = {
951
+ _ctype_to_vartype: Dict[Type["_CDataType"], int] = {
947
952
  c_byte: VT_I1,
948
953
  c_ubyte: VT_UI1,
949
954
  c_short: VT_I2,
@@ -980,7 +985,7 @@ _ctype_to_vartype: Dict[Type[_CData], int] = {
980
985
  # POINTER(IDispatch): VT_DISPATCH,
981
986
  }
982
987
 
983
- _vartype_to_ctype: Dict[int, Type[_CData]] = {}
988
+ _vartype_to_ctype: Dict[int, Type["_CDataType"]] = {}
984
989
  for c, v in _ctype_to_vartype.items():
985
990
  _vartype_to_ctype[v] = c
986
991
  _vartype_to_ctype[VT_INT] = _vartype_to_ctype[VT_I4]
@@ -0,0 +1,42 @@
1
+ """comtypes.client - High level client level COM support package."""
2
+
3
+ import ctypes
4
+ import logging
5
+
6
+ from comtypes import automation
7
+ from comtypes.client import dynamic, lazybind # noqa
8
+ from comtypes.client._code_cache import _find_gen_dir
9
+ from comtypes.client._constants import Constants # noqa
10
+ from comtypes.client._events import GetEvents, PumpEvents, ShowEvents
11
+ from comtypes.client._generate import GetModule
12
+ from comtypes.client._managing import GetBestInterface, _manage, wrap_outparam # noqa
13
+ from comtypes.hresult import * # noqa
14
+
15
+ gen_dir = _find_gen_dir()
16
+ import comtypes.gen # noqa
17
+
18
+ ### for testing
19
+ ##gen_dir = None
20
+
21
+ logger = logging.getLogger(__name__)
22
+
23
+
24
+ # backwards compatibility:
25
+ wrap = GetBestInterface
26
+
27
+ # Should we do this for POINTER(IUnknown) also?
28
+ ctypes.POINTER(automation.IDispatch).__ctypes_from_outparam__ = wrap_outparam # type: ignore
29
+
30
+ from comtypes.client._activeobj import GetActiveObject
31
+ from comtypes.client._create import (
32
+ CoGetObject,
33
+ CreateObject,
34
+ GetClassObject,
35
+ )
36
+
37
+ # fmt: off
38
+ __all__ = [
39
+ "CreateObject", "GetActiveObject", "CoGetObject", "GetEvents",
40
+ "ShowEvents", "PumpEvents", "GetModule", "GetClassObject",
41
+ ]
42
+ # fmt: on
@@ -0,0 +1,46 @@
1
+ from typing import Any, Optional, Type, TypeVar, overload
2
+ from typing import Union as _UnionT
3
+
4
+ import comtypes
5
+ import comtypes.client.dynamic
6
+ from comtypes import GUID, CoClass, IUnknown, automation
7
+ from comtypes.client._managing import _manage
8
+
9
+ _T_IUnknown = TypeVar("_T_IUnknown", bound=IUnknown)
10
+
11
+
12
+ ################################################################
13
+ #
14
+ # Object creation
15
+ #
16
+ @overload
17
+ def GetActiveObject(progid: _UnionT[str, Type[CoClass], GUID]) -> Any: ...
18
+ @overload
19
+ def GetActiveObject(
20
+ progid: _UnionT[str, Type[CoClass], GUID], interface: Type[_T_IUnknown]
21
+ ) -> _T_IUnknown: ...
22
+ def GetActiveObject(
23
+ progid: _UnionT[str, Type[CoClass], GUID],
24
+ interface: Optional[Type[IUnknown]] = None,
25
+ dynamic: bool = False,
26
+ ) -> Any:
27
+ """Return a pointer to a running COM object that has been
28
+ registered with COM.
29
+
30
+ 'progid' may be a string like "Excel.Application",
31
+ a string specifying a clsid, a GUID instance, or an object with
32
+ a _clsid_ attribute which should be any of the above.
33
+ 'interface' allows to force a certain interface.
34
+ 'dynamic=True' will return a dynamic dispatch object.
35
+ """
36
+ clsid = GUID.from_progid(progid)
37
+ if dynamic:
38
+ if interface is not None:
39
+ raise ValueError("interface and dynamic are mutually exclusive")
40
+ interface = automation.IDispatch
41
+ elif interface is None:
42
+ interface = getattr(progid, "_com_interfaces_", [None])[0]
43
+ obj = comtypes.GetActiveObject(clsid, interface=interface)
44
+ if dynamic:
45
+ return comtypes.client.dynamic.Dispatch(obj)
46
+ return _manage(obj, clsid, interface=interface)
@@ -5,8 +5,15 @@ comtypes.gen package and returns a directory where generated code can
5
5
  be written to.
6
6
  """
7
7
 
8
- import ctypes, logging, os, sys, tempfile, types
9
- from ctypes import wintypes
8
+ import ctypes
9
+ import logging
10
+ import os
11
+ import sys
12
+ import tempfile
13
+ import types
14
+ from ctypes.wintypes import BOOL, HWND, LPWSTR, MAX_PATH
15
+
16
+ from comtypes import typeinfo
10
17
 
11
18
  logger = logging.getLogger(__name__)
12
19
 
@@ -49,14 +56,14 @@ def _find_gen_dir():
49
56
  # where generated modules are placed.
50
57
  ftype = getattr(sys, "frozen", None)
51
58
  pymaj, pymin = sys.version_info[:2]
52
- if ftype == None:
59
+ if ftype is None:
53
60
  # Python script
54
61
  subdir = rf"Python\Python{pymaj:d}{pymin:d}\comtypes_cache"
55
62
  basedir = _get_appdata_dir()
56
63
 
57
64
  elif ftype == "dll":
58
65
  # dll created with py2exe
59
- path = _get_module_filename(sys.frozendllhandle)
66
+ path = typeinfo.GetModuleFileName(sys.frozendllhandle, MAX_PATH)
60
67
  base = os.path.splitext(os.path.basename(path))[0]
61
68
  subdir = rf"comtypes_cache\{base}-{pymaj:d}{pymin:d}"
62
69
  basedir = tempfile.gettempdir()
@@ -79,19 +86,12 @@ def _find_gen_dir():
79
86
 
80
87
  ################################################################
81
88
 
82
- SHGetSpecialFolderPath = ctypes.OleDLL("shell32.dll").SHGetSpecialFolderPathW
83
- GetModuleFileName = ctypes.WinDLL("kernel32.dll").GetModuleFileNameW
84
- SHGetSpecialFolderPath.argtypes = [
85
- ctypes.c_ulong,
86
- ctypes.c_wchar_p,
87
- ctypes.c_int,
88
- ctypes.c_int,
89
- ]
90
- GetModuleFileName.restype = ctypes.c_ulong
91
- GetModuleFileName.argtypes = [wintypes.HMODULE, ctypes.c_wchar_p, ctypes.c_ulong]
89
+ _shell32 = ctypes.OleDLL("shell32.dll")
90
+ SHGetSpecialFolderPath = _shell32.SHGetSpecialFolderPathW
91
+ SHGetSpecialFolderPath.argtypes = [HWND, LPWSTR, ctypes.c_int, BOOL]
92
+ SHGetSpecialFolderPath.restype = BOOL
92
93
 
93
94
  CSIDL_APPDATA = 26
94
- MAX_PATH = 260
95
95
 
96
96
 
97
97
  def _create_comtypes_gen_package():
@@ -132,15 +132,6 @@ def _is_writeable(path):
132
132
  return os.access(path[0], os.W_OK)
133
133
 
134
134
 
135
- def _get_module_filename(hmodule):
136
- """Call the Windows GetModuleFileName function which determines
137
- the path from a module handle."""
138
- path = ctypes.create_unicode_buffer(MAX_PATH)
139
- if GetModuleFileName(hmodule, path, MAX_PATH):
140
- return path.value
141
- raise ctypes.WinError()
142
-
143
-
144
135
  def _get_appdata_dir():
145
136
  """Return the 'file system directory that serves as a common
146
137
  repository for application-specific data' - CSIDL_APPDATA"""