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,10 +1,11 @@
1
- import ctypes
2
1
  import logging
3
2
  import sys
4
3
  import winreg
4
+ from ctypes import c_void_p, pointer
5
5
  from typing import TYPE_CHECKING, Any, Literal, Optional, Type
6
6
 
7
7
  from comtypes import GUID, COMObject, IUnknown, hresult
8
+ from comtypes._comobject import InprocServer as _InprocRefCounter
8
9
  from comtypes.server import IClassFactory
9
10
 
10
11
  if TYPE_CHECKING:
@@ -21,7 +22,7 @@ class ClassFactory(COMObject):
21
22
  _com_interfaces_ = [IClassFactory]
22
23
 
23
24
  def __init__(self, cls: Type[COMObject]) -> None:
24
- super(ClassFactory, self).__init__()
25
+ super().__init__()
25
26
  self._cls = cls
26
27
 
27
28
  def IClassFactory_CreateInstance(
@@ -29,7 +30,7 @@ class ClassFactory(COMObject):
29
30
  this: Any,
30
31
  punkOuter: Optional[Type["_Pointer[IUnknown]"]],
31
32
  riid: "_Pointer[GUID]",
32
- ppv: ctypes.c_void_p,
33
+ ppv: c_void_p,
33
34
  ) -> int:
34
35
  _debug("ClassFactory.CreateInstance(%s)", riid[0])
35
36
  result = self._cls().IUnknown_QueryInterface(None, riid, ppv)
@@ -37,6 +38,7 @@ class ClassFactory(COMObject):
37
38
  return result
38
39
 
39
40
  def IClassFactory_LockServer(self, this: Any, fLock: bool) -> Literal[0]:
41
+ assert COMObject.__server__ is not None, "The inprocserver is not running yet"
40
42
  if fLock:
41
43
  COMObject.__server__.Lock()
42
44
  else:
@@ -58,7 +60,7 @@ def inproc_find_class(clsid: GUID) -> Type[COMObject]:
58
60
  except:
59
61
  _debug("NO path to insert")
60
62
  else:
61
- if not pathdir in sys.path:
63
+ if pathdir not in sys.path:
62
64
  sys.path.insert(0, str(pathdir))
63
65
  _debug("insert path %r", pathdir)
64
66
  else:
@@ -90,7 +92,7 @@ def _setup_logging(clsid: GUID) -> None:
90
92
 
91
93
  try:
92
94
  hkey = winreg.OpenKey(winreg.HKEY_CLASSES_ROOT, r"CLSID\%s\Logging" % clsid)
93
- except WindowsError:
95
+ except OSError:
94
96
  return
95
97
  from comtypes.logutil import NTDebugHandler
96
98
 
@@ -138,7 +140,7 @@ def DllGetClassObject(rclsid: int, riid: int, ppv: int) -> int:
138
140
  return hresult.CLASS_E_CLASSNOTAVAILABLE
139
141
 
140
142
  result = ClassFactory(cls).IUnknown_QueryInterface(
141
- None, ctypes.pointer(iid), ctypes.c_void_p(ppv)
143
+ None, pointer(iid), c_void_p(ppv)
142
144
  )
143
145
  _debug("DllGetClassObject() -> %s", result)
144
146
  return result
@@ -149,7 +151,8 @@ def DllGetClassObject(rclsid: int, riid: int, ppv: int) -> int:
149
151
 
150
152
  def DllCanUnloadNow() -> Literal[1]: # S_FALSE
151
153
  COMObject.__run_inprocserver__()
152
- result = COMObject.__server__.DllCanUnloadNow()
154
+ assert isinstance(COMObject.__server__, _InprocRefCounter)
155
+ result = COMObject.__server__.DllCanUnloadNow() # noqa
153
156
  # To avoid a memory leak when PyInitialize()/PyUninitialize() are
154
157
  # called several times, we refuse to unload the dll.
