comtypes 1.4.11__zip → 1.4.13__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.11 → comtypes-1.4.13}/CHANGES.txt +33 -0
  2. {comtypes-1.4.11/comtypes.egg-info → comtypes-1.4.13}/PKG-INFO +5 -5
  3. {comtypes-1.4.11 → comtypes-1.4.13}/README.md +3 -3
  4. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/__init__.py +8 -2
  5. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/_comobject.py +6 -6
  6. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/_memberspec.py +7 -7
  7. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/_meta.py +7 -3
  8. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/_npsupport.py +12 -17
  9. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/_post_coinit/_cominterface_meta_patcher.py +5 -5
  10. comtypes-1.4.13/comtypes/_post_coinit/activeobj.py +61 -0
  11. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/_post_coinit/misc.py +1 -23
  12. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/_post_coinit/unknwn.py +10 -8
  13. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/_vtbl.py +3 -3
  14. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/automation.py +10 -13
  15. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/client/__init__.py +2 -1
  16. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/client/_activeobj.py +8 -0
  17. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/client/_code_cache.py +1 -1
  18. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/client/_constants.py +1 -1
  19. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/client/_events.py +6 -6
  20. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/client/_generate.py +1 -1
  21. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/client/dynamic.py +3 -3
  22. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/client/lazybind.py +3 -3
  23. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/errorinfo.py +1 -1
  24. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/hresult.py +68 -0
  25. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/messageloop.py +1 -1
  26. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/patcher.py +2 -2
  27. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/persist.py +9 -2
  28. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/safearray.py +10 -10
  29. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/server/__init__.py +5 -37
  30. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/server/automation.py +2 -2
  31. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/server/connectionpoints.py +3 -3
  32. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/server/inprocserver.py +2 -2
  33. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/server/localserver.py +3 -3
  34. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/server/register.py +5 -5
  35. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_agilent.py +1 -1
  36. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_client_dynamic.py +1 -1
  37. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_comserver.py +15 -2
  38. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_createwrappers.py +1 -1
  39. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_dispifc_records.py +0 -2
  40. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_dispifc_safearrays.py +0 -2
  41. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_dispinterface.py +1 -1
  42. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_excel.py +2 -5
  43. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_getactiveobj.py +19 -2
  44. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_hresult.py +39 -0
  45. comtypes-1.4.13/comtypes/test/test_messageloop.py +117 -0
  46. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_midl_safearray_create.py +0 -2
  47. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_msscript.py +1 -1
  48. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_npsupport.py +22 -11
  49. comtypes-1.4.13/comtypes/test/test_persist.py +71 -0
  50. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_recordinfo.py +0 -2
  51. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_server.py +6 -6
  52. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_storage.py +1 -1
  53. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_stream.py +22 -2
  54. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_urlhistory.py +1 -1
  55. comtypes-1.4.13/comtypes/test/test_util.py +227 -0
  56. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_variant.py +41 -24
  57. comtypes-1.4.13/comtypes/test/test_viewobject.py +78 -0
  58. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_word.py +1 -1
  59. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/tools/codegenerator/codegenerator.py +1 -1
  60. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/tools/codegenerator/comments.py +1 -1
  61. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/tools/codegenerator/heads.py +5 -5
  62. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/tools/codegenerator/helpers.py +7 -7
  63. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/tools/codegenerator/namespaces.py +3 -3
  64. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/tools/codegenerator/typeannotator.py +2 -2
  65. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/tools/tlbparser.py +1 -1
  66. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/tools/typedesc.py +14 -14
  67. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/tools/typedesc_base.py +19 -19
  68. comtypes-1.4.13/comtypes/util.py +189 -0
  69. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/viewobject.py +29 -5
  70. {comtypes-1.4.11 → comtypes-1.4.13/comtypes.egg-info}/PKG-INFO +5 -5
  71. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes.egg-info/SOURCES.txt +4 -0
  72. {comtypes-1.4.11 → comtypes-1.4.13}/pyproject.toml +12 -1
  73. {comtypes-1.4.11 → comtypes-1.4.13}/setup.cfg +1 -1
  74. comtypes-1.4.11/comtypes/test/test_persist.py +0 -38
  75. comtypes-1.4.11/comtypes/util.py +0 -107
  76. {comtypes-1.4.11 → comtypes-1.4.13}/LICENSE.txt +0 -0
  77. {comtypes-1.4.11 → comtypes-1.4.13}/MANIFEST.in +0 -0
  78. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/GUID.py +0 -0
  79. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/_post_coinit/__init__.py +0 -0
  80. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/_post_coinit/bstr.py +0 -0
  81. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/_post_coinit/instancemethod.py +0 -0
  82. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/_safearray.py +0 -0
  83. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/_tlib_version_checker.py +0 -0
  84. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/clear_cache.py +0 -0
  85. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/client/_create.py +0 -0
  86. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/client/_managing.py +0 -0
  87. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/connectionpoints.py +0 -0
  88. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/git.py +0 -0
  89. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/hints.pyi +0 -0
  90. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/logutil.py +0 -0
  91. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/server/w_getopt.py +0 -0
  92. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/shelllink.py +0 -0
  93. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/stream.py +0 -0
  94. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/TestComServer.idl +0 -0
  95. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/TestComServer.py +0 -0
  96. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/TestComServer.tlb +0 -0
  97. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/TestDispServer.idl +0 -0
  98. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/TestDispServer.py +0 -0
  99. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/TestDispServer.tlb +0 -0
  100. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/__init__.py +0 -0
  101. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/find_memleak.py +0 -0
  102. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/mylib.idl +0 -0
  103. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/mylib.tlb +0 -0
  104. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/mytypelib.idl +0 -0
  105. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/runtests.py +0 -0
  106. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/setup.py +0 -0
  107. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_BSTR.py +0 -0
  108. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_DISPPARAMS.py +0 -0
  109. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_GUID.py +0 -0
  110. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_QueryService.py +0 -0
  111. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_avmc.py +0 -0
  112. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_basic.py +0 -0
  113. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_casesensitivity.py +0 -0
  114. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_clear_cache.py +0 -0
  115. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_client.py +0 -0
  116. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_client_regenerate_modules.py +0 -0
  117. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_collections.py +0 -0
  118. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_comobject.py +0 -0
  119. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_dict.py +0 -0
  120. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_dyndispatch.py +0 -0
  121. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_errorinfo.py +0 -0
  122. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_findgendir.py +0 -0
  123. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_ie.py +0 -0
  124. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_ienum.py +0 -0
  125. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_imfattributes.py +0 -0
  126. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_inout_args.py +0 -0
  127. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_jscript.js +0 -0
  128. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_monikers.py +0 -0
  129. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_outparam.py +0 -0
  130. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_pump_events.py +0 -0
  131. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_safearray.py +0 -0
  132. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_sapi.py +0 -0
  133. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_server_register.py +0 -0
  134. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_shelllink.py +0 -0
  135. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_showevents.py +0 -0
  136. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_subinterface.py +0 -0
  137. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_typeannotator.py +0 -0
  138. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_typeinfo.py +0 -0
  139. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_w_getopt.py +0 -0
  140. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_win32com_interop.py +0 -0
  141. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/test_wmi.py +0 -0
  142. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/test/urlhist.tlb +0 -0
  143. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/tools/__init__.py +0 -0
  144. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/tools/codegenerator/__init__.py +0 -0
  145. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/tools/codegenerator/modulenamer.py +0 -0
  146. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/tools/codegenerator/packing.py +0 -0
  147. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes/typeinfo.py +0 -0
  148. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes.egg-info/dependency_links.txt +0 -0
  149. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes.egg-info/entry_points.txt +0 -0
  150. {comtypes-1.4.11 → comtypes-1.4.13}/comtypes.egg-info/top_level.txt +0 -0
  151. {comtypes-1.4.11 → comtypes-1.4.13}/setup.py +0 -0
