comtypes 1.4.8__zip → 1.4.9__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.
- {comtypes-1.4.8 → comtypes-1.4.9}/CHANGES.txt +21 -0
- {comtypes-1.4.8/comtypes.egg-info → comtypes-1.4.9}/PKG-INFO +2 -2
- {comtypes-1.4.8 → comtypes-1.4.9}/README.md +1 -1
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/GUID.py +6 -5
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/__init__.py +16 -5
- comtypes-1.4.9/comtypes/_comobject.py +507 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/_memberspec.py +80 -8
- comtypes-1.4.9/comtypes/_post_coinit/_cominterface_meta_patcher.py +153 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/_post_coinit/misc.py +1 -1
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/_post_coinit/unknwn.py +25 -171
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/_safearray.py +1 -2
- comtypes-1.4.9/comtypes/_vtbl.py +448 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/automation.py +36 -45
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/client/_code_cache.py +4 -4
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/client/_constants.py +1 -1
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/client/_events.py +1 -1
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/client/_generate.py +4 -8
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/client/lazybind.py +2 -2
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/errorinfo.py +3 -3
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/git.py +1 -2
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/hints.pyi +7 -15
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/safearray.py +10 -0
- comtypes-1.4.9/comtypes/server/__init__.py +86 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/server/inprocserver.py +22 -17
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/server/localserver.py +28 -16
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/server/register.py +61 -73
- comtypes-1.4.9/comtypes/server/w_getopt.py +48 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/shelllink.py +3 -26
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/__init__.py +9 -11
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_BSTR.py +4 -7
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_avmc.py +1 -1
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_casesensitivity.py +3 -5
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_collections.py +3 -3
- comtypes-1.4.9/comtypes/test/test_comobject.py +146 -0
- comtypes-1.4.9/comtypes/test/test_comserver.py +319 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_createwrappers.py +2 -4
- comtypes-1.4.9/comtypes/test/test_dispinterface.py +153 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_excel.py +22 -12
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_ie.py +2 -5
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_inout_args.py +7 -4
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_midl_safearray_create.py +9 -1
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_outparam.py +17 -10
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_safearray.py +1 -90
- comtypes-1.4.9/comtypes/test/test_server.py +350 -0
- comtypes-1.4.9/comtypes/test/test_server_register.py +536 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_showevents.py +7 -17
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_variant.py +0 -17
- comtypes-1.4.9/comtypes/test/test_w_getopt.py +29 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_win32com_interop.py +80 -36
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_wmi.py +0 -3
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/tools/codegenerator/codegenerator.py +62 -68
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/tools/codegenerator/helpers.py +8 -8
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/tools/codegenerator/packing.py +4 -4
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/tools/codegenerator/typeannotator.py +7 -7
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/tools/typedesc.py +1 -6
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/typeinfo.py +11 -22
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/viewobject.py +1 -5
- {comtypes-1.4.8 → comtypes-1.4.9/comtypes.egg-info}/PKG-INFO +2 -2
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes.egg-info/SOURCES.txt +6 -3
- {comtypes-1.4.8 → comtypes-1.4.9}/pyproject.toml +1 -0
- comtypes-1.4.8/comtypes/_comobject.py +0 -833
- comtypes-1.4.8/comtypes/_idl_stuff.py +0 -67
- comtypes-1.4.8/comtypes/server/__init__.py +0 -70
- comtypes-1.4.8/comtypes/server/w_getopt.py +0 -75
- comtypes-1.4.8/comtypes/test/test_comserver.py +0 -239
- comtypes-1.4.8/comtypes/test/test_dispinterface.py +0 -137
- comtypes-1.4.8/comtypes/test/test_propputref.py +0 -40
- comtypes-1.4.8/comtypes/test/test_server.py +0 -354
- {comtypes-1.4.8 → comtypes-1.4.9}/LICENSE.txt +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/MANIFEST.in +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/_meta.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/_npsupport.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/_post_coinit/__init__.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/_post_coinit/bstr.py +0 -0
- /comtypes-1.4.8/comtypes/_py_instance_method.py → /comtypes-1.4.9/comtypes/_post_coinit/instancemethod.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/_tlib_version_checker.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/clear_cache.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/client/__init__.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/client/dynamic.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/connectionpoints.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/hresult.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/logutil.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/messageloop.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/patcher.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/persist.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/server/automation.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/server/connectionpoints.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/stream.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/TestComServer.idl +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/TestComServer.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/TestComServer.tlb +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/TestDispServer.idl +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/TestDispServer.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/TestDispServer.tlb +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/find_memleak.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/mylib.idl +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/mylib.tlb +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/mytypelib.idl +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/runtests.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/setup.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_DISPPARAMS.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_GUID.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_QueryService.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_agilent.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_basic.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_clear_cache.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_client.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_client_dynamic.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_client_regenerate_modules.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_dict.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_dispifc_records.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_dispifc_safearrays.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_dyndispatch.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_findgendir.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_getactiveobj.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_ienum.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_imfattributes.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_jscript.js +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_monikers.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_msscript.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_npsupport.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_persist.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_pump_events.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_recordinfo.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_sapi.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_shelllink.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_storage.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_stream.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_subinterface.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_typeannotator.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_typeinfo.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_urlhistory.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/test_word.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/test/urlhist.tlb +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/tools/__init__.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/tools/codegenerator/__init__.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/tools/codegenerator/modulenamer.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/tools/codegenerator/namespaces.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/tools/tlbparser.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/tools/typedesc_base.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes/util.py +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes.egg-info/dependency_links.txt +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes.egg-info/entry_points.txt +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/comtypes.egg-info/top_level.txt +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/setup.cfg +0 -0
- {comtypes-1.4.8 → comtypes-1.4.9}/setup.py +0 -0
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
import doctest
|
|
2
|
+
import unittest
|
|
3
|
+
from ctypes import pointer
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
import comtypes.test.TestComServer
|
|
7
|
+
from comtypes import BSTR
|
|
8
|
+
from comtypes.automation import VARIANT, _midlSAFEARRAY
|
|
9
|
+
from comtypes.client import CreateObject
|
|
10
|
+
from comtypes.server.register import register, unregister
|
|
11
|
+
from comtypes.test.find_memleak import find_memleak
|
|
12
|
+
|
|
13
|
+
try:
|
|
14
|
+
from win32com.client import Dispatch
|
|
15
|
+
|
|
16
|
+
IMPORT_PYWIN32_FAILED = False
|
|
17
|
+
except ImportError:
|
|
18
|
+
IMPORT_PYWIN32_FAILED = True
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def setUpModule():
|
|
22
|
+
try:
|
|
23
|
+
register(comtypes.test.TestComServer.TestComServer)
|
|
24
|
+
except WindowsError as e:
|
|
25
|
+
if e.winerror != 5: # [Error 5] Access is denied
|
|
26
|
+
raise e
|
|
27
|
+
raise unittest.SkipTest(
|
|
28
|
+
"This test requires the tests to be run as admin since it tries to "
|
|
29
|
+
"register the test COM server."
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def tearDownModule():
|
|
34
|
+
unregister(comtypes.test.TestComServer.TestComServer)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class BaseServerTest(object):
|
|
38
|
+
def create_object(self) -> Any: ...
|
|
39
|
+
|
|
40
|
+
def _find_memleak(self, func):
|
|
41
|
+
bytes = find_memleak(func)
|
|
42
|
+
self.assertFalse(bytes, f"Leaks {bytes} bytes") # type: ignore
|
|
43
|
+
|
|
44
|
+
def test_mixedinout(self):
|
|
45
|
+
o = self.create_object()
|
|
46
|
+
self.assertEqual(o.MixedInOut(2, 4), (3, 5)) # type: ignore
|
|
47
|
+
|
|
48
|
+
def test_getname(self):
|
|
49
|
+
# This tests a tricky bug, introduced with this patch:
|
|
50
|
+
# http://www.python.org/sf/1643874
|
|
51
|
+
#
|
|
52
|
+
# Returning a BSTR as an [out] parameter from a server
|
|
53
|
+
# implementation must transfer the ownership to the caller.
|
|
54
|
+
# When this is not done, the BSTR instance is SysFreeString'd
|
|
55
|
+
# too early, and the memory is reused.
|
|
56
|
+
obj = self.create_object()
|
|
57
|
+
pb = pointer(BSTR())
|
|
58
|
+
# Get the BSTR from the server:
|
|
59
|
+
obj._ITestComServer__com__get_name(pb)
|
|
60
|
+
# Retrieve the value, but keep the pointer to the BSTR alive:
|
|
61
|
+
name = pb[0]
|
|
62
|
+
# Create sme BSTR's to reuse the memory in case it has been freed:
|
|
63
|
+
for i in range(10):
|
|
64
|
+
BSTR("f" * len(name))
|
|
65
|
+
# Make sure the pointer is still valid:
|
|
66
|
+
self.assertEqual(pb[0], name) # type: ignore
|
|
67
|
+
|
|
68
|
+
def test_get_id(self):
|
|
69
|
+
obj = self.create_object()
|
|
70
|
+
self._find_memleak(lambda: obj.id)
|
|
71
|
+
|
|
72
|
+
def test_get_name(self):
|
|
73
|
+
obj = self.create_object()
|
|
74
|
+
self._find_memleak(lambda: obj.name)
|
|
75
|
+
|
|
76
|
+
def test_set_name(self):
|
|
77
|
+
obj = self.create_object()
|
|
78
|
+
|
|
79
|
+
def func():
|
|
80
|
+
obj.name = "abcde"
|
|
81
|
+
|
|
82
|
+
self._find_memleak(func)
|
|
83
|
+
|
|
84
|
+
def test_SetName(self):
|
|
85
|
+
obj = self.create_object()
|
|
86
|
+
|
|
87
|
+
def func():
|
|
88
|
+
obj.SetName("abcde")
|
|
89
|
+
|
|
90
|
+
self._find_memleak(func)
|
|
91
|
+
|
|
92
|
+
def test_eval(self):
|
|
93
|
+
obj = self.create_object()
|
|
94
|
+
|
|
95
|
+
def func():
|
|
96
|
+
return obj.eval("(1, 2, 3)")
|
|
97
|
+
|
|
98
|
+
self.assertEqual(func(), (1, 2, 3)) # type: ignore
|
|
99
|
+
self._find_memleak(func)
|
|
100
|
+
|
|
101
|
+
def test_get_typeinfo(self):
|
|
102
|
+
obj = self.create_object()
|
|
103
|
+
|
|
104
|
+
def func():
|
|
105
|
+
obj.GetTypeInfo(0)
|
|
106
|
+
obj.GetTypeInfoCount()
|
|
107
|
+
obj.QueryInterface(comtypes.IUnknown)
|
|
108
|
+
|
|
109
|
+
self._find_memleak(func)
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
class TestInproc(BaseServerTest, unittest.TestCase):
|
|
113
|
+
def create_object(self):
|
|
114
|
+
return CreateObject(
|
|
115
|
+
"TestComServerLib.TestComServer", clsctx=comtypes.CLSCTX_INPROC_SERVER
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
class TestLocalServer(BaseServerTest, unittest.TestCase):
|
|
120
|
+
def create_object(self):
|
|
121
|
+
return CreateObject(
|
|
122
|
+
"TestComServerLib.TestComServer", clsctx=comtypes.CLSCTX_LOCAL_SERVER
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
@unittest.skip("This fails. Why?")
|
|
126
|
+
def test_get_typeinfo(self):
|
|
127
|
+
# Calling `GetTypeInfo` occurs;
|
|
128
|
+
# OSError: exception: access violation reading 0x0000000000000000
|
|
129
|
+
pass
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
@unittest.skipIf(IMPORT_PYWIN32_FAILED, "This depends on 'pywin32'.")
|
|
133
|
+
class TestInproc_win32com(BaseServerTest, unittest.TestCase):
|
|
134
|
+
def create_object(self):
|
|
135
|
+
return Dispatch("TestComServerLib.TestComServer")
|
|
136
|
+
|
|
137
|
+
# These tests make no sense with win32com, override to disable them:
|
|
138
|
+
@unittest.skip("This test make no sense with win32com.")
|
|
139
|
+
def test_get_typeinfo(self):
|
|
140
|
+
pass
|
|
141
|
+
|
|
142
|
+
@unittest.skip("This test make no sense with win32com.")
|
|
143
|
+
def test_getname(self):
|
|
144
|
+
pass
|
|
145
|
+
|
|
146
|
+
@unittest.skip("This test make no sense with win32com.")
|
|
147
|
+
def test_mixedinout(self):
|
|
148
|
+
# Not sure about this; it raise 'Invalid Number of parameters'
|
|
149
|
+
# Is mixed [in], [out] args not compatible with IDispatch???
|
|
150
|
+
pass
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
@unittest.skipIf(IMPORT_PYWIN32_FAILED, "This depends on 'pywin32'.")
|
|
154
|
+
class TestLocalServer_win32com(BaseServerTest, unittest.TestCase):
|
|
155
|
+
def create_object(self):
|
|
156
|
+
return Dispatch(
|
|
157
|
+
"TestComServerLib.TestComServer", clsctx=comtypes.CLSCTX_LOCAL_SERVER
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
# These tests are skipped for the same reason as `TestInproc_win32com`.
|
|
161
|
+
@unittest.skip("This test make no sense with win32com.")
|
|
162
|
+
def test_get_typeinfo(self):
|
|
163
|
+
pass
|
|
164
|
+
|
|
165
|
+
@unittest.skip("This test make no sense with win32com.")
|
|
166
|
+
def test_getname(self):
|
|
167
|
+
pass
|
|
168
|
+
|
|
169
|
+
@unittest.skip("This test make no sense with win32com.")
|
|
170
|
+
def test_mixedinout(self):
|
|
171
|
+
pass
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
class VariantTest(unittest.TestCase):
|
|
175
|
+
def test_UDT(self):
|
|
176
|
+
from comtypes.gen.TestComServerLib import MYCOLOR
|
|
177
|
+
|
|
178
|
+
v = VARIANT(MYCOLOR(red=1.0, green=2.0, blue=3.0))
|
|
179
|
+
value = v.value
|
|
180
|
+
self.assertEqual(1.0, value.red) # type: ignore
|
|
181
|
+
self.assertEqual(2.0, value.green) # type: ignore
|
|
182
|
+
self.assertEqual(3.0, value.blue) # type: ignore
|
|
183
|
+
|
|
184
|
+
def func():
|
|
185
|
+
v = VARIANT(MYCOLOR(red=1.0, green=2.0, blue=3.0))
|
|
186
|
+
return v.value
|
|
187
|
+
|
|
188
|
+
bytes = find_memleak(func)
|
|
189
|
+
self.assertFalse(bytes, f"Leaks {bytes} bytes") # type: ignore
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
class SafeArrayTest(unittest.TestCase):
|
|
193
|
+
def test_UDT(self):
|
|
194
|
+
from comtypes.gen.TestComServerLib import MYCOLOR
|
|
195
|
+
|
|
196
|
+
t = _midlSAFEARRAY(MYCOLOR)
|
|
197
|
+
self.assertTrue(t is _midlSAFEARRAY(MYCOLOR))
|
|
198
|
+
|
|
199
|
+
sa = t.from_param([MYCOLOR(0, 0, 0), MYCOLOR(1, 2, 3)])
|
|
200
|
+
|
|
201
|
+
self.assertEqual(
|
|
202
|
+
[(x.red, x.green, x.blue) for x in sa[0]],
|
|
203
|
+
[(0.0, 0.0, 0.0), (1.0, 2.0, 3.0)],
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
def doit():
|
|
207
|
+
t.from_param([MYCOLOR(0, 0, 0), MYCOLOR(1, 2, 3)])
|
|
208
|
+
|
|
209
|
+
bytes = find_memleak(doit)
|
|
210
|
+
self.assertFalse(bytes, f"Leaks {bytes} bytes") # type: ignore
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
class PropPutRefTest(unittest.TestCase):
|
|
214
|
+
def doit(self, dynamic: bool):
|
|
215
|
+
d = CreateObject("Scripting.Dictionary", dynamic=dynamic)
|
|
216
|
+
s = CreateObject("TestComServerLib.TestComServer", dynamic=dynamic)
|
|
217
|
+
s.name = "the value"
|
|
218
|
+
|
|
219
|
+
# This calls propputref, since we assign an Object
|
|
220
|
+
d.Item["object"] = s
|
|
221
|
+
# This calls propput, since we assing a Value
|
|
222
|
+
d.Item["value"] = s.name
|
|
223
|
+
|
|
224
|
+
self.assertEqual(d.Item["object"], s)
|
|
225
|
+
self.assertEqual(d.Item["object"].name, "the value")
|
|
226
|
+
self.assertEqual(d.Item["value"], "the value")
|
|
227
|
+
|
|
228
|
+
# Changing the default property of the object
|
|
229
|
+
s.name = "foo bar"
|
|
230
|
+
self.assertEqual(d.Item["object"], s)
|
|
231
|
+
self.assertEqual(d.Item["object"].name, "foo bar")
|
|
232
|
+
self.assertEqual(d.Item["value"], "the value")
|
|
233
|
+
|
|
234
|
+
# This also calls propputref since we assign an Object
|
|
235
|
+
d.Item["var"] = VARIANT(s)
|
|
236
|
+
self.assertEqual(d.Item["var"], s)
|
|
237
|
+
|
|
238
|
+
def test_earlybind(self):
|
|
239
|
+
self.doit(dynamic=False)
|
|
240
|
+
|
|
241
|
+
def test_latebind(self):
|
|
242
|
+
self.doit(dynamic=True)
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
class TestEvents(unittest.TestCase):
|
|
246
|
+
def test(self):
|
|
247
|
+
import comtypes.test.test_comserver
|
|
248
|
+
|
|
249
|
+
doctest.testmod(
|
|
250
|
+
comtypes.test.test_comserver, verbose=False, optionflags=doctest.ELLIPSIS
|
|
251
|
+
)
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
class ShowEventsExamples:
|
|
255
|
+
# The following functions are never called, they only contain doctests:
|
|
256
|
+
|
|
257
|
+
def ShowEventsFloat(self):
|
|
258
|
+
"""
|
|
259
|
+
>>> from comtypes.client import CreateObject, ShowEvents
|
|
260
|
+
>>>
|
|
261
|
+
>>> o = CreateObject("TestComServerLib.TestComServer")
|
|
262
|
+
>>> con = ShowEvents(o)
|
|
263
|
+
# event found: ITestComServerEvents_EvalStarted
|
|
264
|
+
# event found: ITestComServerEvents_EvalCompleted
|
|
265
|
+
>>> result = o.eval("10. / 4")
|
|
266
|
+
Event ITestComServerEvents_EvalStarted(None, '10. / 4')
|
|
267
|
+
Event ITestComServerEvents_EvalCompleted(None, '10. / 4', VARIANT(vt=0x5, 2.5))
|
|
268
|
+
>>> result
|
|
269
|
+
2.5
|
|
270
|
+
>>>
|
|
271
|
+
"""
|
|
272
|
+
|
|
273
|
+
# # The following test, if enabled, works but the testsuit
|
|
274
|
+
# # crashes elsewhere. Is there s problem with SAFEARRAYs?
|
|
275
|
+
|
|
276
|
+
# def Fails(self):
|
|
277
|
+
# """
|
|
278
|
+
# >>> from comtypes.client import CreateObject, ShowEvents
|
|
279
|
+
# >>>
|
|
280
|
+
# >>> o = CreateObject("TestComServerLib.TestComServer")
|
|
281
|
+
# >>> con = ShowEvents(o)
|
|
282
|
+
# # event found: ITestComServerEvents_EvalStarted
|
|
283
|
+
# # event found: ITestComServerEvents_EvalCompleted
|
|
284
|
+
# >>> result = o.eval("['32'] * 2")
|
|
285
|
+
# Event ITestComServerEvents_EvalStarted(None, u"['32'] * 2")
|
|
286
|
+
# Event ITestComServerEvents_EvalCompleted(None, u"['32'] * 2", VARIANT(vt=0x200c, (u'32', u'32')))
|
|
287
|
+
# >>> result
|
|
288
|
+
# (u'32', u'32')
|
|
289
|
+
# >>>
|
|
290
|
+
# """
|
|
291
|
+
|
|
292
|
+
def GetEvents(self):
|
|
293
|
+
"""
|
|
294
|
+
>>> from comtypes.client import CreateObject, GetEvents
|
|
295
|
+
>>>
|
|
296
|
+
>>> o = CreateObject("TestComServerLib.TestComServer")
|
|
297
|
+
>>> class EventHandler(object):
|
|
298
|
+
... def EvalStarted(self, this, what):
|
|
299
|
+
... print("EvalStarted: %s" % what)
|
|
300
|
+
... return 0
|
|
301
|
+
... def EvalCompleted(self, this, what, result):
|
|
302
|
+
... print("EvalCompleted: %s = %s" % (what, result.value))
|
|
303
|
+
... return 0
|
|
304
|
+
...
|
|
305
|
+
>>>
|
|
306
|
+
>>> con = GetEvents(o, EventHandler())
|
|
307
|
+
>>> o.eval("2 + 3")
|
|
308
|
+
EvalStarted: 2 + 3
|
|
309
|
+
EvalCompleted: 2 + 3 = 5
|
|
310
|
+
5
|
|
311
|
+
>>> del con
|
|
312
|
+
>>> o.eval("3 + 2")
|
|
313
|
+
5
|
|
314
|
+
>>>
|
|
315
|
+
"""
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
if __name__ == "__main__":
|
|
319
|
+
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(
|
|
61
|
-
setattr(Test, "test_
|
|
58
|
+
test.__doc__ = f"test GetModule({fname!r})"
|
|
59
|
+
setattr(Test, f"test_{number}", test)
|
|
62
60
|
number += 1
|
|
63
61
|
|
|
64
62
|
|
|
@@ -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()
|
|
@@ -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(
|
|
71
|
-
|
|
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(
|
|
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(
|
|
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]
|
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
import unittest as ut
|
|
2
|
-
from ctypes import
|
|
2
|
+
from ctypes import Structure, c_long, c_uint, c_ulong
|
|
3
3
|
|
|
4
|
-
import comtypes.test
|
|
5
4
|
from comtypes.client import CreateObject, GetEvents
|
|
6
5
|
|
|
7
|
-
comtypes.test.requires("ui")
|
|
8
|
-
|
|
9
6
|
|
|
10
7
|
def setUpModule():
|
|
11
8
|
raise ut.SkipTest(
|
|
@@ -61,7 +58,7 @@ class MSG(Structure):
|
|
|
61
58
|
|
|
62
59
|
|
|
63
60
|
def PumpWaitingMessages():
|
|
64
|
-
from ctypes import
|
|
61
|
+
from ctypes import byref, windll
|
|
65
62
|
|
|
66
63
|
user32 = windll.user32
|
|
67
64
|
msg = MSG()
|
|
@@ -1,11 +1,14 @@
|
|
|
1
|
-
from typing import Any, Callable, List, NamedTuple, Tuple, Type
|
|
2
|
-
from ctypes import POINTER, pointer, Structure, HRESULT, c_ulong, c_wchar_p, c_int
|
|
3
1
|
import unittest as ut
|
|
2
|
+
from ctypes import HRESULT, POINTER, Structure, c_int, c_ulong, c_wchar_p, pointer
|
|
3
|
+
from typing import TYPE_CHECKING, Any, Callable, List, NamedTuple, Tuple, Type
|
|
4
4
|
from unittest.mock import MagicMock
|
|
5
5
|
|
|
6
6
|
import comtypes
|
|
7
|
+
from comtypes._memberspec import _fix_inout_args
|
|
7
8
|
from comtypes.client import IUnknown
|
|
8
|
-
|
|
9
|
+
|
|
10
|
+
if TYPE_CHECKING:
|
|
11
|
+
from comtypes._memberspec import _ArgSpecElmType
|
|
9
12
|
|
|
10
13
|
WSTRING = c_wchar_p
|
|
11
14
|
|
|
@@ -256,7 +259,7 @@ class Test_ArgsKwargsCombinations(ut.TestCase):
|
|
|
256
259
|
|
|
257
260
|
|
|
258
261
|
class PermutedArgspecTestingParams(NamedTuple):
|
|
259
|
-
argspec: Tuple[_ArgSpecElmType, _ArgSpecElmType, _ArgSpecElmType, _ArgSpecElmType]
|
|
262
|
+
argspec: "Tuple[_ArgSpecElmType, _ArgSpecElmType, _ArgSpecElmType, _ArgSpecElmType]"
|
|
260
263
|
args: Tuple[Any, Any, Any]
|
|
261
264
|
orig_ret_val: Tuple[Any, Any, Any]
|
|
262
265
|
fixed_ret_val: List[Any]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# coding: utf-8
|
|
2
2
|
|
|
3
|
-
from ctypes import c_int, pointer, POINTER
|
|
3
|
+
from ctypes import c_int, pointer, HRESULT, POINTER
|
|
4
4
|
import unittest
|
|
5
5
|
|
|
6
6
|
import comtypes
|
|
@@ -82,6 +82,14 @@ class Test_midlSAFEARRAY_create(unittest.TestCase):
|
|
|
82
82
|
self.assertEqual(unpacked.answer, 42)
|
|
83
83
|
self.assertEqual(unpacked.needs_clarification, True)
|
|
84
84
|
|
|
85
|
+
def test_HRESULT(self):
|
|
86
|
+
hr = HRESULT(1)
|
|
87
|
+
sa_type = comtypes.safearray._midlSAFEARRAY(HRESULT)
|
|
88
|
+
with self.assertRaises(TypeError):
|
|
89
|
+
sa_type.create([hr], extra=None)
|
|
90
|
+
with self.assertRaises(TypeError):
|
|
91
|
+
sa_type.create([hr])
|
|
92
|
+
|
|
85
93
|
def test_ctype(self):
|
|
86
94
|
extra = None
|
|
87
95
|
cdata = c_int(1)
|
|
@@ -1,18 +1,25 @@
|
|
|
1
|
-
import sys
|
|
2
1
|
import unittest
|
|
3
|
-
from ctypes import
|
|
2
|
+
from ctypes import (
|
|
3
|
+
POINTER,
|
|
4
|
+
byref,
|
|
5
|
+
c_int,
|
|
6
|
+
c_ulong,
|
|
7
|
+
c_void_p,
|
|
8
|
+
c_wchar,
|
|
9
|
+
c_wchar_p,
|
|
10
|
+
cast,
|
|
11
|
+
memmove,
|
|
12
|
+
oledll,
|
|
13
|
+
sizeof,
|
|
14
|
+
windll,
|
|
15
|
+
wstring_at,
|
|
16
|
+
)
|
|
4
17
|
from unittest.mock import patch
|
|
5
18
|
|
|
6
|
-
import
|
|
19
|
+
from comtypes import COMMETHOD, GUID, IUnknown
|
|
7
20
|
|
|
8
|
-
comtypes.test.requires("devel")
|
|
9
21
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
if sys.version_info >= (3, 0):
|
|
13
|
-
text_type = str
|
|
14
|
-
else:
|
|
15
|
-
text_type = unicode
|
|
22
|
+
text_type = str
|
|
16
23
|
|
|
17
24
|
|
|
18
25
|
class IMalloc(IUnknown):
|