155
158
  return hresult.S_FALSE
@@ -1,18 +1,12 @@
1
1
  import logging
2
2
  import queue
3
- from ctypes import (
4
- HRESULT,
5
- POINTER,
6
- OleDLL,
7
- byref,
8
- c_ulong,
9
- c_void_p,
10
- )
3
+ from ctypes import HRESULT, OleDLL, byref, c_ulong, c_void_p
11
4
  from ctypes.wintypes import DWORD, LPDWORD
12
5
  from typing import TYPE_CHECKING, Any, Literal, Optional, Sequence, Type
13
6
 
14
7
  import comtypes
15
- from comtypes import GUID, hresult
8
+ from comtypes import GUID, COMObject, IUnknown, hresult
9
+ from comtypes.GUID import REFCLSID
16
10
  from comtypes.server import IClassFactory
17
11
 
18
12
  if TYPE_CHECKING:
@@ -30,7 +24,6 @@ REGCLS_SURROGATE = 8 # must be used when a surrogate process
30
24
 
31
25
  _ole32 = OleDLL("ole32")
32
26
 
33
- REFCLSID = POINTER(GUID)
34
27
  _CoRegisterClassObject = _ole32.CoRegisterClassObject
35
28
  _CoRegisterClassObject.argtypes = [REFCLSID, c_void_p, DWORD, DWORD, LPDWORD]
36
29
  _CoRegisterClassObject.restype = HRESULT
@@ -40,19 +33,19 @@ _CoRevokeClassObject.argtypes = [DWORD]
40
33
  _CoRevokeClassObject.restype = HRESULT
41
34
 
42
35
 
43
- def run(classes: Sequence[Type[comtypes.COMObject]]) -> None:
36
+ def run(classes: Sequence[Type[COMObject]]) -> None:
44
37
  classobjects = [ClassFactory(cls) for cls in classes]
45
- comtypes.COMObject.__run_localserver__(classobjects)
38
+ COMObject.__run_localserver__(classobjects)
46
39
 
47
40
 
48
- class ClassFactory(comtypes.COMObject):
41
+ class ClassFactory(COMObject):
49
42
  _com_interfaces_ = [IClassFactory]
50
43
  _locks: int = 0
51
44
  _queue: Optional[queue.Queue] = None
52
45
  regcls: int = REGCLS_MULTIPLEUSE
53
46
 
54
- def __init__(self, cls: Type[comtypes.COMObject], *args, **kw) -> None:
55
- super(ClassFactory, self).__init__()
47
+ def __init__(self, cls: Type[COMObject], *args, **kw) -> None:
48
+ super().__init__()
56
49
  self._cls = cls
57
50
  self._register_class()
58
51
  self._args = args
@@ -67,11 +60,11 @@ class ClassFactory(comtypes.COMObject):
67
60
  def _register_class(self) -> None:
68
61
  regcls = getattr(self._cls, "_regcls_", self.regcls)
69
62
  cookie = c_ulong()
70
- ptr = self._com_pointers_[comtypes.IUnknown._iid_]
71
- clsctx = self._cls._reg_clsctx_
63
+ ptr = self._com_pointers_[IUnknown._iid_]
64
+ clsctx = self._cls._reg_clsctx_ # type: ignore
72
65
  clsctx &= ~comtypes.CLSCTX_INPROC # reset the inproc flags