@@ -43,7 +43,7 @@ class _frozen_attr_dict(dict):
43
43
  raise TypeError
44
44
 
45
45
 
46
- class Constants(object):
46
+ class Constants:
47
47
  """This class loads the type library from the supplied object,
48
48
  then exposes constants and enumerations in the type library
49
49
  as attributes.
@@ -64,7 +64,7 @@ _CloseHandle.restype = BOOL
64
64
  _ReceiverType = _UnionT[COMObject, IUnknown]
65
65
 
66
66
 
67
- class _AdviseConnection(object):
67
+ class _AdviseConnection:
68
68
  cp: Optional[IConnectionPoint]
69
69
  cookie: Optional[int]
70
70
  receiver: Optional[_ReceiverType]
@@ -104,7 +104,7 @@ class _AdviseConnection(object):
104
104
  if self.cookie is not None:
105
105
  assert self.cp is not None
106
106
  self.cp.Unadvise(self.cookie)
107
- except (COMError, WindowsError):
107
+ except (OSError, COMError):
108
108
  # Are we sure we want to ignore errors here?
109
109
  pass
110
110
 
@@ -209,7 +209,7 @@ class _SinkMethodFinder(_MethodFinder):
209
209
  """
210
210
 
211
211
  def __init__(self, inst: COMObject, sink: Any) -> None:
