comtypes 1.4.10__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 (145) hide show
  1. {comtypes-1.4.10 → comtypes-1.4.11}/CHANGES.txt +22 -0
  2. {comtypes-1.4.10/comtypes.egg-info → comtypes-1.4.11}/PKG-INFO +3 -2
  3. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/__init__.py +4 -4
  4. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/_comobject.py +23 -25
  5. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/_memberspec.py +100 -74
  6. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/_meta.py +1 -1
  7. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/_post_coinit/_cominterface_meta_patcher.py +3 -5
  8. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/_post_coinit/unknwn.py +29 -20
  9. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/_vtbl.py +52 -55
  10. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/automation.py +9 -10
  11. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/client/_code_cache.py +9 -23
  12. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/client/_events.py +87 -49
  13. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/client/_generate.py +0 -2
  14. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/connectionpoints.py +37 -3
  15. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/errorinfo.py +53 -15
  16. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/hints.pyi +15 -2
  17. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/hresult.py +16 -6
  18. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/messageloop.py +14 -12
  19. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/server/connectionpoints.py +68 -67
  20. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/server/inprocserver.py +8 -5
  21. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/server/localserver.py +14 -20
  22. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/server/register.py +2 -2
  23. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_GUID.py +6 -7
  24. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_basic.py +6 -3
  25. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_collections.py +6 -3
  26. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_comobject.py +19 -6
  27. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_comserver.py +25 -2
  28. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_dict.py +2 -1
  29. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_dyndispatch.py +4 -2
  30. comtypes-1.4.11/comtypes/test/test_errorinfo.py +115 -0
  31. comtypes-1.4.11/comtypes/test/test_hresult.py +48 -0
  32. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_inout_args.py +9 -2
  33. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_safearray.py +2 -1
  34. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_server_register.py +2 -1
  35. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_typeinfo.py +19 -2
  36. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_variant.py +2 -1
  37. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_w_getopt.py +4 -4
  38. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/tools/tlbparser.py +7 -6
  39. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/typeinfo.py +14 -9
  40. {comtypes-1.4.10 → comtypes-1.4.11/comtypes.egg-info}/PKG-INFO +3 -2
  41. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes.egg-info/SOURCES.txt +2 -0
  42. {comtypes-1.4.10 → comtypes-1.4.11}/pyproject.toml +1 -6
  43. {comtypes-1.4.10 → comtypes-1.4.11}/LICENSE.txt +0 -0
  44. {comtypes-1.4.10 → comtypes-1.4.11}/MANIFEST.in +0 -0
  45. {comtypes-1.4.10 → comtypes-1.4.11}/README.md +0 -0
  46. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/GUID.py +0 -0
  47. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/_npsupport.py +0 -0
  48. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/_post_coinit/__init__.py +0 -0
  49. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/_post_coinit/bstr.py +0 -0
  50. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/_post_coinit/instancemethod.py +0 -0
  51. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/_post_coinit/misc.py +0 -0
  52. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/_safearray.py +0 -0
  53. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/_tlib_version_checker.py +0 -0
  54. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/clear_cache.py +0 -0
  55. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/client/__init__.py +0 -0
  56. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/client/_activeobj.py +0 -0
  57. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/client/_constants.py +0 -0
  58. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/client/_create.py +0 -0
  59. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/client/_managing.py +0 -0
  60. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/client/dynamic.py +0 -0
  61. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/client/lazybind.py +0 -0
  62. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/git.py +0 -0
  63. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/logutil.py +0 -0
  64. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/patcher.py +0 -0
  65. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/persist.py +0 -0
  66. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/safearray.py +0 -0
  67. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/server/__init__.py +0 -0
  68. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/server/automation.py +0 -0
  69. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/server/w_getopt.py +0 -0
  70. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/shelllink.py +0 -0
  71. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/stream.py +0 -0
  72. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/TestComServer.idl +0 -0
  73. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/TestComServer.py +0 -0
  74. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/TestComServer.tlb +0 -0
  75. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/TestDispServer.idl +0 -0
  76. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/TestDispServer.py +0 -0
  77. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/TestDispServer.tlb +0 -0
  78. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/__init__.py +0 -0
  79. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/find_memleak.py +0 -0
  80. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/mylib.idl +0 -0
  81. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/mylib.tlb +0 -0
  82. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/mytypelib.idl +0 -0
  83. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/runtests.py +0 -0
  84. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/setup.py +0 -0
  85. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_BSTR.py +0 -0
  86. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_DISPPARAMS.py +0 -0
  87. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_QueryService.py +0 -0
  88. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_agilent.py +0 -0
  89. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_avmc.py +0 -0
  90. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_casesensitivity.py +0 -0
  91. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_clear_cache.py +0 -0
  92. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_client.py +0 -0
  93. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_client_dynamic.py +0 -0
  94. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_client_regenerate_modules.py +0 -0
  95. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_createwrappers.py +0 -0
  96. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_dispifc_records.py +0 -0
  97. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_dispifc_safearrays.py +0 -0
  98. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_dispinterface.py +0 -0
  99. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_excel.py +0 -0
  100. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_findgendir.py +0 -0
  101. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_getactiveobj.py +0 -0
  102. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_ie.py +0 -0
  103. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_ienum.py +0 -0
  104. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_imfattributes.py +0 -0
  105. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_jscript.js +0 -0
  106. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_midl_safearray_create.py +0 -0
  107. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_monikers.py +0 -0
  108. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_msscript.py +0 -0
  109. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_npsupport.py +0 -0
  110. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_outparam.py +0 -0
  111. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_persist.py +0 -0
  112. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_pump_events.py +0 -0
  113. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_recordinfo.py +0 -0
  114. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_sapi.py +0 -0
  115. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_server.py +0 -0
  116. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_shelllink.py +0 -0
  117. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_showevents.py +0 -0
  118. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_storage.py +0 -0
  119. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_stream.py +0 -0
  120. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_subinterface.py +0 -0
  121. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_typeannotator.py +0 -0
  122. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_urlhistory.py +0 -0
  123. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_win32com_interop.py +0 -0
  124. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_wmi.py +0 -0
  125. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/test_word.py +0 -0
  126. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/test/urlhist.tlb +0 -0
  127. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/tools/__init__.py +0 -0
  128. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/tools/codegenerator/__init__.py +0 -0
  129. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/tools/codegenerator/codegenerator.py +0 -0
  130. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/tools/codegenerator/comments.py +0 -0
  131. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/tools/codegenerator/heads.py +0 -0
  132. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/tools/codegenerator/helpers.py +0 -0
  133. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/tools/codegenerator/modulenamer.py +0 -0
  134. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/tools/codegenerator/namespaces.py +0 -0
  135. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/tools/codegenerator/packing.py +0 -0
  136. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/tools/codegenerator/typeannotator.py +0 -0
  137. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/tools/typedesc.py +0 -0
  138. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/tools/typedesc_base.py +0 -0
  139. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/util.py +0 -0
  140. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes/viewobject.py +0 -0
  141. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes.egg-info/dependency_links.txt +0 -0
  142. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes.egg-info/entry_points.txt +0 -0
  143. {comtypes-1.4.10 → comtypes-1.4.11}/comtypes.egg-info/top_level.txt +0 -0
  144. {comtypes-1.4.10 → comtypes-1.4.11}/setup.cfg +0 -0
  145. {comtypes-1.4.10 → comtypes-1.4.11}/setup.py +0 -0