73
66
  _CoRegisterClassObject(
74
- byref(comtypes.GUID(self._cls._reg_clsid_)),
67
+ byref(GUID(self._cls._reg_clsid_)),
75
68
  ptr,
76
69
  clsctx,
77
70
  regcls,
@@ -85,8 +78,8 @@ class ClassFactory(comtypes.COMObject):
85
78
  def CreateInstance(
86
79
  self,
87
80
  this: Any,
88
- punkOuter: Optional[Type["_Pointer[comtypes.IUnknown]"]],
89
- riid: "_Pointer[comtypes.GUID]",
81
+ punkOuter: Optional[Type["_Pointer[IUnknown]"]],
82
+ riid: "_Pointer[GUID]",
90
83
  ppv: c_void_p,
91
84
  ) -> int:
92
85
  _debug("ClassFactory.CreateInstance(%s)", riid[0])
@@ -96,8 +89,9 @@ class ClassFactory(comtypes.COMObject):
96
89
  return result
97
90
 
98
91
  def LockServer(self, this: Any, fLock: bool) -> Literal[0]:
92
+ assert COMObject.__server__ is not None, "The localserver is not running yet"
99
93
  if fLock:
100
- comtypes.COMObject.__server__.Lock()
94
+ COMObject.__server__.Lock()
101
95
  else:
102
- comtypes.COMObject.__server__.Unlock()
96
+ COMObject.__server__.Unlock()
103
97
  return hresult.S_OK
@@ -43,7 +43,7 @@ import os
43
43
  import sys
44
44
  import winreg
45
45
  from ctypes import WinDLL, WinError
46
- from ctypes.wintypes import HKEY, LONG, LPCWSTR
46
+ from ctypes.wintypes import HKEY, LONG, LPCWSTR, MAX_PATH
47
47
  from typing import Iterable, Iterator, List, Optional, Tuple, Type, Union
48
48
  from winreg import HKEY_CLASSES_ROOT as HKCR
49
49
  from winreg import HKEY_CURRENT_USER as HKCU
@@ -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,
@@ -242,7 +242,7 @@ class Registrar(object):
242
242
 
243
243
  def _get_serverdll(handle: int) -> str:
244
244
  """Return the pathname of the dll hosting the COM object."""
245
- return GetModuleFileName(handle, 260)
245
+ return GetModuleFileName(handle, MAX_PATH)
246
246
 
247
247
 
248
248
  class RegistryEntries(abc.ABC):
@@ -30,25 +30,24 @@ class Test(unittest.TestCase):
30
30
  )
31
31
 
32
32
  def test_invalid_constructor_arg(self):
33
- self.assertRaises(WindowsError, GUID, "abc")
33
+ with self.assertRaises(WindowsError):
34
+ GUID("abc")
34
35
 
35
36
  def test_from_progid(self):
36
37
  self.assertEqual(
37
38
  GUID.from_progid("Scripting.FileSystemObject"),
38
39
  GUID("{0D43FE01-F093-11CF-8940-00A0C9054228}"),
39
40
  )
40
- self.assertRaises(WindowsError, GUID.from_progid, "abc")
41
+ with self.assertRaises(WindowsError):
42
+ GUID.from_progid("abc")
41
43
 
42
44
  def test_as_progid(self):
43
45
  self.assertEqual(
44
46
  GUID("{0D43FE01-F093-11CF-8940-00A0C9054228}").as_progid(),
45
47
  "Scripting.FileSystemObject",
46
48
  )
47
- self.assertRaises(
48
- WindowsError,
49
- lambda guid: guid.as_progid(),
50
- GUID("{00000000-0000-0000-C000-000000000046}"),
51
- )
49
+ with self.assertRaises(WindowsError):
50
+ GUID("{00000000-0000-0000-C000-000000000046}").as_progid()
52
51
 
53
52
  def test_create_new(self):
54
53
  self.assertNotEqual(GUID.create_new(), GUID.create_new())
@@ -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:
@@ -61,7 +61,8 @@ class BasicTest(ut.TestCase):
61
61
  self.assertEqual(method_count(IMyInterface), 3)
62
62
 
63
63
  # assigning _methods_ does not work until we have an _iid_!
64
- self.assertRaises(AttributeError, setattr, IMyInterface, "_methods_", [])
64
+ with self.assertRaises(AttributeError):
65
+ setattr(IMyInterface, "_methods_", [])
65
66
  IMyInterface._iid_ = GUID.create_new()