212
- super(_SinkMethodFinder, self).__init__(inst)
212
+ super().__init__(inst)
213
213
  self.sink = sink
214
214
 
215
215
  def find_method(self, fq_name: str, mthname: str) -> Callable[..., Any]:
@@ -229,7 +229,7 @@ class _SinkMethodFinder(_MethodFinder):
229
229
 
230
230
  def _find_method(self, fq_name: str, mthname: str) -> Callable[..., Any]:
231
231
  try:
232
- return super(_SinkMethodFinder, self).find_method(fq_name, mthname)
232
+ return super().find_method(fq_name, mthname)
233
233
  except AttributeError:
234
234
  try:
235
235
  return getattr(self.sink, fq_name)
@@ -283,7 +283,7 @@ def GetEvents(
283
283
  return _AdviseConnection(source, interface, rcv)
284
284
 
285
285
 
286
- class EventDumper(object):
286
+ class EventDumper:
287
287
  """Universal sink for COM events."""
288
288
 
289
289
  def __getattr__(self, name: str) -> Callable[..., Any]:
@@ -381,7 +381,7 @@ def PumpEvents(timeout: Any) -> None:
381
381
  handles,
382
382
  byref(ctypes.c_ulong()),
383
383
  )
384
- except WindowsError as details:
384
+ except OSError as details:
385
385
  if details.winerror != hresult.RPC_S_CALLPENDING: # timeout expired
386
386
  raise
387
387
  else:
@@ -211,7 +211,7 @@ def _create_module(modulename: str, code: str) -> types.ModuleType:
211
211
  return _my_import(modulename)
212
212
 
213
213
 
214
- class ModuleGenerator(object):
214
+ class ModuleGenerator:
215
215
  def __init__(self, tlib: typeinfo.ITypeLib, pathname: Optional[str]) -> None:
216
216
  self.wrapper_name = codegenerator.name_wrapper_module(tlib)
217
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
  """
@@ -126,7 +126,7 @@ def ReportError(
126
126
  clsid = GUID(clsid)
127
127
  try:
128
128
  progid = clsid.as_progid()
129
- except WindowsError:
129
+ except OSError:
130
130
  pass
131
131
  else:
132
132
  # progid for the class or application that created the error
@@ -89,3 +89,71 @@ def HRESULT_FROM_WIN32(x: int) -> int:
89
89
  # them into HRESULT values by setting the high bit, ensuring a consistent way
90
90
  # to indicate failure across these APIs.
91
91
  RPC_S_SERVER_UNAVAILABLE = -2147023174 # 0x800706BA (WIN32: 1722 0x6BA)
92
+
93
+
94
+ ################################################################
95
+ # signed32bithex
96
+ #
97
+ # When using this package, error codes for exceptions like
98
+ # `COMError` or `WindowsError` are base10 integers.
99
+ #
100
+ # However, as shown below, many technical references represent
101
+ # HRESULT values using signed 32-bit hexadecimal notation:
102
+ # https://learn.microsoft.com/en-us/windows/win32/seccrypto/common-hresult-values
103
+ # https://learn.microsoft.com/en-us/windows/win32/learnwin32/error-codes-in-com
104
+ #
105
+ # If you search for the error code using the proper notation,
106
+ # you might be able to find the reference.
107
+ #
108
+ # Don't be overly afraid of `COMError` or `WindowsError`!
109
+
110
+
111
+ def signed32bithex_to_int(value: str, /) -> int:
112
+ """Converts a string in signed 32-bit hexadecimal notation to an integer.
113
+
114
+ Examples:
115
+
116
+ >>> signed32bithex_to_int('0x00000000') == 0 # S_OK
117
+ True
118
+ >>> signed32bithex_to_int('0x00000001') == 1 # S_FALSE
119
+ True
120
+ >>> signed32bithex_to_int('0x8000FFFF') == -2147418113 # E_UNEXPECTED
121
+ True
122
+ """
123
+ val = int(value, 16)
124
+ if val < 0x80000000:
125
+ return val
126
+ return val - 0x100000000
127
+
128
+
129
+ def int_to_signed32bithex(value: int, /) -> str:
130
+ """Converts an integer to a string in signed 32-bit hexadecimal notation.
131
+
132
+ Examples:
133
+
134
+ >>> import comtypes.hresult as hr
135
+ >>> int_to_signed32bithex(hr.S_OK)
136
+ '0x00000000'
137
+ >>> int_to_signed32bithex(hr.S_FALSE)
138
+ '0x00000001'
139
+ >>> int_to_signed32bithex(hr.E_UNEXPECTED)
140
+ '0x8000FFFF'
141
+
142
+ >>> from comtypes import CoCreateInstance
143
+ >>> from comtypes import shelllink, automation
144
+ >>> CLSID_ShellLink = shelllink.ShellLink().IPersist_GetClassID()
145
+ >>> p = CoCreateInstance(CLSID_ShellLink)
146
+ >>> p.QueryInterface(shelllink.IShellLinkA) # doctest: +ELLIPSIS
147
+ <POINTER(IShellLinkA) ptr=0x... at ...>
148
+ >>> p.QueryInterface(automation.IDispatch) # doctest: +ELLIPSIS
149
+ Traceback (most recent call last):
150
+ ...
151
+ _ctypes.COMError: (-2147467262, ..., (None, None, None, 0, None))
152
+ >>> int_to_signed32bithex(-2147467262) # E_NOINTERFACE
153
+ '0x80004002'
154
+ """
155
+ # it is simpler than using `hex(value & 0xFFFFFFFF)`
156
+ return f"0x{value & 0xFFFFFFFF:08X}"
157
+
158
+
159
+ ################################################################
@@ -17,7 +17,7 @@ TranslateMessage = _user32.TranslateMessage
17
17
  DispatchMessage = _user32.DispatchMessageA
18
18
 
19
19
 
20
- class _MessageLoop(object):
20
+ class _MessageLoop:
21
21
  def __init__(self) -> None:
22
22
  self._filters: List["_FilterCallable"] = []
23
23
 
@@ -1,4 +1,4 @@
1
- class Patch(object):
1
+ class Patch:
2
2
  """
