comtypes 1.4.8__zip → 1.4.10__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 (154) hide show
  1. {comtypes-1.4.8 → comtypes-1.4.10}/CHANGES.txt +40 -0
  2. {comtypes-1.4.8/comtypes.egg-info → comtypes-1.4.10}/PKG-INFO +4 -3
  3. {comtypes-1.4.8 → comtypes-1.4.10}/README.md +1 -1
  4. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/GUID.py +38 -16
  5. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/__init__.py +36 -16
  6. comtypes-1.4.10/comtypes/_comobject.py +562 -0
  7. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/_memberspec.py +93 -13
  8. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/_meta.py +1 -0
  9. comtypes-1.4.10/comtypes/_post_coinit/_cominterface_meta_patcher.py +152 -0
  10. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/_post_coinit/bstr.py +12 -5
  11. comtypes-1.4.8/comtypes/_py_instance_method.py → comtypes-1.4.10/comtypes/_post_coinit/instancemethod.py +1 -2
  12. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/_post_coinit/misc.py +60 -25
  13. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/_post_coinit/unknwn.py +26 -176
  14. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/_safearray.py +3 -4
  15. comtypes-1.4.10/comtypes/_vtbl.py +448 -0
  16. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/automation.py +46 -49
  17. comtypes-1.4.10/comtypes/client/__init__.py +42 -0
  18. comtypes-1.4.10/comtypes/client/_activeobj.py +46 -0
  19. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/client/_code_cache.py +10 -5
  20. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/client/_constants.py +1 -1
  21. comtypes-1.4.10/comtypes/client/_create.py +147 -0
  22. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/client/_events.py +58 -13
  23. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/client/_generate.py +7 -11
  24. comtypes-1.4.10/comtypes/client/_managing.py +114 -0
  25. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/client/dynamic.py +2 -3
  26. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/client/lazybind.py +12 -13
  27. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/connectionpoints.py +2 -1
  28. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/errorinfo.py +22 -9
  29. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/git.py +5 -5
  30. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/hints.pyi +7 -15
  31. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/logutil.py +15 -3
  32. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/messageloop.py +1 -1
  33. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/persist.py +3 -5
  34. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/safearray.py +17 -5
  35. comtypes-1.4.10/comtypes/server/__init__.py +104 -0
  36. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/server/automation.py +1 -2
  37. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/server/connectionpoints.py +5 -5
  38. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/server/inprocserver.py +25 -17
  39. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/server/localserver.py +49 -19
  40. comtypes-1.4.10/comtypes/server/register.py +478 -0
  41. comtypes-1.4.10/comtypes/server/w_getopt.py +48 -0
  42. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/shelllink.py +16 -33
  43. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/stream.py +7 -4
  44. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/TestComServer.py +6 -7
  45. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/TestDispServer.py +4 -2
  46. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/__init__.py +10 -12
  47. comtypes-1.4.10/comtypes/test/find_memleak.py +72 -0
  48. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/runtests.py +1 -0
  49. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/setup.py +2 -1
  50. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_BSTR.py +10 -23
  51. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_GUID.py +1 -0
  52. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_QueryService.py +1 -0
  53. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_agilent.py +4 -3
  54. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_avmc.py +1 -1
  55. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_basic.py +12 -6
  56. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_casesensitivity.py +3 -5
  57. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_clear_cache.py +1 -1
  58. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_client.py +2 -2
  59. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_client_dynamic.py +2 -2
  60. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_client_regenerate_modules.py +2 -2
  61. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_collections.py +4 -4
  62. comtypes-1.4.10/comtypes/test/test_comobject.py +146 -0
  63. comtypes-1.4.10/comtypes/test/test_comserver.py +349 -0
  64. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_createwrappers.py +2 -4
  65. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_dispifc_records.py +1 -1
  66. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_dispifc_safearrays.py +1 -1
  67. comtypes-1.4.10/comtypes/test/test_dispinterface.py +153 -0
  68. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_dyndispatch.py +1 -0
  69. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_excel.py +22 -12
  70. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_findgendir.py +1 -2
  71. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_getactiveobj.py +4 -4
  72. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_ie.py +19 -9
  73. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_ienum.py +2 -2
  74. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_imfattributes.py +13 -3
  75. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_inout_args.py +8 -5
  76. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_midl_safearray_create.py +14 -4
  77. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_monikers.py +23 -9
  78. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_msscript.py +2 -1
  79. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_npsupport.py +4 -4
  80. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_outparam.py +37 -14
  81. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_persist.py +2 -4
  82. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_recordinfo.py +1 -1
  83. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_safearray.py +1 -90
  84. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_sapi.py +4 -1
  85. comtypes-1.4.10/comtypes/test/test_server.py +350 -0
  86. comtypes-1.4.10/comtypes/test/test_server_register.py +524 -0
  87. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_shelllink.py +2 -3
  88. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_showevents.py +7 -17
  89. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_storage.py +12 -6
  90. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_stream.py +16 -5
  91. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_subinterface.py +4 -2
  92. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_typeannotator.py +1 -2
  93. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_typeinfo.py +19 -7
  94. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_urlhistory.py +7 -4
  95. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_variant.py +3 -19
  96. comtypes-1.4.10/comtypes/test/test_w_getopt.py +29 -0
  97. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_win32com_interop.py +80 -36
  98. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_wmi.py +0 -3
  99. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_word.py +1 -1
  100. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/tools/codegenerator/codegenerator.py +166 -440
  101. comtypes-1.4.10/comtypes/tools/codegenerator/comments.py +79 -0
  102. comtypes-1.4.10/comtypes/tools/codegenerator/heads.py +192 -0
  103. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/tools/codegenerator/helpers.py +11 -14
  104. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/tools/codegenerator/namespaces.py +13 -5
  105. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/tools/codegenerator/packing.py +4 -4
  106. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/tools/codegenerator/typeannotator.py +19 -9
  107. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/tools/tlbparser.py +22 -23
  108. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/tools/typedesc.py +4 -8
  109. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/tools/typedesc_base.py +2 -2
  110. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/typeinfo.py +159 -63
  111. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/viewobject.py +3 -9
  112. {comtypes-1.4.8 → comtypes-1.4.10/comtypes.egg-info}/PKG-INFO +4 -3
  113. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes.egg-info/SOURCES.txt +11 -3
  114. {comtypes-1.4.8 → comtypes-1.4.10}/pyproject.toml +12 -19
  115. comtypes-1.4.8/comtypes/_comobject.py +0 -833
  116. comtypes-1.4.8/comtypes/_idl_stuff.py +0 -67
  117. comtypes-1.4.8/comtypes/client/__init__.py +0 -323
  118. comtypes-1.4.8/comtypes/server/__init__.py +0 -70
  119. comtypes-1.4.8/comtypes/server/register.py +0 -431
  120. comtypes-1.4.8/comtypes/server/w_getopt.py +0 -75
  121. comtypes-1.4.8/comtypes/test/find_memleak.py +0 -76
  122. comtypes-1.4.8/comtypes/test/test_comserver.py +0 -239
  123. comtypes-1.4.8/comtypes/test/test_dispinterface.py +0 -137
  124. comtypes-1.4.8/comtypes/test/test_propputref.py +0 -40
  125. comtypes-1.4.8/comtypes/test/test_server.py +0 -354
  126. {comtypes-1.4.8 → comtypes-1.4.10}/LICENSE.txt +0 -0
  127. {comtypes-1.4.8 → comtypes-1.4.10}/MANIFEST.in +0 -0
  128. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/_npsupport.py +0 -0
  129. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/_post_coinit/__init__.py +0 -0
  130. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/_tlib_version_checker.py +0 -0
  131. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/clear_cache.py +0 -0
  132. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/hresult.py +0 -0
  133. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/patcher.py +0 -0
  134. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/TestComServer.idl +0 -0
  135. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/TestComServer.tlb +0 -0
  136. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/TestDispServer.idl +0 -0
  137. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/TestDispServer.tlb +0 -0
  138. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/mylib.idl +0 -0
  139. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/mylib.tlb +0 -0
  140. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/mytypelib.idl +0 -0
  141. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_DISPPARAMS.py +0 -0
  142. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_dict.py +0 -0
  143. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_jscript.js +0 -0
  144. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_pump_events.py +0 -0
  145. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/urlhist.tlb +0 -0
  146. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/tools/__init__.py +0 -0
  147. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/tools/codegenerator/__init__.py +0 -0
  148. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/tools/codegenerator/modulenamer.py +0 -0
  149. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/util.py +0 -0
  150. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes.egg-info/dependency_links.txt +0 -0
  151. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes.egg-info/entry_points.txt +0 -0
  152. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes.egg-info/top_level.txt +0 -0
  153. {comtypes-1.4.8 → comtypes-1.4.10}/setup.cfg +0 -0
  154. {comtypes-1.4.8 → comtypes-1.4.10}/setup.py +0 -0