66
67
  IMyInterface._methods_ = []
67
68
  self.assertEqual(method_count(IMyInterface), 3)
@@ -96,9 +97,11 @@ class BasicTest(ut.TestCase):
96
97
  _iid_ = GUID.create_new()
97
98
 
98
99
  # We cannot assign _methods_ to IDerived before IBase has it's _methods_:
99
- self.assertRaises(TypeError, lambda: setattr(IDerived, "_methods_", []))
100
+ with self.assertRaises(TypeError):
101
+ setattr(IDerived, "_methods_", [])
100
102
  # Make sure that setting _methods_ failed completely.
101
- self.assertRaises(KeyError, lambda: IDerived.__dict__["_methods_"])
103
+ with self.assertRaises(KeyError):
104
+ IDerived.__dict__["_methods_"]
102
105
  IBase._methods_ = []
103
106
  # Now it works:
104
107
  IDerived._methods_ = []
@@ -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):
@@ -60,7 +60,8 @@ class Test(unittest.TestCase):
60
60
 
61
61
  # slicing is not (yet?) supported
62
62
  cv.Reset()
63
- self.assertRaises(ArgumentError, lambda: cv[:])
63
+ with self.assertRaises(ArgumentError):
64
+ cv[:]
64
65
 
65
66
  @unittest.skip("This test takes a long time. Do we need it? Can it be rewritten?")
66
67
  def test_leaks_1(self):
@@ -151,10 +152,12 @@ class TestCollectionInterface(unittest.TestCase):
151
152
  self.assertAccessInterface(d)
152
153
 
153
154
  def test_named_property_no_length(self):
154
- self.assertRaises(TypeError, len, self.d.Item)
155
+ with self.assertRaises(TypeError):
156
+ len(self.d.Item)
155
157
 
156
158
  def test_named_property_not_iterable(self):
157
- self.assertRaises(TypeError, list, self.d.Item)
159
+ with self.assertRaises(TypeError):
160
+ list(self.d.Item)
158
161
 
159
162
 
160
163
  if __name__ == "__main__":
@@ -4,9 +4,10 @@ from ctypes import POINTER, byref, pointer
4
4
  from unittest import mock
5
5
 
6
6
  import comtypes.client
7
- from comtypes import CLSCTX_SERVER, COMObject, IUnknown, hresult
7
+ from comtypes import CLSCTX_SERVER, COMObject, IPersist, IUnknown, hresult
8
8
  from comtypes._post_coinit.misc import _CoCreateInstance
9
9
  from comtypes.automation import IDispatch
10
+ from comtypes.typeinfo import GUIDKIND_DEFAULT_SOURCE_DISP_IID
10
11
 
11
12
  comtypes.client.GetModule("UIAutomationCore.dll")
12
13
  comtypes.client.GetModule("scrrun.dll")
@@ -131,11 +132,9 @@ class Test_IProvideClassInfo_GetClassInfo(ut.TestCase):
131
132
 
132
133
  class Test_IProvideClassInfo2_GetGUID(ut.TestCase):
133
134
  def test(self):
134
- # GUIDKIND_DEFAULT_SOURCE_DISP_IID = 1
135
- self.assertEqual(
136
- stdole.StdFont().IProvideClassInfo2_GetGUID(1),
137
- stdole.FontEvents._iid_,
138
- )
135
+ obj = stdole.StdFont()
136
+ actual = obj.IProvideClassInfo2_GetGUID(GUIDKIND_DEFAULT_SOURCE_DISP_IID)
137
+ self.assertEqual(actual, stdole.FontEvents._iid_)
139
138
 
140
139
 
141
140
  class Test_IPersist_GetClassID(ut.TestCase):
@@ -144,3 +143,17 @@ class Test_IPersist_GetClassID(ut.TestCase):
144
143
  uiac.CUIAutomation().IPersist_GetClassID(),