3
3
  Implements a class decorator suitable for patching an existing class with
4
4
  a new namespace.
@@ -69,7 +69,7 @@ def no_replace(f):
69
69
  return f
70
70
 
71
71
 
72
- class ReferenceEmptyClass(object):
72
+ class ReferenceEmptyClass:
73
73
  """
74
74
  This empty class will serve as a reference for attributes present on
75
75
  any class.
@@ -12,7 +12,7 @@ interface, useful in client code.
12
12
 
13
13
  from ctypes import POINTER, Structure, c_int, c_ulong, c_ushort, c_wchar_p
14
14
  from ctypes.wintypes import BOOL, DWORD, WORD
15
- from typing import TYPE_CHECKING
15
+ from typing import TYPE_CHECKING, Any, Optional
16
16
 
17
17
  from comtypes import COMMETHOD, GUID, HRESULT, IPersist, IUnknown
18
18
  from comtypes.automation import VARIANT, tagEXCEPINFO
@@ -65,6 +65,13 @@ class IPropertyBag(IUnknown):
65
65
  ),
66
66
  ]
67
67
 
68
+ if TYPE_CHECKING:
69
+
70
+ def Read(
71
+ self, pszPropName: str, pVar: VARIANT, pErrorLog: Optional[IErrorLog]
72
+ ) -> Any: ...
73
+ def Write(self, pszPropName: str, pVar: Any) -> hints.Hresult: ...
74
+
68
75
 
69
76
  class IPersistPropertyBag(IPersist):
70
77
  _iid_ = GUID("{37D84F60-42CB-11CE-8135-00AA004BB851}")
@@ -266,7 +273,7 @@ class DictPropertyBag(COMObject):
266
273
  _com_interfaces_ = [IPropertyBag]
267
274
 
268
275
  def __init__(self, **kw):
269
- super(DictPropertyBag, self).__init__()
276
+ super().__init__()
270
277
  self.values = kw
271
278
 
272
279
  def Read(self, this, name, pVar, errorlog):
@@ -17,7 +17,7 @@ if TYPE_CHECKING:
17
17
  _safearray_type_cache = {}
18
18
 
19
19
 
20
- class _SafeArrayAsNdArrayContextManager(object):
20
+ class _SafeArrayAsNdArrayContextManager:
21
21
  """Context manager allowing safe arrays to be extracted as ndarrays.
22
22
 
23
23
  This is thread-safe.
@@ -110,7 +110,7 @@ def _make_safearray_type(itemtype):
110
110
  raise TypeError(itemtype)
111
111
 
112
112
  @Patch(POINTER(sa_type))
113
- class _(object):
113
+ class _:
114
114
  # Should explain the ideas how SAFEARRAY is used in comtypes