@@ -1,11 +1,22 @@
1
+ import functools
1
2
  import logging
2
- from ctypes import *
3
+ from _ctypes import COMError
4
+ from ctypes import c_void_p, pointer
5
+ from ctypes.wintypes import DWORD
6
+ from typing import TYPE_CHECKING, Any, Callable, Dict, Iterator, List, Tuple, Type
7
+ from typing import Union as _UnionT
3
8
 
4
- from comtypes import COMError, COMObject, IUnknown
9
+ from comtypes import GUID, COMObject, IUnknown
5
10
  from comtypes.automation import IDispatch
6
11
  from comtypes.connectionpoints import IConnectionPoint
7
12
  from comtypes.hresult import *
8
- from comtypes.typeinfo import LoadRegTypeLib
13
+ from comtypes.typeinfo import ITypeInfo, LoadRegTypeLib
14
+
15
+ if TYPE_CHECKING:
16
+ from ctypes import _Pointer
17
+ from typing import ClassVar
18
+
19
+ from comtypes import hints # type: ignore
9
20
 
10
21
  logger = logging.getLogger(__name__)
11
22
 
@@ -17,9 +28,11 @@ class ConnectionPointImpl(COMObject):
17
28
 
18
29
  _com_interfaces_ = [IConnectionPoint]