145
144
  uiac.CUIAutomation._reg_clsid_,
146
145
  )
146
+
147
+
148
+ class Test_Vtbl(ut.TestCase):
149
+ def test_com_pointers(self):
150
+ stdpic = stdole.StdPicture()
151
+ cuia = uiac.CUIAutomation()
152
+ self.assertIs(
153
+ type(stdpic._com_pointers_[IPersist._iid_]),
154
+ type(cuia._com_pointers_[IPersist._iid_]),
155
+ )
156
+ self.assertIn(IDispatch._iid_, stdpic._com_pointers_)
157
+ self.assertNotIn(IDispatch._iid_, cuia._com_pointers_)
158
+ self.assertIn(stdole.IPictureDisp._iid_, stdpic._com_pointers_)
159
+ self.assertIn(uiac.IUIAutomation._iid_, cuia._com_pointers_)
@@ -5,7 +5,7 @@ from typing import Any
5
5
 
6
6
  import comtypes.server
7
7
  import comtypes.test.TestComServer
8
- from comtypes import BSTR
8
+ from comtypes import BSTR, errorinfo, hresult, shelllink
9
9
  from comtypes.automation import VARIANT, _midlSAFEARRAY
10
10
  from comtypes.client import CreateObject, GetActiveObject
11
11
  from comtypes.server.register import register, unregister
@@ -22,7 +22,7 @@ except ImportError:
22
22
  def setUpModule():
23
23
  try:
24
24
  register(comtypes.test.TestComServer.TestComServer)
25
- except WindowsError as e:
25
+ except OSError as e:
26
26
  if e.winerror != 5: # [Error 5] Access is denied
27
27
  raise e
28
28
  raise unittest.SkipTest(
@@ -35,7 +35,7 @@ def tearDownModule():
35
35
  unregister(comtypes.test.TestComServer.TestComServer)
36
36
 
37
37
 
38
- class BaseServerTest(object):
38
+ class BaseServerTest:
39
39
  def create_object(self) -> Any: ...
40
40
 
41
41
  def _find_memleak(self, func):
@@ -116,6 +116,11 @@ class TestInproc(BaseServerTest, unittest.TestCase):
116
116
  "TestComServerLib.TestComServer", clsctx=comtypes.CLSCTX_INPROC_SERVER
117
117
  )
118
118
 
119
+ @unittest.skip("Fails occasionally with a memory leak on INPROC.")
120
+ def test_eval(self):
121
+ # This test sometimes leaks memory when run as an in-process server.
122
+ pass
123
+
119
124
 
120
125
  class TestLocalServer(BaseServerTest, unittest.TestCase):
121
126
  def create_object(self):
@@ -201,6 +206,26 @@ class ActiveObjTest(unittest.TestCase):
201
206
  self._doit(weak=False)
202
207
 
203
208
 
209
+ class SupportErrorInfoTest(unittest.TestCase):
210
+ def create_object(self):
211
+ return CreateObject(
212
+ comtypes.test.TestComServer.TestComServer,
213
+ interface=comtypes.test.TestComServer.ITestComServer,
214
+ )
215
+
216
+ def test_returns_S_OK(self):
217
+ psei = self.create_object().QueryInterface(errorinfo.ISupportErrorInfo)
218
+ iid = comtypes.test.TestComServer.ITestComServer._iid_
219
+ hr = psei.InterfaceSupportsErrorInfo(iid)
220
+ self.assertEqual(hr, hresult.S_OK)
221
+
222
+ def test_returns_S_FALSE(self):
223
+ psei = self.create_object().QueryInterface(errorinfo.ISupportErrorInfo)
224
+ iid = shelllink.IShellLinkW._iid_
225
+ hr = psei.InterfaceSupportsErrorInfo(iid)
226
+ self.assertEqual(hr, hresult.S_FALSE)
227
+
228
+
204
229
  class VariantTest(unittest.TestCase):