115
115
  _itemtype_ = itemtype # a ctypes type
116
116
  _vartype_ = vartype # a VARTYPE value: VT_...
@@ -378,7 +378,7 @@ def _make_safearray_type(itemtype):
378
378
  return tuple(result) # for compatibility with pywin32.
379
379
 
380
380
  @Patch(POINTER(POINTER(sa_type)))
381
- class __(object):
381
+ class __:
382
382
  @classmethod
383
383
  def from_param(cls, value):
384
384
  if isinstance(value, cls._type_):
@@ -398,19 +398,19 @@ def _make_safearray_type(itemtype):
398
398
  def _ndarray_to_variant_array(value):
399
399
  """Convert an ndarray to VARIANT_dtype array"""
400
400
  # Check that variant arrays are supported
401
- if comtypes.npsupport.interop.VARIANT_dtype is None:
401
+ if comtypes.npsupport.VARIANT_dtype is None:
402
402
  msg = "VARIANT ndarrays require NumPy 1.7 or newer."
403
403
  raise RuntimeError(msg)
404
- numpy = comtypes.npsupport.interop.numpy
404
+ numpy = comtypes.npsupport.numpy
405
405
 
406
406
  # special cases
407
- if numpy.issubdtype(value.dtype, comtypes.npsupport.interop.datetime64):
407
+ if numpy.issubdtype(value.dtype, comtypes.npsupport.datetime64):
408
408
  return _datetime64_ndarray_to_variant_array(value)
409
409
 
410
410
  from comtypes.automation import VARIANT
411
411
 
412
412
  # Empty array
413
- varr = numpy.zeros(value.shape, comtypes.npsupport.interop.VARIANT_dtype, order="F")
413
+ varr = numpy.zeros(value.shape, comtypes.npsupport.VARIANT_dtype, order="F")
414
414
  # Convert each value to a variant and put it in the array.
415
415
  varr.flat = [VARIANT(v) for v in value.flat]
416
416
  return varr
@@ -423,12 +423,12 @@ def _datetime64_ndarray_to_variant_array(value):
423
423
  # fractional days.
424
424
  from comtypes.automation import VT_DATE
425
425
 
426
- numpy = comtypes.npsupport.interop.numpy
426
+ numpy = comtypes.npsupport.numpy
427
427
  value = numpy.array(value, "datetime64[ns]")
428
- value = value - comtypes.npsupport.interop.com_null_date64
428
+ value = value - comtypes.npsupport.com_null_date64
429
429
  # Convert to days
430
430
  value = value / numpy.timedelta64(1, "D")
431
- varr = numpy.zeros(value.shape, comtypes.npsupport.interop.VARIANT_dtype, order="F")
431
+ varr = numpy.zeros(value.shape, comtypes.npsupport.VARIANT_dtype, order="F")
432
432
  varr["vt"] = VT_DATE
433
433
  varr["_"]["VT_R8"].flat = value.flat
434
434
  return varr
@@ -1,14 +1,13 @@
1
1
  import ctypes
2
- from ctypes import HRESULT, POINTER, OleDLL, byref, c_void_p
3
- from ctypes.wintypes import DWORD, LPVOID
2
+ from ctypes import HRESULT, POINTER, byref
4
3
  from typing import TYPE_CHECKING, Any, Optional, Type
5
4
 
6
5
  import comtypes
7
6
  import comtypes.client
8
7
  import comtypes.client.dynamic
9
8
  from comtypes import GUID, STDMETHOD, IUnknown
9
+ from comtypes import RevokeActiveObject as RevokeActiveObject
10
10
  from comtypes.automation import IDispatch
11
- from comtypes.GUID import REFCLSID
12
11
 
13
12
  if TYPE_CHECKING:
14
13
  from ctypes import _Pointer
@@ -64,41 +63,10 @@ class IClassFactory(IUnknown):
64
63
  # STDMETHOD(HRESULT, "AddConnection", [c_ulong, c_ulong]),
65
64
  # STDMETHOD(HRESULT, "ReleaseConnection", [c_ulong, c_ulong, c_ulong])]
66
65
 
67
- # The following code is untested:
68
-
69
- ACTIVEOBJECT_STRONG = 0x0
70
- ACTIVEOBJECT_WEAK = 0x1
71
-
72
- _oleaut32 = OleDLL("oleaut32")
73
-
74
- _RegisterActiveObject = _oleaut32.RegisterActiveObject
75
- _RegisterActiveObject.argtypes = [
76
- c_void_p,
77
- REFCLSID,
78
- DWORD,
79
- POINTER(DWORD),
80
- ]
81
- _RegisterActiveObject.restype = HRESULT
82
-
83
- _RevokeActiveObject = _oleaut32.RevokeActiveObject
84
- _RevokeActiveObject.argtypes = [
85
- DWORD,
86
- LPVOID,
87
- ]
88
- _RevokeActiveObject.restype = HRESULT
89
-
90
66
 