@@ -0,0 +1,349 @@
1
+ import doctest
2
+ import unittest
3
+ from ctypes import pointer
4
+ from typing import Any
5
+
6
+ import comtypes.server
7
+ import comtypes.test.TestComServer
8
+ from comtypes import BSTR
9
+ from comtypes.automation import VARIANT, _midlSAFEARRAY
10
+ from comtypes.client import CreateObject, GetActiveObject
11
+ from comtypes.server.register import register, unregister
12
+ from comtypes.test.find_memleak import find_memleak
13
+
14
+ try:
15
+ from win32com.client import Dispatch
16
+
17
+ IMPORT_PYWIN32_FAILED = False
18
+ except ImportError:
19
+ IMPORT_PYWIN32_FAILED = True
20
+
21
+
22
+ def setUpModule():
23
+ try:
24
+ register(comtypes.test.TestComServer.TestComServer)
25
+ except WindowsError as e:
26
+ if e.winerror != 5: # [Error 5] Access is denied
27
+ raise e
28
+ raise unittest.SkipTest(
29
+ "This test requires the tests to be run as admin since it tries to "
30
+ "register the test COM server."
31
+ )
32
+
33
+
34
+ def tearDownModule():
35
+ unregister(comtypes.test.TestComServer.TestComServer)
36
+
37
+
38
+ class BaseServerTest(object):
39
+ def create_object(self) -> Any: ...
40
+
41
+ def _find_memleak(self, func):
42
+ bytes = find_memleak(func)
43
+ self.assertFalse(bytes, f"Leaks {bytes} bytes") # type: ignore
44
+
45
+ def test_mixedinout(self):
46
+ o = self.create_object()
47
+ self.assertEqual(o.MixedInOut(2, 4), (3, 5)) # type: ignore
48
+
49
+ def test_getname(self):
50
+ # This tests a tricky bug, introduced with this patch:
51
+ # http://www.python.org/sf/1643874
52
+ #
53
+ # Returning a BSTR as an [out] parameter from a server
54
+ # implementation must transfer the ownership to the caller.
55
+ # When this is not done, the BSTR instance is SysFreeString'd
56
+ # too early, and the memory is reused.
57
+ obj = self.create_object()
58
+ pb = pointer(BSTR())
59
+ # Get the BSTR from the server:
60
+ obj._ITestComServer__com__get_name(pb)
61
+ # Retrieve the value, but keep the pointer to the BSTR alive:
62
+ name = pb[0]
63
+ # Create sme BSTR's to reuse the memory in case it has been freed:
64
+ for i in range(10):
65
+ BSTR("f" * len(name))
66
+ # Make sure the pointer is still valid:
67
+ self.assertEqual(pb[0], name) # type: ignore
68
+
69
+ def test_get_id(self):
70
+ obj = self.create_object()
71
+ self._find_memleak(lambda: obj.id)
72
+
73
+ def test_get_name(self):
74
+ obj = self.create_object()
75
+ self._find_memleak(lambda: obj.name)
76
+
77
+ def test_set_name(self):
78
+ obj = self.create_object()
79
+
80
+ def func():
81
+ obj.name = "abcde"
82
+
83
+ self._find_memleak(func)
84
+
85
+ def test_SetName(self):
86
+ obj = self.create_object()
87
+
88
+ def func():
89
+ obj.SetName("abcde")
90
+
91
+ self._find_memleak(func)
92
+
93
+ def test_eval(self):
94
+ obj = self.create_object()
95
+
96
+ def func():
97
+ return obj.eval("(1, 2, 3)")
98
+
99
+ self.assertEqual(func(), (1, 2, 3)) # type: ignore
100
+ self._find_memleak(func)
101
+
102
+ def test_get_typeinfo(self):
103
+ obj = self.create_object()
104
+
105
+ def func():
106
+ obj.GetTypeInfo(0)
107
+ obj.GetTypeInfoCount()
108
+ obj.QueryInterface(comtypes.IUnknown)
109
+
110
+ self._find_memleak(func)
111
+
112
+
113
+ class TestInproc(BaseServerTest, unittest.TestCase):
114
+ def create_object(self):
115
+ return CreateObject(
116
+ "TestComServerLib.TestComServer", clsctx=comtypes.CLSCTX_INPROC_SERVER
117
+ )
118
+
119
+
120
+ class TestLocalServer(BaseServerTest, unittest.TestCase):
121
+ def create_object(self):
122
+ return CreateObject(
123
+ "TestComServerLib.TestComServer", clsctx=comtypes.CLSCTX_LOCAL_SERVER
124
+ )
125
+
126
+ @unittest.skip("This fails. Why?")
127
+ def test_get_typeinfo(self):
128
+ # Calling `GetTypeInfo` occurs;
129
+ # OSError: exception: access violation reading 0x0000000000000000
130
+ pass
131
+
132
+
133
+ @unittest.skipIf(IMPORT_PYWIN32_FAILED, "This depends on 'pywin32'.")
134
+ class TestInproc_win32com(BaseServerTest, unittest.TestCase):
135
+ def create_object(self):
136
+ return Dispatch("TestComServerLib.TestComServer")
137
+
138
+ # These tests make no sense with win32com, override to disable them:
139
+ @unittest.skip("This test make no sense with win32com.")
140
+ def test_get_typeinfo(self):
141
+ pass
142
+
143
+ @unittest.skip("This test make no sense with win32com.")
144
+ def test_getname(self):
145
+ pass
146
+
147
+ @unittest.skip("This test make no sense with win32com.")
148
+ def test_mixedinout(self):
149
+ # Not sure about this; it raise 'Invalid Number of parameters'
150
+ # Is mixed [in], [out] args not compatible with IDispatch???
151
+ pass
152
+
153
+
154
+ @unittest.skipIf(IMPORT_PYWIN32_FAILED, "This depends on 'pywin32'.")
155
+ class TestLocalServer_win32com(BaseServerTest, unittest.TestCase):
156
+ def create_object(self):
157
+ return Dispatch(
158
+ "TestComServerLib.TestComServer", clsctx=comtypes.CLSCTX_LOCAL_SERVER
159
+ )
160
+
161
+ # These tests are skipped for the same reason as `TestInproc_win32com`.
162
+ @unittest.skip("This test make no sense with win32com.")
163
+ def test_get_typeinfo(self):
164
+ pass
165
+
166
+ @unittest.skip("This test make no sense with win32com.")
167
+ def test_getname(self):
168
+ pass
169
+
170
+ @unittest.skip("This test make no sense with win32com.")
171
+ def test_mixedinout(self):
172
+ pass
173
+
174
+
175
+ class ActiveObjTest(unittest.TestCase):
176
+ def get_active_object(self) -> comtypes.test.TestComServer.ITestComServer:
177
+ return GetActiveObject(
178
+ comtypes.test.TestComServer.TestComServer,
179
+ interface=comtypes.test.TestComServer.ITestComServer,
180
+ )
181
+
182
+ def _doit(self, weak: bool):
183
+ comobj = comtypes.test.TestComServer.TestComServer()
184
+ with self.assertRaises(OSError):
185
+ self.get_active_object()
186
+ handle = comtypes.server.RegisterActiveObject(comobj, weak=weak)
187
+ activeobj = self.get_active_object()
188
+ self.assertEqual(activeobj.MixedInOut(2, 4), (3, 5))
189
+ self.assertEqual(activeobj.AddRef(), 3)
190
+ self.assertEqual(activeobj.Release(), 2)
191
+ punk = comobj.QueryInterface(comtypes.test.TestComServer.ITestComServer)
192
+ self.assertEqual(activeobj, punk)
193
+ comtypes.server.RevokeActiveObject(handle)
194
+ with self.assertRaises(OSError):
195
+ self.get_active_object()
196
+
197
+ def test_activeobj_weak_registration(self):
198
+ self._doit(weak=True)
199
+
200
+ def test_activeobj_strong_registration(self):
201
+ self._doit(weak=False)
202
+
203
+
204
+ class VariantTest(unittest.TestCase):
205
+ def test_UDT(self):
206
+ from comtypes.gen.TestComServerLib import MYCOLOR
207
+
208
+ v = VARIANT(MYCOLOR(red=1.0, green=2.0, blue=3.0))
209
+ value = v.value
210
+ self.assertEqual(1.0, value.red) # type: ignore
211
+ self.assertEqual(2.0, value.green) # type: ignore
212
+ self.assertEqual(3.0, value.blue) # type: ignore
213
+
214
+ def func():
215
+ v = VARIANT(MYCOLOR(red=1.0, green=2.0, blue=3.0))
216
+ return v.value
217
+
218
+ bytes = find_memleak(func)
219
+ self.assertFalse(bytes, f"Leaks {bytes} bytes") # type: ignore
220
+
221
+
222
+ class SafeArrayTest(unittest.TestCase):
223
+ def test_UDT(self):
224
+ from comtypes.gen.TestComServerLib import MYCOLOR
225
+
226
+ t = _midlSAFEARRAY(MYCOLOR)
227
+ self.assertTrue(t is _midlSAFEARRAY(MYCOLOR))
228
+
229
+ sa = t.from_param([MYCOLOR(0, 0, 0), MYCOLOR(1, 2, 3)])
230
+
231
+ self.assertEqual(
232
+ [(x.red, x.green, x.blue) for x in sa[0]],
233
+ [(0.0, 0.0, 0.0), (1.0, 2.0, 3.0)],
234
+ )
235
+
236
+ def doit():
237
+ t.from_param([MYCOLOR(0, 0, 0), MYCOLOR(1, 2, 3)])
238
+
239
+ bytes = find_memleak(doit)
240
+ self.assertFalse(bytes, f"Leaks {bytes} bytes") # type: ignore
241
+
242
+
243
+ class PropPutRefTest(unittest.TestCase):
244
+ def doit(self, dynamic: bool):
245
+ d = CreateObject("Scripting.Dictionary", dynamic=dynamic)
246
+ s = CreateObject("TestComServerLib.TestComServer", dynamic=dynamic)
247
+ s.name = "the value"
248
+
249
+ # This calls propputref, since we assign an Object
250
+ d.Item["object"] = s
251
+ # This calls propput, since we assing a Value
252
+ d.Item["value"] = s.name
253
+
254
+ self.assertEqual(d.Item["object"], s)
255
+ self.assertEqual(d.Item["object"].name, "the value")
256
+ self.assertEqual(d.Item["value"], "the value")
257
+
258
+ # Changing the default property of the object
259
+ s.name = "foo bar"
260
+ self.assertEqual(d.Item["object"], s)
261
+ self.assertEqual(d.Item["object"].name, "foo bar")
262
+ self.assertEqual(d.Item["value"], "the value")
263
+
264
+ # This also calls propputref since we assign an Object
265
+ d.Item["var"] = VARIANT(s)
266
+ self.assertEqual(d.Item["var"], s)
267
+
268
+ def test_earlybind(self):
269
+ self.doit(dynamic=False)
270
+
271
+ def test_latebind(self):
272
+ self.doit(dynamic=True)
273
+
274
+
275
+ class TestEvents(unittest.TestCase):
276
+ def test(self):
277
+ import comtypes.test.test_comserver
278
+
279
+ doctest.testmod(
280
+ comtypes.test.test_comserver, verbose=False, optionflags=doctest.ELLIPSIS
281
+ )
282
+
283
+
284
+ class ShowEventsExamples:
285
+ # The following functions are never called, they only contain doctests:
286
+
287
+ def ShowEventsFloat(self):
288
+ """
289
+ >>> from comtypes.client import CreateObject, ShowEvents
290
+ >>>
291
+ >>> o = CreateObject("TestComServerLib.TestComServer")
292
+ >>> con = ShowEvents(o)
293
+ # event found: ITestComServerEvents_EvalStarted
294
+ # event found: ITestComServerEvents_EvalCompleted
295
+ >>> result = o.eval("10. / 4")
296
+ Event ITestComServerEvents_EvalStarted(None, '10. / 4')
297
+ Event ITestComServerEvents_EvalCompleted(None, '10. / 4', VARIANT(vt=0x5, 2.5))
298
+ >>> result
299
+ 2.5
300
+ >>>
301
+ """
302
+
303
+ # # The following test, if enabled, works but the testsuit
304
+ # # crashes elsewhere. Is there s problem with SAFEARRAYs?
305
+
306
+ # def Fails(self):
307
+ # """
308
+ # >>> from comtypes.client import CreateObject, ShowEvents
309
+ # >>>
310
+ # >>> o = CreateObject("TestComServerLib.TestComServer")
311
+ # >>> con = ShowEvents(o)
312
+ # # event found: ITestComServerEvents_EvalStarted
313
+ # # event found: ITestComServerEvents_EvalCompleted
314
+ # >>> result = o.eval("['32'] * 2")
315
+ # Event ITestComServerEvents_EvalStarted(None, u"['32'] * 2")
316
+ # Event ITestComServerEvents_EvalCompleted(None, u"['32'] * 2", VARIANT(vt=0x200c, (u'32', u'32')))
317
+ # >>> result
318
+ # (u'32', u'32')
319
+ # >>>
320
+ # """
321
+
322
+ def GetEvents(self):
323
+ """
324
+ >>> from comtypes.client import CreateObject, GetEvents
325
+ >>>
326
+ >>> o = CreateObject("TestComServerLib.TestComServer")
327
+ >>> class EventHandler(object):
328
+ ... def EvalStarted(self, this, what):
329
+ ... print("EvalStarted: %s" % what)
330
+ ... return 0
331
+ ... def EvalCompleted(self, this, what, result):
332
+ ... print("EvalCompleted: %s = %s" % (what, result.value))
333
+ ... return 0
334
+ ...
335
+ >>>
336
+ >>> con = GetEvents(o, EventHandler())
337
+ >>> o.eval("2 + 3")
338
+ EvalStarted: 2 + 3
339
+ EvalCompleted: 2 + 3 = 5
340
+ 5
341
+ >>> del con
342
+ >>> o.eval("3 + 2")
343
+ 5
344
+ >>>
345
+ """
346
+
347
+
348
+ if __name__ == "__main__":
349
+ unittest.main()
@@ -15,8 +15,6 @@ def setUpModule():
15
15
  )