205
230
  def test_UDT(self):
206
231
  from comtypes.gen.TestComServerLib import MYCOLOR
@@ -277,7 +302,10 @@ class TestEvents(unittest.TestCase):
277
302
  import comtypes.test.test_comserver
278
303
 
279
304
  doctest.testmod(
280
- comtypes.test.test_comserver, verbose=False, optionflags=doctest.ELLIPSIS
305
+ comtypes.test.test_comserver,
306
+ verbose=False,
307
+ optionflags=doctest.ELLIPSIS,
308
+ raise_on_error=True,
281
309
  )
282
310
 
283
311
 
@@ -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
 
@@ -14,7 +14,8 @@ class Test(unittest.TestCase):
14
14
 
15
15
  # Count is a normal propget, no propput
16
16
  self.assertEqual(d.Count, 0)
17
- self.assertRaises(AttributeError, lambda: setattr(d, "Count", -1))
17
+ with self.assertRaises(AttributeError):
18
+ setattr(d, "Count", -1)
18
19
 
19
20
  # HashVal is a 'named' propget, no propput
20
21
  ##d.HashVal
@@ -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(
@@ -66,10 +66,12 @@ class Test(unittest.TestCase):
66
66
  self.assertEqual(d3.Item["baz"], 3.14)
67
67
 
68
68
  def test_named_property_no_length(self):
69
- self.assertRaises(TypeError, len, self.d.Item)
69
+ with self.assertRaises(TypeError):
70
+ len(self.d.Item)
70
71
 
71
72
  def test_named_property_not_iterable(self):
72
- self.assertRaises(TypeError, list, self.d.Item)
73
+ with self.assertRaises(TypeError):
74
+ list(self.d.Item)
73
75
 
74
76
  def assertAccessInterface(self, d):
75
77
  """Asserts access via indexing and named property"""
@@ -0,0 +1,115 @@
1
+ import unittest as ut
2
+
3
+ from comtypes import errorinfo, shelllink
4
+ from comtypes import hresult as hres
5
+
6
+
7
+ class Test_GetErrorInfo(ut.TestCase):
8
+ def test_error_has_been_set(self):
9
+ self.assertIsNone(errorinfo.GetErrorInfo())
10
+ errmsg = "sample unexpected error message for tests"
11
+ errcode = hres.E_UNEXPECTED
12
+ helpcontext = 123
13
+ hr = errorinfo.ReportError(
14
+ errmsg,
15
+ shelllink.IShellLinkW._iid_,
16
+ str(shelllink.ShellLink._reg_clsid_),
17
+ helpfile="help.chm",
18
+ helpcontext=helpcontext,
19
+ hresult=errcode,
20
+ )
21
+ self.assertEqual(errcode, hr)
22
+ pei = errorinfo.GetErrorInfo()
23
+ self.assertIsNotNone(pei)
24
+ assert pei is not None # for static type guard
25
+ self.assertEqual(shelllink.IShellLinkW._iid_, pei.GetGUID())
26
+ self.assertEqual("lnkfile", pei.GetSource())
27
+ self.assertEqual(errmsg, pei.GetDescription())
28
+ self.assertEqual("help.chm", pei.GetHelpFile())
29
+ self.assertEqual(helpcontext, pei.GetHelpContext())
30
+ # Calling `GetErrorInfo` clears the error state for the thread.
31
+ # Therefore, `None` is returned in the second call.
32
+ self.assertIsNone(errorinfo.GetErrorInfo())
33
+
34
+ def test_without_optional_args(self):
35
+ self.assertIsNone(errorinfo.GetErrorInfo())
36
+ errmsg = "sample unexpected error message for tests"
37
+ hr = errorinfo.ReportError(errmsg, shelllink.IShellLinkW._iid_)
38
+ self.assertEqual(hres.DISP_E_EXCEPTION, hr)
39
+ pei = errorinfo.GetErrorInfo()
40
+ self.assertIsNotNone(pei)
41
+ assert pei is not None # for static type guard
42
+ self.assertEqual(shelllink.IShellLinkW._iid_, pei.GetGUID())
43
+ self.assertIsNone(pei.GetSource())
44
+ self.assertEqual(errmsg, pei.GetDescription())
45
+ self.assertIsNone(pei.GetHelpFile())
46
+ self.assertEqual(0, pei.GetHelpContext())
47
+
48
+ def test_error_has_not_been_set(self):
49
+ self.assertIsNone(errorinfo.GetErrorInfo())
50
+ pei = errorinfo.GetErrorInfo()
51
+ self.assertIsNone(pei)
52
+
53
+
54
+ def raise_runtime_error():
55
+ _raise_runtime_error()
56
+
57
+
58
+ def _raise_runtime_error():
59
+ raise RuntimeError("for testing")
60
+
61
+
62
+ class Test_ReportException(ut.TestCase):
63
+ def test_without_stacklevel(self):
64
+ self.assertIsNone(errorinfo.GetErrorInfo())
65
+ iid = shelllink.IShellLinkW._iid_
66
+ try:
67
+ raise_runtime_error()
68
+ except RuntimeError:
69
+ hr = errorinfo.ReportException(hres.E_UNEXPECTED, iid)
70
+ self.assertEqual(hres.E_UNEXPECTED, hr)
71
+ pei = errorinfo.GetErrorInfo()
72
+ self.assertIsNotNone(pei)
73
+ assert pei is not None # for static type guard
74
+ self.assertEqual(shelllink.IShellLinkW._iid_, pei.GetGUID())
75
+ self.assertIsNone(pei.GetSource())
76
+ self.assertEqual("<class 'RuntimeError'>: for testing", pei.GetDescription())
77
+ self.assertIsNone(pei.GetHelpFile())
78
+ self.assertEqual(0, pei.GetHelpContext())
79
+ self.assertIsNone(errorinfo.GetErrorInfo())
80
+
81
+ def test_with_stacklevel(self):
82
+ self.assertIsNone(errorinfo.GetErrorInfo())
83
+ stem = "<class 'RuntimeError'>: for testing"
84
+ iid = shelllink.IShellLinkW._iid_
85
+ for slv, text in [
86
+ # XXX: If the codebase changes, the line where functions or
87
+ # methods are defined will change, meaning this test is brittle.
88
+ (0, f"{stem} ({__name__}, line 96)"),
89
+ (1, f"{stem} ({__name__}, line 55)"),
90
+ (2, f"{stem} ({__name__}, line 59)"),
91
+ ]:
92
+ with self.subTest(text=text):
93
+ try:
94
+ raise_runtime_error()
95
+ except RuntimeError:
96
+ errorinfo.ReportException(hres.E_UNEXPECTED, iid, stacklevel=slv)
97
+ pei = errorinfo.GetErrorInfo()
98
+ assert pei is not None # for static type guard
99
+ self.assertEqual(text, pei.GetDescription())
100
+ self.assertIsNone(errorinfo.GetErrorInfo())
101
+
102
+ def test_with_over_stacklevel(self):
103
+ self.assertIsNone(errorinfo.GetErrorInfo())
104
+ iid = shelllink.IShellLinkW._iid_
105
+ try:
106
+ raise_runtime_error()
107
+ except RuntimeError:
108
+ with self.assertRaises(ValueError):
109
+ errorinfo.ReportException(hres.E_UNEXPECTED, iid, stacklevel=4)
110
+
111
+ def test_with_no_error_and_zero_stacklevel(self):
112
+ self.assertIsNone(errorinfo.GetErrorInfo())
113
+ iid = shelllink.IShellLinkW._iid_
114
+ with self.assertRaises(ValueError):
115
+ errorinfo.ReportException(hres.E_UNEXPECTED, iid, stacklevel=0)
@@ -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