91
67
  def RegisterActiveObject(comobj: comtypes.COMObject, weak: bool = True) -> int:
68
+ """Registers a pointer as the active object for its class and returns the handle."""
92
69
  punk = comobj._com_pointers_[IUnknown._iid_]
93
70
  clsid = comobj._reg_clsid_
94
- if weak:
95
- flags = ACTIVEOBJECT_WEAK
96
- else:
97
- flags = ACTIVEOBJECT_STRONG
98
- handle = ctypes.c_ulong()
99
- _RegisterActiveObject(punk, byref(clsid), flags, byref(handle))
100
- return handle.value
101
-
102
-
103
- def RevokeActiveObject(handle: int) -> None:
104
- _RevokeActiveObject(handle, None)
71
+ flags = comtypes.ACTIVEOBJECT_WEAK if weak else comtypes.ACTIVEOBJECT_STRONG
72
+ return comtypes.RegisterActiveObject(punk, clsid, flags)
@@ -22,7 +22,7 @@ class VARIANTEnumerator(COMObject):
22
22
  items # keep, so that we can restore our iterator (in Reset, and Clone).
23
23
  )
24
24
  self.seq = iter(self.items)
25
- super(VARIANTEnumerator, self).__init__()
25
+ super().__init__()
26
26
 
27
27
  def Next(self, this, celt, rgVar, pCeltFetched):
28
28
  if not rgVar:
@@ -75,7 +75,7 @@ class COMCollection(COMObject):
75
75
  def __init__(self, itemtype, collection):
76
76
  self.collection = collection
77
77
  self.itemtype = itemtype
78
- super(COMCollection, self).__init__()
78
+ super().__init__()
79
79
 
80
80
  def _get_Item(self, this, pathname, pitem):
81
81
  if not pitem:
@@ -31,7 +31,7 @@ class ConnectionPointImpl(COMObject):
31
31
  def __init__(
32
32
  self, sink_interface: Type[IUnknown], sink_typeinfo: ITypeInfo
33
33
  ) -> None:
34
- super(ConnectionPointImpl, self).__init__()
34
+ super().__init__()
35
35
  self._connections: Dict[int, IUnknown] = {}
36
36
  self._cookie = 0
37
37
  self._sink_interface = sink_interface
@@ -109,7 +109,7 @@ class ConnectionPointImpl(COMObject):
109
109
  yield result
110
110
 
111
111
 