19
30
 
20
- def __init__(self, sink_interface, sink_typeinfo):
31
+ def __init__(
32
+ self, sink_interface: Type[IUnknown], sink_typeinfo: ITypeInfo
33
+ ) -> None:
21
34
  super(ConnectionPointImpl, self).__init__()
22
- self._connections = {}
35
+ self._connections: Dict[int, IUnknown] = {}
23
36
  self._cookie = 0
24
37
  self._sink_interface = sink_interface
25
38
  self._typeinfo = sink_typeinfo
@@ -27,7 +40,9 @@ class ConnectionPointImpl(COMObject):
27
40
  # per MSDN, all interface methods *must* be implemented, E_NOTIMPL
28
41
  # is no allowed return value
29
42
 
30
- def IConnectionPoint_Advise(self, this, pUnk, pdwCookie):
43
+ def IConnectionPoint_Advise(
44
+ self, this: Any, pUnk: IUnknown, pdwCookie: "_Pointer[DWORD]"
45
+ ) -> "hints.Hresult":
31
46
  if not pUnk or not pdwCookie:
32
47
  return E_POINTER
33
48
  logger.debug("Advise")
@@ -39,7 +54,7 @@ class ConnectionPointImpl(COMObject):
39
54
  self._connections[self._cookie] = ptr
40
55
  return S_OK
41
56
 
42
- def IConnectionPoint_Unadvise(self, this, dwCookie):
57
+ def IConnectionPoint_Unadvise(self, this: Any, dwCookie: int) -> "hints.Hresult":
43
58
  logger.debug("Unadvise %s", dwCookie)
44
59
  try:
45
60
  del self._connections[dwCookie]
@@ -47,13 +62,17 @@ class ConnectionPointImpl(COMObject):
47
62
  return CONNECT_E_NOCONNECTION
48
63
  return S_OK
49
64
 
50
- def IConnectionPoint_GetConnectionPointContainer(self, this, ppCPC):
65
+ def IConnectionPoint_GetConnectionPointContainer(
66
+ self, this: Any, ppCPC: c_void_p
67
+ ) -> "hints.Hresult":
51
68
  return E_NOTIMPL
52
69
 
53
- def IConnectionPoint_GetConnectionInterface(self, this, pIID):
70
+ def IConnectionPoint_GetConnectionInterface(
71
+ self, this: Any, pIID: "_Pointer[GUID]"
72
+ ) -> "hints.Hresult":
54
73
  return E_NOTIMPL
55
74
 
56
- def _call_sinks(self, name, *args, **kw):
75
+ def _call_sinks(self, name: str, *args: Any, **kw: Any) -> List[Any]:
57
76
  results = []
58
77
  logger.debug("_call_sinks(%s, %s, *%s, **%s)", self, name, args, kw)
59
78
  # Is it an IDispatch derived interface? Then, events have to be delivered
@@ -62,61 +81,33 @@ class ConnectionPointImpl(COMObject):
62
81
  # for better performance, we could cache the dispids.
