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
@@ -0,0 +1,159 @@
1
+ # comtypes.hresult
2
+ # COM success and error codes
3
+ #
4
+ # Note that the codes should be written in decimal notation!
5
+
6
+ from ctypes import c_long
7
+
8
+ S_OK = 0
9
+ S_FALSE = 1
10
+
11
+ E_UNEXPECTED = -2147418113 # 0x8000FFFFL
12
+
13
+ E_NOTIMPL = -2147467263 # 0x80004001L
14
+ E_NOINTERFACE = -2147467262 # 0x80004002L
15
+ E_POINTER = -2147467261 # 0x80004003L
16
+ E_FAIL = -2147467259 # 0x80004005L
17
+ E_INVALIDARG = -2147024809 # 0x80070057L
18
+ E_OUTOFMEMORY = -2147024882 # 0x8007000EL
19
+
20
+ CLASS_E_NOAGGREGATION = -2147221232 # 0x80040110L
21
+ CLASS_E_CLASSNOTAVAILABLE = -2147221231 # 0x80040111L
22
+
23
+ CO_E_CLASSSTRING = -2147221005 # 0x800401F3L
24
+
25
+ # connection point error codes
26
+ CONNECT_E_CANNOTCONNECT = -2147220990
27
+ CONNECT_E_ADVISELIMIT = -2147220991
28
+ CONNECT_E_NOCONNECTION = -2147220992
29
+
30
+ TYPE_E_ELEMENTNOTFOUND = -2147352077 # 0x8002802BL
31
+
32
+ TYPE_E_REGISTRYACCESS = -2147319780 # 0x8002801CL
33
+ TYPE_E_CANTLOADLIBRARY = -2147312566 # 0x80029C4AL
34
+
35
+ # all the DISP_E_ values from windows.h
36
+ DISP_E_BUFFERTOOSMALL = -2147352557
37
+ DISP_E_DIVBYZERO = -2147352558
38
+ DISP_E_NOTACOLLECTION = -2147352559
39
+ DISP_E_BADCALLEE = -2147352560
40
+ DISP_E_PARAMNOTOPTIONAL = -2147352561 # 0x8002000F
41
+ DISP_E_BADPARAMCOUNT = -2147352562 # 0x8002000E
42
+ DISP_E_ARRAYISLOCKED = -2147352563 # 0x8002000D
43
+ DISP_E_UNKNOWNLCID = -2147352564 # 0x8002000C
44
+ DISP_E_BADINDEX = -2147352565 # 0x8002000B
45
+ DISP_E_OVERFLOW = -2147352566 # 0x8002000A
46
+ DISP_E_EXCEPTION = -2147352567 # 0x80020009
47
+ DISP_E_BADVARTYPE = -2147352568 # 0x80020008
48
+ DISP_E_NONAMEDARGS = -2147352569 # 0x80020007
49
+ DISP_E_UNKNOWNNAME = -2147352570 # 0x80020006
50
+ DISP_E_TYPEMISMATCH = -2147352571 # 0800020005
51
+ DISP_E_PARAMNOTFOUND = -2147352572 # 0x80020004
52
+ DISP_E_MEMBERNOTFOUND = -2147352573 # 0x80020003
53
+ DISP_E_UNKNOWNINTERFACE = -2147352575 # 0x80020001
54
+
55
+ RPC_E_CHANGED_MODE = -2147417850 # 0x80010106
56
+ RPC_E_SERVERFAULT = -2147417851 # 0x80010105
57
+
58
+ RPC_E_NO_SYNC = -2147417824 # 0x80010120
59
+ RPC_S_CALLPENDING = -2147417835 # 0x80010115
60
+
61
+ # 'macros' and constants to create your own HRESULT values:
62
+
63
+
64
+ def MAKE_HRESULT(sev: int, fac: int, code: int) -> int:
65
+ """Creates an HRESULT value from its component pieces."""
66
+ # A hresult is SIGNED in comtypes
67
+ return c_long((sev << 31 | fac << 16 | code)).value
68
+
69
+
70
+ SEVERITY_ERROR = 1
71
+ SEVERITY_SUCCESS = 0
72
+
73
+ FACILITY_ITF = 4
74
+ FACILITY_WIN32 = 7
75
+
76
+
77
+ def HRESULT_FROM_WIN32(x: int) -> int:
78
+ """Converts a system error code to an HRESULT value."""
79
+ # make signed
80
+ x = c_long(x).value
81
+ if x < 0:
82
+ return x
83
+ # 0x80000000 | FACILITY_WIN32 << 16 | x & 0xFFFF
84
+ return c_long(0x80070000 | (x & 0xFFFF)).value
85
+
86
+
87
+ # Win32 error codes are defined as unsigned 32-bit integers. However, to
88
+ # ensure compatibility with COM and other HRESULT-based APIs, Windows converts
89
+ # them into HRESULT values by setting the high bit, ensuring a consistent way
90
+ # to indicate failure across these APIs.
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
+ ################################################################
@@ -1,31 +1,33 @@
1
1
  import ctypes