16
16
 
17
17
 
18
- # requires("typelibs")
19
-
20
18
  # filter warnings about interfaces without a base interface; they will
21
19
  # be skipped in the code generation.
22
20
  warnings.filterwarnings(
@@ -57,8 +55,8 @@ def add_test(fname):
57
55
  return
58
56
  comtypes.client.GetModule(fname)
59
57
 
60
- test.__doc__ = "test GetModule(%r)" % fname
61
- setattr(Test, "test_%d" % number, test)
58
+ test.__doc__ = f"test GetModule({fname!r})"
59
+ setattr(Test, f"test_{number}", test)
62
60
  number += 1
63
61
 
64
62
 
@@ -1,10 +1,10 @@
1
1
  # coding: utf-8
2
2
 
3
3
  import unittest
4
+ from ctypes import byref, pointer
4
5
 
5
6
  from comtypes import CLSCTX_LOCAL_SERVER
6
7
  from comtypes.client import CreateObject, GetModule
7
- from ctypes import byref, pointer
8
8
 
9
9
  ComtypesCppTestSrvLib_GUID = "{07D2AEE5-1DF8-4D2C-953A-554ADFD25F99}"
10
10
 
@@ -1,7 +1,7 @@
1
1
  # coding: utf-8
2
2
 
3
- from ctypes import byref, c_double, pointer
4
3
  import unittest
4
+ from ctypes import byref, c_double, pointer
5
5
 
6
6
  import comtypes
7
7
  import comtypes.safearray
@@ -0,0 +1,153 @@
1
+ import os
2
+ import unittest
3
+
4
+ import comtypes.test.TestDispServer
5
+ from comtypes.server.register import register, unregister
6
+
7
+ try:
8
+ from win32com.client import Dispatch
9
+ from win32com.client.gencache import EnsureDispatch
10
+
11
+ IMPORT_PYWIN32_FAILED = False
12
+ except ImportError:
13
+ IMPORT_PYWIN32_FAILED = True
14
+
15
+
16
+ def setUpModule():
17
+ try:
18
+ register(comtypes.test.TestDispServer.TestDispServer)
19
+ except WindowsError as e:
20
+ if e.winerror != 5: # [Error 5] Access is denied
21
+ raise e
22
+ raise unittest.SkipTest(
23
+ "This test requires the tests to be run as admin since it tries to "
24
+ "register the test COM server."
25
+ )
26
+
27
+
28
+ def tearDownModule():
29
+ unregister(comtypes.test.TestDispServer.TestDispServer)
30
+
31
+
32
+ @unittest.skipIf(IMPORT_PYWIN32_FAILED, "This depends on 'pywin32'.")
33
+ class Test_win32com(unittest.TestCase):
34
+ @unittest.skip(
35
+ "It likely fails due to bugs in `GenerateChildFromTypeLibSpec` "
36
+ "or `GetModuleForCLSID`."
37
+ )
38
+ def test_win32com_ensure_dispatch(self):
39
+ # EnsureDispatch is case-sensitive
40
+ d = EnsureDispatch("TestDispServerLib.TestDispServer")
41
+
42
+ self.assertEqual(d.eval("3.14"), 3.14)
43
+ self.assertEqual(d.eval("1 + 2"), 3)
44
+ self.assertEqual(d.eval("[1 + 2, 'foo', None]"), (3, "foo", None))
45
+
46
+ self.assertEqual(d.eval2("3.14"), 3.14)
47
+ self.assertEqual(d.eval2("1 + 2"), 3)
48
+ self.assertEqual(d.eval2("[1 + 2, 'foo', None]"), (3, "foo", None))
49
+
50
+ d.eval(
51
+ "__import__('comtypes.client').client.CreateObject('Scripting.Dictionary')"
52
+ )
53
+
54
+ server_id = d.eval("id(self)")
55
+ self.assertEqual(d.id, server_id)
56
+
57
+ self.assertEqual(d.name, "spam, spam, spam")
58
+
59
+ d.SetName("foo bar")
60
+ self.assertEqual(d.name, "foo bar")
61
+
62
+ d.name = "blah"
63
+ self.assertEqual(d.name, "blah")
64
+
65
+ def test_win32com_dynamic_dispatch(self):
66
+ # dynamic Dispatch is case-IN-sensitive
67
+ d = Dispatch("TestDispServerLib.TestDispServer")
68
+
69
+ self.assertEqual(d.eval("3.14"), 3.14)
70
+ self.assertEqual(d.eval("1 + 2"), 3)
71
+ self.assertEqual(d.eval("[1 + 2, 'foo', None]"), (3, "foo", None))
72
+
73
+ self.assertEqual(d.eval2("3.14"), 3.14)
74
+ self.assertEqual(d.eval2("1 + 2"), 3)
75
+ self.assertEqual(d.eval2("[1 + 2, 'foo', None]"), (3, "foo", None))
76
+
77
+ d.eval(
78
+ "__import__('comtypes.client').client.CreateObject('Scripting.Dictionary')"
79
+ )
80
+
81
+ self.assertEqual(d.EVAL("3.14"), 3.14)
82
+ self.assertEqual(d.EVAL("1 + 2"), 3)
83
+ self.assertEqual(d.EVAL("[1 + 2, 'foo', None]"), (3, "foo", None))
84
+
85
+ self.assertEqual(d.EVAL2("3.14"), 3.14)
86
+ self.assertEqual(d.EVAL2("1 + 2"), 3)
87
+ self.assertEqual(d.EVAL2("[1 + 2, 'foo', None]"), (3, "foo", None))
88
+
89
+ server_id = d.eval("id(self)")
90
+ self.assertEqual(d.id, server_id)
91
+ self.assertEqual(d.ID, server_id)
92
+
93
+ self.assertEqual(d.Name, "spam, spam, spam")
94
+ self.assertEqual(d.nAME, "spam, spam, spam")
95
+
96
+ d.SetName("foo bar")
97
+ self.assertEqual(d.Name, "foo bar")
98
+
99
+ # fails. Why?
100
+ # d.name = "blah"
101
+ # self.assertEqual(d.Name, "blah")
102
+
103
+
104
+ class Test_comtypes(unittest.TestCase):
105
+ def test_comtypes(self):
106
+ from comtypes.client import CreateObject
107
+
108
+ d = CreateObject("TestDispServerLib.TestDispServer")
109
+
110
+ self.assertEqual(d.eval("3.14"), 3.14)
111
+ self.assertEqual(d.eval("1 + 2"), 3)
112
+ self.assertEqual(d.eval("[1 + 2, 'foo', None]"), (3, "foo", None))
113
+
114
+ self.assertEqual(d.eval2("3.14"), 3.14)
115
+ self.assertEqual(d.eval2("1 + 2"), 3)
116
+ self.assertEqual(d.eval2("[1 + 2, 'foo', None]"), (3, "foo", None))
117
+
118
+ d.eval(
119
+ "__import__('comtypes.client').client.CreateObject('Scripting.Dictionary')"
120
+ )
121
+
122
+ self.assertEqual(d.EVAL("3.14"), 3.14)
123
+ self.assertEqual(d.EVAL("1 + 2"), 3)
124
+ self.assertEqual(d.EVAL("[1 + 2, 'foo', None]"), (3, "foo", None))
125
+
126
+ self.assertEqual(d.EVAL2("3.14"), 3.14)
127
+ self.assertEqual(d.EVAL2("1 + 2"), 3)
128
+ self.assertEqual(d.EVAL2("[1 + 2, 'foo', None]"), (3, "foo", None))
129
+
130
+ server_id = d.eval("id(self)")
131
+ self.assertEqual(d.id, server_id)
132
+ self.assertEqual(d.ID, server_id)
133
+
134
+ self.assertEqual(d.Name, "spam, spam, spam")
135
+ self.assertEqual(d.nAME, "spam, spam, spam")
136
+
137
+ d.SetName("foo bar")
138
+ self.assertEqual(d.Name, "foo bar")
139
+
140
+ d.name = "blah"
141
+ self.assertEqual(d.Name, "blah")
142
+
143
+
144
+ @unittest.skip("This raises 'ClassFactory cannot supply requested class'. Why?")
145
+ class Test_jscript(unittest.TestCase):
146
+ def test_withjscript(self):
147
+ jscript = os.path.join(os.path.dirname(__file__), "test_jscript.js")
148
+ errcode = os.system("cscript -nologo %s" % jscript)
149
+ self.assertEqual(errcode, 0)
150
+
151
+
152
+ if __name__ == "__main__":
153
+ unittest.main()
@@ -1,4 +1,5 @@
1
1
  import unittest
2
+
2
3
  from comtypes.automation import IDispatch
3
4
  from comtypes.client import CreateObject, GetModule
4
5
  from comtypes.client.lazybind import Dispatch
@@ -3,6 +3,7 @@
3
3
  import datetime
4
4
  import sys
5
5
  import unittest
6
+ from typing import ClassVar
6
7
 
7
8
  from comtypes.client import CreateObject, GetModule
8
9
 
@@ -27,6 +28,7 @@ except (ImportError, OSError):
27
28
 
28
29
  class BaseBindTest(object):
29
30
  # `dynamic = True/False` must be defined in subclasses!
31
+ dynamic: ClassVar[bool]
30
32
 
31
33
  def setUp(self):
32
34
  self.xl = CreateObject("Excel.Application", dynamic=self.dynamic)
@@ -62,17 +64,21 @@ class BaseBindTest(object):
62
64
  # call property to retrieve value
63
65
  expected_values = ((10.0, 20.0, 31.4), ("x", "y", "z"), (3.0, 2.0, 1.0))
64
66
  # XXX: in Python >= 3.8.x, fails below
65
- self.assertEqual(xl.Range["A1:C3"].Value(), expected_values)
67
+ self.assertEqual(xl.Range["A1:C3"].Value(), expected_values) # type: ignore
66
68
  # index with empty tuple
67
- self.assertEqual(xl.Range["A1:C3"].Value[()], expected_values)
69
+ self.assertEqual(xl.Range["A1:C3"].Value[()], expected_values) # type: ignore
68
70
  # index with empty slice
69
- self.assertEqual(xl.Range["A1:C3"].Value[:], expected_values)
70
- self.assertEqual(xl.Range["A1:C3"].Value[xlRangeValueDefault], expected_values)
71
- self.assertEqual(xl.Range["A1", "C3"].Value[()], expected_values)
71
+ self.assertEqual(xl.Range["A1:C3"].Value[:], expected_values) # type: ignore
72
+ self.assertEqual( # type: ignore
73
+ xl.Range["A1:C3"].Value[xlRangeValueDefault], expected_values
74
+ )
75
+ self.assertEqual( # type: ignore
76
+ xl.Range["A1", "C3"].Value[()], expected_values
77
+ )
72
78
 
73
79
  # Test for iteration support in "Range" interface
74
80
  iter(xl.Range["A1:C3"])
75
- self.assertEqual(
81
+ self.assertEqual( # type: ignore
76
82
  [c.Value() for c in xl.Range["A1:C3"]],
77
83
  [10.0, 20.0, 31.4, "x", "y", "z", 3.0, 2.0, 1.0],
78
84
  )
@@ -83,25 +89,29 @@ class BaseBindTest(object):
83
89
  for i in range(20):
84
90
  val = "Hi %d" % i
85
91
  xl.Cells.Item[i + 1, i + 1].Value[()] = val
86
- self.assertEqual(xl.Cells.Item[i + 1, i + 1].Value[()], val)
92
+ self.assertEqual( # type: ignore
93
+ xl.Cells.Item[i + 1, i + 1].Value[()], val
94
+ )
87
95
 
88
96
  for i in range(20):
89
97
  val = "Hi %d" % i
90
98
  xl.Cells(i + 1, i + 1).Value[()] = val
91
- self.assertEqual(xl.Cells(i + 1, i + 1).Value[()], val)
99
+ self.assertEqual(xl.Cells(i + 1, i + 1).Value[()], val) # type: ignore
92
100
 
93
101
  # test dates out with Excel
94
102
  xl.Range["A5"].Value[()] = "Excel time"
95
103
  xl.Range["B5"].Formula = "=Now()"
96
- self.assertEqual(xl.Cells.Item[5, 2].Formula, "=NOW()")
104
+ self.assertEqual(xl.Cells.Item[5, 2].Formula, "=NOW()") # type: ignore
97
105
 
98
106
  xl.Range["A6"].Calculate()
99
107
  excel_time = xl.Range["B5"].Value[()]
100
- self.assertEqual(type(excel_time), datetime.datetime)
108
+ self.assertEqual(type(excel_time), datetime.datetime) # type: ignore
101
109
  python_time = datetime.datetime.now()
102
110
 
103
- self.assertTrue(python_time >= excel_time)
104
- self.assertTrue(python_time - excel_time < datetime.timedelta(seconds=1))
111
+ self.assertTrue(python_time >= excel_time) # type: ignore
112
+ self.assertTrue( # type: ignore
113
+ python_time - excel_time < datetime.timedelta(seconds=1)
114
+ )
105
115
 
106
116
  # some random code, grabbed from c.l.p
107
117
  sh = wb.Worksheets[1]
@@ -4,15 +4,14 @@ import os
4
4
  import sys
5
5
  import tempfile
6
6
  import types
7
- from typing import Iterator
8
7
  import unittest
8
+ from typing import Iterator
9
9
  from unittest import mock
10
10
 
11
11
  import comtypes
12
12
  import comtypes.client
13
13
  import comtypes.gen
14
14
 
15
-
16
15
  IMGBASE = os.path.splitext(os.path.basename(sys.executable))[0]
17
16
 
18
17
 
@@ -8,9 +8,9 @@ import comtypes.test
8
8
  try:
9
9
  # pass Word libUUID
10
10
  comtypes.client.GetModule(("{00020905-0000-0000-C000-000000000046}",))
11
- IMPORT_FAILED = False
11
+ IMPORT_WORD_FAILED = False
12
12
  except (ImportError, OSError):
13
- IMPORT_FAILED = True
13
+ IMPORT_WORD_FAILED = True
14
14
 
15
15
 
16
16
  ################################################################
@@ -24,8 +24,8 @@ except (ImportError, OSError):
24
24
  ################################################################
25
25
 
26
26
 
27
- @unittest.skipIf(IMPORT_FAILED, "This depends on Word.")
28
- class Test(unittest.TestCase):
27
+ @unittest.skipIf(IMPORT_WORD_FAILED, "This depends on Word.")
28
+ class Test_Word(unittest.TestCase):
29
29
  def setUp(self):
30
30
  try:
31
31
  comtypes.client.GetActiveObject("Word.Application")