112
- class ConnectableObjectMixin(object):
112
+ class ConnectableObjectMixin:
113
113
  """Mixin which implements IConnectionPointContainer.
114
114
 
115
115
  Call Fire_Event(interface, methodname, *args, **kw) to fire an
@@ -122,7 +122,7 @@ class ConnectableObjectMixin(object):
122
122
  _reg_typelib_: ClassVar[Tuple[str, int, int]]
123
123
 
124
124
  def __init__(self) -> None:
125
- super(ConnectableObjectMixin, self).__init__()
125
+ super().__init__()
126
126
  self.__connections: Dict[Type[IDispatch], ConnectionPointImpl] = {}
127
127
 
128
128
  tlib = LoadRegTypeLib(*self._reg_typelib_)
@@ -22,7 +22,7 @@ class ClassFactory(COMObject):
22
22
  _com_interfaces_ = [IClassFactory]
23
23
 
24
24
  def __init__(self, cls: Type[COMObject]) -> None:
25
- super(ClassFactory, self).__init__()
25
+ super().__init__()
26
26
  self._cls = cls
27
27
 
28
28
  def IClassFactory_CreateInstance(
@@ -92,7 +92,7 @@ def _setup_logging(clsid: GUID) -> None:
92
92
 
93
93
  try:
94
94
  hkey = winreg.OpenKey(winreg.HKEY_CLASSES_ROOT, r"CLSID\%s\Logging" % clsid)
95
- except WindowsError:
95
+ except OSError:
96
96
  return
97
97
  from comtypes.logutil import NTDebugHandler
98
98
 
@@ -1,11 +1,12 @@
1
1
  import logging
2
2
  import queue
3
- from ctypes import HRESULT, POINTER, OleDLL, byref, c_ulong, c_void_p
3
+ from ctypes import HRESULT, OleDLL, byref, c_ulong, c_void_p
4
4
  from ctypes.wintypes import DWORD, LPDWORD
5
5
  from typing import TYPE_CHECKING, Any, Literal, Optional, Sequence, Type
6
6
 
7
7
  import comtypes
8
8
  from comtypes import GUID, COMObject, IUnknown, hresult
9
+ from comtypes.GUID import REFCLSID
9
10
  from comtypes.server import IClassFactory
10
11
 
11
12
  if TYPE_CHECKING:
@@ -23,7 +24,6 @@ REGCLS_SURROGATE = 8 # must be used when a surrogate process
23
24
 
24
25
  _ole32 = OleDLL("ole32")
25
26
 
26
- REFCLSID = POINTER(GUID)
27
27
  _CoRegisterClassObject = _ole32.CoRegisterClassObject
28
28
  _CoRegisterClassObject.argtypes = [REFCLSID, c_void_p, DWORD, DWORD, LPDWORD]
29
29
  _CoRegisterClassObject.restype = HRESULT
@@ -45,7 +45,7 @@ class ClassFactory(COMObject):
45
45
  regcls: int = REGCLS_MULTIPLEUSE
46
46
 
47
47
  def __init__(self, cls: Type[COMObject], *args, **kw) -> None:
48
- super(ClassFactory, self).__init__()
48
+ super().__init__()
49
49
  self._cls = cls
50
50
  self._register_class()
51
51
  self._args = args
@@ -105,7 +105,7 @@ def _delete_key(hkey: int, subkey: str, *, force: bool) -> None:
105
105
  else:
106
106
  _debug("DeleteKey %s\\%s", _explain(hkey), subkey)
107
107
  winreg.DeleteKey(hkey, subkey)
108
- except WindowsError as detail:
108
+ except OSError as detail:
109
109
  if get_winerror(detail) != 2:
110
110
  raise
111
111
 
@@ -113,7 +113,7 @@ def _delete_key(hkey: int, subkey: str, *, force: bool) -> None:
113
113
  _Entry = Tuple[int, str, str, str]
114
114
 
115
115
 
116
- class Registrar(object):
116
+ class Registrar:
117
117
  """COM class registration.
118
118
 
119
119
  The COM class can override what this does by implementing
@@ -142,7 +142,7 @@ class Registrar(object):
142
142
  _debug('DeleteKey( %s\\CLSID\\%s\\Logging"' % (_explain(HKCR), clsid))
143
143
  hkey = winreg.OpenKey(HKCR, rf"CLSID\{clsid}")
144
144
  winreg.DeleteKey(hkey, "Logging")
145
- except WindowsError as detail:
145
+ except OSError as detail:
146
146
  if get_winerror(detail) != 2:
147
147
  raise
148
148
 
@@ -166,7 +166,7 @@ class Registrar(object):
166
166
  _debug("DeleteValue(format)")
167
167
  try:
168
168
  winreg.DeleteValue(hkey, "format")
169
- except WindowsError as detail:
169
+ except OSError as detail:
170
170
  if get_winerror(detail) != 2:
171
171
  raise
172
172
 
@@ -231,7 +231,7 @@ class Registrar(object):
231
231
  try:
232
232
  _debug("UnRegisterTypeLib(%s, %s, %s)", *tlib)
233
233
  UnRegisterTypeLib(*tlib)