63
82
  dispid = self._typeinfo.GetIDsOfNames(name)[0]
64
83
  for key, p in self._connections.items():
65
- try:
66
- result = p.Invoke(dispid, *args, **kw)
67
- except COMError as details:
68
- if details.hresult == -2147023174:
69
- logger.warning(
70
- "_call_sinks(%s, %s, *%s, **%s) failed; removing connection",
71
- self,
72
- name,
73
- args,
74
- kw,
75
- exc_info=True,
76
- )
77
- try:
78
- del self._connections[key]
79
- except KeyError:
80
- pass # connection already gone
81
- else:
82
- logger.warning(
83
- "_call_sinks(%s, %s, *%s, **%s)",
84
- self,
85
- name,
86
- args,
87
- kw,
88
- exc_info=True,
89
- )
90
- else:
91
- results.append(result)
84
+ mth = functools.partial(p.Invoke, dispid) # type: ignore
85
+ results.extend(self._call_sink(name, key, mth, *args, **kw))
92
86
  else:
93
- for p in self._connections.values():
94
- try:
95
- result = getattr(p, name)(*args, **kw)
96
- except COMError as details:
97
- if details.hresult == -2147023174:
98
- logger.warning(
99
- "_call_sinks(%s, %s, *%s, **%s) failed; removing connection",
100
- self,
101
- name,
102
- args,
103
- kw,
104
- exc_info=True,
105
- )
106
- del self._connections[key]
107
- else:
108
- logger.warning(
109
- "_call_sinks(%s, %s, *%s, **%s)",
110
- self,
111
- name,
112
- args,
113
- kw,
114
- exc_info=True,
115
- )
116
- else:
117
- results.append(result)
87
+ for key, p in self._connections.items():
88
+ mth = getattr(p, name)
89
+ results.extend(self._call_sink(name, key, mth, *args, **kw))
118
90
  return results
119
91
 
92
+ def _call_sink(
93
+ self, name: str, key: int, mth: Callable[..., Any], *args: Any, **kw: Any
94
+ ) -> Iterator[Any]:
95
+ try:
96
+ result = mth(*args, **kw)
97
+ except COMError as details:
98
+ if details.hresult == RPC_S_SERVER_UNAVAILABLE:
99
+ warn_msg = "_call_sinks(%s, %s, *%s, **%s) failed; removing connection"
100
+ logger.warning(warn_msg, self, name, args, kw, exc_info=True)
101
+ try:
102
+ del self._connections[key]
103
+ except KeyError:
104
+ pass # connection already gone
105
+ else:
106
+ warn_msg = "_call_sinks(%s, %s, *%s, **%s)"
107
+ logger.warning(warn_msg, self, name, args, kw, exc_info=True)
108
+ else:
109
+ yield result
110
+
120
111
 
121
112
  class ConnectableObjectMixin(object):
122
113
  """Mixin which implements IConnectionPointContainer.
@@ -126,22 +117,30 @@ class ConnectableObjectMixin(object):
126
117
  integer index into the _outgoing_interfaces_ list.
127
118
  """
128
119
 
129
- def __init__(self):
120
+ if TYPE_CHECKING:
121
+ _outgoing_interfaces_: ClassVar[List[Type[IDispatch]]]
122
+ _reg_typelib_: ClassVar[Tuple[str, int, int]]
123
+
124
+ def __init__(self) -> None:
130
125
  super(ConnectableObjectMixin, self).__init__()
131
- self.__connections = {}
126
+ self.__connections: Dict[Type[IDispatch], ConnectionPointImpl] = {}
132
127
 
133
128
  tlib = LoadRegTypeLib(*self._reg_typelib_)
134
129
  for itf in self._outgoing_interfaces_:
135
130
  typeinfo = tlib.GetTypeInfoOfGuid(itf._iid_)
136
131
  self.__connections[itf] = ConnectionPointImpl(itf, typeinfo)
137
132
 