2
2
  from ctypes import WinDLL, WinError, byref
3
3
  from ctypes.wintypes import MSG
4
+ from typing import TYPE_CHECKING, List, SupportsIndex
5
+
6
+ if TYPE_CHECKING:
7
+ from ctypes import _CArgObject
8
+ from typing import Any, Callable, Iterable
9
+
10
+ _FilterCallable = Callable[["_CArgObject"], Iterable[Any]] # type: ignore
4
11
 
5
12
  _user32 = WinDLL("user32")
6
13
 
7
14
  GetMessage = _user32.GetMessageA
8
- GetMessage.argtypes = [
9
- ctypes.c_void_p,
10
- ctypes.c_void_p,
11
- ctypes.c_uint,
12
- ctypes.c_uint,
13
- ]
15
+ GetMessage.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_uint, ctypes.c_uint]
14
16
  TranslateMessage = _user32.TranslateMessage
15
17
  DispatchMessage = _user32.DispatchMessageA
16
18
 
17
19
 
18
- class _MessageLoop(object):
19
- def __init__(self):
20
- self._filters = []
20
+ class _MessageLoop:
21
+ def __init__(self) -> None:
22
+ self._filters: List["_FilterCallable"] = []
21
23
 
22
- def insert_filter(self, obj, index=-1):
24
+ def insert_filter(self, obj: "_FilterCallable", index: SupportsIndex = -1) -> None:
23
25
  self._filters.insert(index, obj)
24
26
 
25
- def remove_filter(self, obj):
27
+ def remove_filter(self, obj: "_FilterCallable") -> None:
26
28
  self._filters.remove(obj)
27
29
 
28
- def run(self):
30
+ def run(self) -> None:
29
31
  msg = MSG()
30
32
  lpmsg = byref(msg)
31
33
  while 1:
@@ -38,7 +40,7 @@ class _MessageLoop(object):
38
40
  TranslateMessage(lpmsg)
39
41
  DispatchMessage(lpmsg)
40
42
 
41
- def filter_message(self, lpmsg):
43
+ def filter_message(self, lpmsg: "_CArgObject") -> bool:
42
44
  return any(list(filter(lpmsg)) for filter in self._filters)
43
45
 
44
46
 
@@ -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:
@@ -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):
21
- super(ConnectionPointImpl, self).__init__()
22
- self._connections = {}
31
+ def __init__(
32
+ self, sink_interface: Type[IUnknown], sink_typeinfo: ITypeInfo
33
+ ) -> None:
34
+ super().__init__()
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,63 +81,35 @@ 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
120
110
 
121
- class ConnectableObjectMixin(object):
111
+
112
+ class ConnectableObjectMixin:
122
113
  """Mixin which implements IConnectionPointContainer.
123
114
 
124
115
  Call Fire_Event(interface, methodname, *args, **kw) to fire an
@@ -126,22 +117,30 @@ class ConnectableObjectMixin(object):
126
117
  integer index into the _outgoing_interfaces_ list.
127
118
  """
128
119
 
129
- def __init__(self):
130
- super(ConnectableObjectMixin, self).__init__()
131
- self.__connections = {}
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:
125
+ super().__init__()
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.