234
- except WindowsError as detail:
234
+ except OSError as detail:
235
235
  if not get_winerror(detail) in (
236
236
  TYPE_E_REGISTRYACCESS,
237
237
  TYPE_E_CANTLOADLIBRARY,
@@ -12,7 +12,7 @@ from comtypes.test import ResourceDenied
12
12
 
13
13
  try:
14
14
  GUID.from_progid("Agilent546XX.Agilent546XX")
15
- except WindowsError:
15
+ except OSError:
16
16
  pass
17
17
 
18
18
  else:
@@ -26,7 +26,7 @@ class Test_Dispatch_Function(ut.TestCase):
26
26
 
27
27
  def test_returns_dynamic_Dispatch_if_takes_ptrIDispatch_and_raised_winerr(self):
28
28
  obj = mock.MagicMock(spec=ctypes.POINTER(automation.IDispatch))
29
- obj.GetTypeInfo.side_effect = WindowsError()
29
+ obj.GetTypeInfo.side_effect = OSError()
30
30
  self.assertIsInstance(dynamic.Dispatch(obj), dynamic._Dispatch)
31
31
 
32
32
  def test_returns_what_is_took_if_takes_other(self):
@@ -1,4 +1,5 @@
1
1
  import doctest
2
+ import sys
2
3
  import unittest
3
4
  from ctypes import pointer
4
5
  from typing import Any
@@ -22,7 +23,7 @@ except ImportError:
22
23
  def setUpModule():
23
24
  try:
24
25
  register(comtypes.test.TestComServer.TestComServer)
25
- except WindowsError as e:
26
+ except OSError as e:
26
27
  if e.winerror != 5: # [Error 5] Access is denied
27
28
  raise e
28
29
  raise unittest.SkipTest(
@@ -35,7 +36,7 @@ def tearDownModule():
35
36
  unregister(comtypes.test.TestComServer.TestComServer)
36
37
 
37
38
 
38
- class BaseServerTest(object):
39
+ class BaseServerTest:
39
40
  def create_object(self) -> Any: ...
40
41
 
41
42
  def _find_memleak(self, func):
@@ -116,6 +117,11 @@ class TestInproc(BaseServerTest, unittest.TestCase):
116
117
  "TestComServerLib.TestComServer", clsctx=comtypes.CLSCTX_INPROC_SERVER
117
118
  )
118
119
 
120
+ @unittest.skip("Fails occasionally with a memory leak on INPROC.")
121
+ def test_eval(self):
122
+ # This test sometimes leaks memory when run as an in-process server.
123
+ pass
124
+
119
125
 
120
126
  class TestLocalServer(BaseServerTest, unittest.TestCase):
121
127
  def create_object(self):
@@ -135,6 +141,13 @@ class TestInproc_win32com(BaseServerTest, unittest.TestCase):
135
141
  def create_object(self):
136
142
  return Dispatch("TestComServerLib.TestComServer")
137
143
 
144
+ if sys.version_info >= (3, 14):
145
+
146
+ @unittest.skip("Fails occasionally with a memory leak on INPROC.")
147
+ def test_eval(self):
148
+ # This test sometimes leaks memory when run as an in-process server.
149
+ pass
150
+
138
151
  # These tests make no sense with win32com, override to disable them:
139
152
  @unittest.skip("This test make no sense with win32com.")
140
153
  def test_get_typeinfo(self):
@@ -51,7 +51,7 @@ def add_test(fname):
51
51
  def test(self):
52
52
  try:
53
53
  comtypes.typeinfo.LoadTypeLibEx(fname)
54
- except WindowsError:
54
+ except OSError:
55
55
  return
56
56
  comtypes.client.GetModule(fname)
57
57
 
@@ -1,5 +1,3 @@
1
- # coding: utf-8
2
-
3
1
  import unittest
4
2
  from ctypes import byref, pointer
5
3
 
@@ -1,5 +1,3 @@
1
- # coding: utf-8
2
-
3
1
  import unittest
4
2
  from ctypes import byref, c_double, pointer
5
3
 
@@ -16,7 +16,7 @@ except ImportError:
16
16
  def setUpModule():
17
17
  try:
18
18
  register(comtypes.test.TestDispServer.TestDispServer)
19
- except WindowsError as e:
19
+ except OSError as e:
20
20
  if e.winerror != 5: # [Error 5] Access is denied
21
21
  raise e
22
22
  raise unittest.SkipTest(
@@ -1,5 +1,3 @@
1
- # -*- coding: latin-1 -*-
2
-
3
1
  import datetime
4
2
  import sys
5
3
  import unittest
@@ -26,7 +24,7 @@ except (ImportError, OSError):
26
24
  IMPORT_FAILED = True
27
25
 
28
26
 
29
- class BaseBindTest(object):
27
+ class BaseBindTest:
30
28
  # `dynamic = True/False` must be defined in subclasses!
31
29
  dynamic: ClassVar[bool]
32
30
 
@@ -127,8 +125,7 @@ PY_VER = "Python {0}.{1}.{2}".format(*sys.version_info[:3])
127
125
 
128
126
  @unittest.skipIf(IMPORT_FAILED, "This depends on Excel.")
129
127
  @unittest.skipIf(
130
- sys.version_info[:2] == (3, 8)
131
- or sys.version_info[:2] == (3, 9)
128
+ sys.version_info[:2] == (3, 9)
132
129
  or (sys.version_info[:2] == (3, 10) and sys.version_info < (3, 10, 10))
133
130
  or (sys.version_info[:2] == (3, 11) and sys.version_info < (3, 11, 2)),
134
131
  f"This fails in {PY_VER}. See https://github.com/enthought/comtypes/issues/212",