138
- def IConnectionPointContainer_EnumConnectionPoints(self, this, ppEnum):
133
+ def IConnectionPointContainer_EnumConnectionPoints(
134
+ self, this: Any, ppEnum: c_void_p
135
+ ) -> "hints.Hresult":
139
136
  # according to MSDN, E_NOTIMPL is specificially disallowed
140
137
  # because, without typeinfo, there's no way for the caller to
141
138
  # find out.
142
139
  return E_NOTIMPL
143
140
 
144
- def IConnectionPointContainer_FindConnectionPoint(self, this, refiid, ppcp):
141
+ def IConnectionPointContainer_FindConnectionPoint(
142
+ self, this: Any, refiid: "_Pointer[GUID]", ppcp: c_void_p
143
+ ) -> "hints.Hresult":
145
144
  iid = refiid[0]
146
145
  logger.debug("FindConnectionPoint %s", iid)
147
146
  if not ppcp:
@@ -161,7 +160,9 @@ class ConnectableObjectMixin(object):
161
160
  logger.debug("No connectionpoint found")
162
161
  return CONNECT_E_NOCONNECTION
163
162
 
164
- def Fire_Event(self, itf, name, *args, **kw):
163
+ def Fire_Event(
164
+ self, itf: _UnionT[int, Type[IDispatch]], name: str, *args: Any, **kw: Any
165
+ ) -> Any:
165
166
  # Fire event 'name' with arguments *args and **kw.
166
167
  # Accepts either an interface index or an interface as first argument.
167
168
  # Returns a list of results.
@@ -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:
@@ -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:
@@ -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,11 @@
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, POINTER, 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
16
9
  from comtypes.server import IClassFactory
17
10
 
18
11
  if TYPE_CHECKING:
@@ -40,18 +33,18 @@ _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:
47
+ def __init__(self, cls: Type[COMObject], *args, **kw) -> None:
55
48
  super(ClassFactory, self).__init__()
56
49
  self._cls = cls
57
50
  self._register_class()
@@ -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
@@ -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())
@@ -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_ = []
@@ -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
@@ -201,6 +201,26 @@ class ActiveObjTest(unittest.TestCase):
201
201
  self._doit(weak=False)
202
202
 
203
203
 
204
+ class SupportErrorInfoTest(unittest.TestCase):
205
+ def create_object(self):
206
+ return CreateObject(
207
+ comtypes.test.TestComServer.TestComServer,
208
+ interface=comtypes.test.TestComServer.ITestComServer,
209
+ )
210
+
211
+ def test_returns_S_OK(self):
212
+ psei = self.create_object().QueryInterface(errorinfo.ISupportErrorInfo)
213
+ iid = comtypes.test.TestComServer.ITestComServer._iid_
214
+ hr = psei.InterfaceSupportsErrorInfo(iid)
215
+ self.assertEqual(hr, hresult.S_OK)
216
+
217
+ def test_returns_S_FALSE(self):
218
+ psei = self.create_object().QueryInterface(errorinfo.ISupportErrorInfo)
219
+ iid = shelllink.IShellLinkW._iid_
220
+ hr = psei.InterfaceSupportsErrorInfo(iid)
221
+ self.assertEqual(hr, hresult.S_FALSE)
222
+
223
+
204
224
  class VariantTest(unittest.TestCase):
205
225
  def test_UDT(self):
206
226
  from comtypes.gen.TestComServerLib import MYCOLOR
@@ -277,7 +297,10 @@ class TestEvents(unittest.TestCase):
277
297
  import comtypes.test.test_comserver
278
298
 
279
299
  doctest.testmod(
280
- comtypes.test.test_comserver, verbose=False, optionflags=doctest.ELLIPSIS
300
+ comtypes.test.test_comserver,
301
+ verbose=False,
302
+ optionflags=doctest.ELLIPSIS,
303
+ raise_on_error=True,
281
304
  )
282
305
 
283
306
 
@@ -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
@@ -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"""