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.
- {comtypes-1.4.10 → comtypes-1.4.12}/CHANGES.txt +48 -0
- {comtypes-1.4.10/comtypes.egg-info → comtypes-1.4.12}/PKG-INFO +4 -3
- {comtypes-1.4.10 → comtypes-1.4.12}/README.md +1 -1
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/__init__.py +11 -5
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/_comobject.py +29 -31
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/_memberspec.py +107 -81
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/_meta.py +1 -1
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/_npsupport.py +12 -17
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/_post_coinit/_cominterface_meta_patcher.py +8 -10
- comtypes-1.4.12/comtypes/_post_coinit/activeobj.py +61 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/_post_coinit/misc.py +1 -23
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/_post_coinit/unknwn.py +33 -26
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/_vtbl.py +55 -58
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/automation.py +19 -23
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/client/__init__.py +2 -1
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/client/_activeobj.py +8 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/client/_code_cache.py +10 -24
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/client/_constants.py +1 -1
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/client/_events.py +92 -54
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/client/_generate.py +1 -3
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/client/dynamic.py +3 -3
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/client/lazybind.py +3 -3
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/connectionpoints.py +37 -3
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/errorinfo.py +54 -16
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/hints.pyi +15 -2
- comtypes-1.4.12/comtypes/hresult.py +159 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/messageloop.py +15 -13
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/patcher.py +2 -2
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/persist.py +9 -2
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/safearray.py +10 -10
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/server/__init__.py +5 -37
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/server/automation.py +2 -2
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/server/connectionpoints.py +71 -70
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/server/inprocserver.py +10 -7
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/server/localserver.py +16 -22
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/server/register.py +7 -7
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_GUID.py +6 -7
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_agilent.py +1 -1
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_basic.py +6 -3
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_client_dynamic.py +1 -1
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_collections.py +6 -3
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_comobject.py +19 -6
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_comserver.py +32 -4
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_createwrappers.py +1 -1
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_dict.py +2 -1
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_dispifc_records.py +0 -2
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_dispifc_safearrays.py +0 -2
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_dispinterface.py +1 -1
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_dyndispatch.py +4 -2
- comtypes-1.4.12/comtypes/test/test_errorinfo.py +115 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_excel.py +1 -3
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_getactiveobj.py +19 -2
- comtypes-1.4.12/comtypes/test/test_hresult.py +87 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_inout_args.py +9 -2
- comtypes-1.4.12/comtypes/test/test_messageloop.py +117 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_midl_safearray_create.py +0 -2
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_msscript.py +1 -1
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_npsupport.py +22 -11
- comtypes-1.4.12/comtypes/test/test_persist.py +71 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_recordinfo.py +0 -2
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_safearray.py +2 -1
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_server.py +6 -6
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_server_register.py +2 -1
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_storage.py +1 -1
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_stream.py +22 -2
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_typeinfo.py +19 -2
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_urlhistory.py +1 -1
- comtypes-1.4.12/comtypes/test/test_util.py +227 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_variant.py +43 -25
- comtypes-1.4.12/comtypes/test/test_viewobject.py +78 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_w_getopt.py +4 -4
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_word.py +1 -1
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/tools/codegenerator/codegenerator.py +1 -1
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/tools/codegenerator/comments.py +1 -1
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/tools/codegenerator/heads.py +5 -5
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/tools/codegenerator/helpers.py +7 -7
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/tools/codegenerator/namespaces.py +3 -3
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/tools/codegenerator/typeannotator.py +2 -2
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/tools/tlbparser.py +8 -7
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/tools/typedesc.py +14 -14
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/tools/typedesc_base.py +19 -19
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/typeinfo.py +14 -9
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/util.py +38 -6
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/viewobject.py +29 -5
- {comtypes-1.4.10 → comtypes-1.4.12/comtypes.egg-info}/PKG-INFO +4 -3
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes.egg-info/SOURCES.txt +6 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/pyproject.toml +13 -7
- comtypes-1.4.10/comtypes/hresult.py +0 -81
- comtypes-1.4.10/comtypes/test/test_persist.py +0 -38
- {comtypes-1.4.10 → comtypes-1.4.12}/LICENSE.txt +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/MANIFEST.in +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/GUID.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/_post_coinit/__init__.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/_post_coinit/bstr.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/_post_coinit/instancemethod.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/_safearray.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/_tlib_version_checker.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/clear_cache.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/client/_create.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/client/_managing.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/git.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/logutil.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/server/w_getopt.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/shelllink.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/stream.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/TestComServer.idl +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/TestComServer.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/TestComServer.tlb +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/TestDispServer.idl +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/TestDispServer.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/TestDispServer.tlb +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/__init__.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/find_memleak.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/mylib.idl +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/mylib.tlb +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/mytypelib.idl +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/runtests.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/setup.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_BSTR.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_DISPPARAMS.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_QueryService.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_avmc.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_casesensitivity.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_clear_cache.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_client.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_client_regenerate_modules.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_findgendir.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_ie.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_ienum.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_imfattributes.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_jscript.js +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_monikers.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_outparam.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_pump_events.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_sapi.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_shelllink.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_showevents.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_subinterface.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_typeannotator.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_win32com_interop.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/test_wmi.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/test/urlhist.tlb +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/tools/__init__.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/tools/codegenerator/__init__.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/tools/codegenerator/modulenamer.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes/tools/codegenerator/packing.py +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes.egg-info/dependency_links.txt +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes.egg-info/entry_points.txt +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/comtypes.egg-info/top_level.txt +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/setup.cfg +0 -0
- {comtypes-1.4.10 → comtypes-1.4.12}/setup.py +0 -0
|
@@ -1,9 +1,13 @@
|
|
|
1
|
+
import contextlib
|
|
1
2
|
import time
|
|
2
3
|
import unittest
|
|
3
4
|
|
|
4
5
|
import comtypes
|
|
5
6
|
import comtypes.client
|
|
6
|
-
|
|
7
|
+
|
|
8
|
+
with contextlib.redirect_stdout(None): # supress warnings
|
|
9
|
+
comtypes.client.GetModule("msvidctl.dll")
|
|
10
|
+
from comtypes.gen import MSVidCtlLib as msvidctl
|
|
7
11
|
|
|
8
12
|
try:
|
|
9
13
|
# pass Word libUUID
|
|
@@ -29,7 +33,7 @@ class Test_Word(unittest.TestCase):
|
|
|
29
33
|
def setUp(self):
|
|
30
34
|
try:
|
|
31
35
|
comtypes.client.GetActiveObject("Word.Application")
|
|
32
|
-
except
|
|
36
|
+
except OSError:
|
|
33
37
|
pass
|
|
34
38
|
else:
|
|
35
39
|
# seems word is running, we cannot test this.
|
|
@@ -67,5 +71,18 @@ class Test_Word(unittest.TestCase):
|
|
|
67
71
|
comtypes.client.GetActiveObject("Word.Application")
|
|
68
72
|
|
|
69
73
|
|
|
74
|
+
class Test_MSVidCtlLib(unittest.TestCase):
|
|
75
|
+
def test_register_and_revoke(self):
|
|
76
|
+
vidctl = comtypes.client.CreateObject(msvidctl.MSVidCtl)
|
|
77
|
+
with self.assertRaises(WindowsError):
|
|
78
|
+
comtypes.client.GetActiveObject(msvidctl.MSVidCtl)
|
|
79
|
+
handle = comtypes.client.RegisterActiveObject(vidctl, msvidctl.MSVidCtl)
|
|
80
|
+
activeobj = comtypes.client.GetActiveObject(msvidctl.MSVidCtl)
|
|
81
|
+
self.assertEqual(vidctl, activeobj)
|
|
82
|
+
comtypes.client.RevokeActiveObject(handle)
|
|
83
|
+
with self.assertRaises(WindowsError):
|
|
84
|
+
comtypes.client.GetActiveObject(msvidctl.MSVidCtl)
|
|
85
|
+
|
|
86
|
+
|
|
70
87
|
if __name__ == "__main__":
|
|
71
88
|
unittest.main()
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import doctest
|
|
2
|
+
import unittest as ut
|
|
3
|
+
|
|
4
|
+
import comtypes.hresult
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class Test_MAKE_HRESULT(ut.TestCase):
|
|
8
|
+
def test(self):
|
|
9
|
+
for sev, fac, code, hr in [
|
|
10
|
+
(0x0000, 0x0000, 0x0000, 0),
|
|
11
|
+
(0x0001, 0x0000, 0x0000, -2147483648),
|
|
12
|
+
(0x0000, 0x0001, 0x0000, 65536),
|
|
13
|
+
(0x0000, 0x0000, 0x0001, 1),
|
|
14
|
+
(0x0001, 0xFFFF, 0xFFFF, -1),
|
|
15
|
+
(0x0000, 0xFFFF, 0xFFFF, -1),
|
|
16
|
+
(0x0001, 0x0000, 0x0001, -2147483647),
|
|
17
|
+
(0x0001, 0x0001, 0x0001, -2147418111),
|
|
18
|
+
(0x0000, 0x0001, 0xFFFF, 131071),
|
|
19
|
+
(0x0001, 0xFFFF, 0x0000, -65536),
|
|
20
|
+
(0x0001, 0x0000, 0xFFFF, -2147418113),
|
|
21
|
+
]:
|
|
22
|
+
with self.subTest(sev=sev, fac=fac, code=code, hr=hr):
|
|
23
|
+
self.assertEqual(comtypes.hresult.MAKE_HRESULT(sev, fac, code), hr)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
ERROR_OUTOFMEMORY = 14 # 0xE
|
|
27
|
+
ERROR_INVALID_PARAMETER = 87 # 0x57
|
|
28
|
+
RPC_S_SERVER_UNAVAILABLE = 1722 # 0x6BA
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class Test_HRESULT_FROM_WIN32(ut.TestCase):
|
|
32
|
+
def test(self):
|
|
33
|
+
for w32, hr in [
|
|
34
|
+
(ERROR_OUTOFMEMORY, comtypes.hresult.E_OUTOFMEMORY),
|
|
35
|
+
(ERROR_INVALID_PARAMETER, comtypes.hresult.E_INVALIDARG),
|
|
36
|
+
(RPC_S_SERVER_UNAVAILABLE, comtypes.hresult.RPC_S_SERVER_UNAVAILABLE),
|
|
37
|
+
(-1, -1),
|
|
38
|
+
(0, -2147024896),
|
|
39
|
+
(1, -2147024895),
|
|
40
|
+
(0xFFFF - 3, -2146959364),
|
|
41
|
+
(0xFFFF - 2, -2146959363),
|
|
42
|
+
(0xFFFF - 1, -2146959362),
|
|
43
|
+
(0xFFFF + 0, -2146959361),
|
|
44
|
+
(0xFFFF + 1, -2147024896),
|
|
45
|
+
(0xFFFF + 2, -2147024895),
|
|
46
|
+
(0xFFFF + 3, -2147024894),
|
|
47
|
+
]:
|
|
48
|
+
with self.subTest(w32=w32, hr=hr):
|
|
49
|
+
self.assertEqual(comtypes.hresult.HRESULT_FROM_WIN32(w32), hr)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
class Test_signed32bithex_to_int(ut.TestCase):
|
|
53
|
+
def test(self):
|
|
54
|
+
for val, expected in [
|
|
55
|
+
("0x00000000", comtypes.hresult.S_OK),
|
|
56
|
+
("0x00000001", comtypes.hresult.S_FALSE),
|
|
57
|
+
("0x8000FFFF", comtypes.hresult.E_UNEXPECTED),
|
|
58
|
+
("0x80004002", comtypes.hresult.E_NOINTERFACE),
|
|
59
|
+
# boundary values
|
|
60
|
+
("0x7FFFFFFF", 2147483647),
|
|
61
|
+
("0x80000000", -2147483648),
|
|
62
|
+
("0xFFFFFFFF", -1),
|
|
63
|
+
]:
|
|
64
|
+
with self.subTest(val=val, expected=expected):
|
|
65
|
+
self.assertEqual(comtypes.hresult.signed32bithex_to_int(val), expected)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
class Test_int_to_signed32bithex(ut.TestCase):
|
|
69
|
+
def test(self):
|
|
70
|
+
for val, expected in [
|
|
71
|
+
(comtypes.hresult.S_OK, "0x00000000"),
|
|
72
|
+
(comtypes.hresult.S_FALSE, "0x00000001"),
|
|
73
|
+
(comtypes.hresult.E_UNEXPECTED, "0x8000FFFF"),
|
|
74
|
+
(comtypes.hresult.E_NOINTERFACE, "0x80004002"),
|
|
75
|
+
]:
|
|
76
|
+
with self.subTest(val=val, expected=expected):
|
|
77
|
+
self.assertEqual(comtypes.hresult.int_to_signed32bithex(val), expected)
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
class DocTest(ut.TestCase):
|
|
81
|
+
def test(self):
|
|
82
|
+
doctest.testmod(
|
|
83
|
+
comtypes.hresult,
|
|
84
|
+
verbose=False,
|
|
85
|
+
optionflags=doctest.ELLIPSIS,
|
|
86
|
+
raise_on_error=True,
|
|
87
|
+
)
|
|
@@ -8,7 +8,14 @@ from comtypes import IUnknown
|
|
|
8
8
|
from comtypes._memberspec import _fix_inout_args
|
|
9
9
|
|
|
10
10
|
if TYPE_CHECKING:
|
|
11
|
-
from comtypes
|
|
11
|
+
from comtypes import hints # type: ignore
|
|
12
|
+
|
|
13
|
+
_ArgSpecType = Tuple[
|
|
14
|
+
hints.ArgSpecElmType,
|
|
15
|
+
hints.ArgSpecElmType,
|
|
16
|
+
hints.ArgSpecElmType,
|
|
17
|
+
hints.ArgSpecElmType,
|
|
18
|
+
]
|
|
12
19
|
|
|
13
20
|
WSTRING = c_wchar_p
|
|
14
21
|
|
|
@@ -259,7 +266,7 @@ class Test_ArgsKwargsCombinations(ut.TestCase):
|
|
|
259
266
|
|
|
260
267
|
|
|
261
268
|
class PermutedArgspecTestingParams(NamedTuple):
|
|
262
|
-
argspec: "
|
|
269
|
+
argspec: "_ArgSpecType"
|
|
263
270
|
args: Tuple[Any, Any, Any]
|
|
264
271
|
orig_ret_val: Tuple[Any, Any, Any]
|
|
265
272
|
fixed_ret_val: List[Any]
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import threading
|
|
2
|
+
import time
|
|
3
|
+
import unittest
|
|
4
|
+
from ctypes import WinDLL
|
|
5
|
+
from typing import Tuple
|
|
6
|
+
from unittest.mock import Mock, patch
|
|
7
|
+
|
|
8
|
+
import comtypes.messageloop
|
|
9
|
+
from comtypes.messageloop import _MessageLoop
|
|
10
|
+
|
|
11
|
+
_user32 = WinDLL("user32")
|
|
12
|
+
_kernel32 = WinDLL("kernel32")
|
|
13
|
+
|
|
14
|
+
PostThreadMessageW = _user32.PostThreadMessageW
|
|
15
|
+
PostQuitMessage = _user32.PostQuitMessage
|
|
16
|
+
GetCurrentThreadId = _kernel32.GetCurrentThreadId
|
|
17
|
+
|
|
18
|
+
WM_QUIT = 0x0012
|
|
19
|
+
WM_USER = 0x0400
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class InsertAndRemoveFilterTest(unittest.TestCase):
|
|
23
|
+
def test_insert_and_remove_filter(self):
|
|
24
|
+
msgloop = _MessageLoop()
|
|
25
|
+
flt = Mock(return_value=[False])
|
|
26
|
+
msgloop.insert_filter(flt)
|
|
27
|
+
msgloop.remove_filter(flt)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class RunInThreadTest(unittest.TestCase):
|
|
31
|
+
def setUp(self):
|
|
32
|
+
self.msgloop = _MessageLoop()
|
|
33
|
+
|
|
34
|
+
def run_msgloop_in_thread(self) -> Tuple[threading.Thread, int]:
|
|
35
|
+
"""Helper method to run message loop in a separate thread."""
|
|
36
|
+
thread_ids = []
|
|
37
|
+
|
|
38
|
+
def thread_target():
|
|
39
|
+
with threading.Lock():
|
|
40
|
+
thread_ids.append(GetCurrentThreadId())
|
|
41
|
+
self.msgloop.run()
|
|
42
|
+
|
|
43
|
+
th = threading.Thread(target=thread_target, daemon=True)
|
|
44
|
+
th.start()
|
|
45
|
+
time.sleep(0.1) # Give thread time to start
|
|
46
|
+
assert len(thread_ids) == 1, "Thread ID was not captured"
|
|
47
|
+
return th, thread_ids[0]
|
|
48
|
+
|
|
49
|
+
def test_quit_message(self):
|
|
50
|
+
th, thread_id = self.run_msgloop_in_thread()
|
|
51
|
+
# Post WM_QUIT to terminate the message loop
|
|
52
|
+
PostThreadMessageW(thread_id, WM_QUIT, 0, 0)
|
|
53
|
+
th.join(timeout=1.0) # Ensure the thread completes
|
|
54
|
+
self.assertFalse(th.is_alive())
|
|
55
|
+
|
|
56
|
+
def test_blocking_filter(self):
|
|
57
|
+
blocking_filter = Mock(return_value=[True]) # Blocking
|
|
58
|
+
self.msgloop.insert_filter(blocking_filter)
|
|
59
|
+
th, thread_id = self.run_msgloop_in_thread()
|
|
60
|
+
# Post a regular message first (should be filtered)
|
|
61
|
+
PostThreadMessageW(thread_id, WM_USER, 0, 0)
|
|
62
|
+
time.sleep(0.1) # Give time for message processing
|
|
63
|
+
# Post WM_QUIT to terminate the message loop
|
|
64
|
+
PostThreadMessageW(thread_id, WM_QUIT, 0, 0)
|
|
65
|
+
th.join(timeout=2.0) # Wait for completion
|
|
66
|
+
self.assertFalse(th.is_alive())
|
|
67
|
+
blocking_filter.assert_called()
|
|
68
|
+
|
|
69
|
+
def test_nonblocking_filter(self):
|
|
70
|
+
message_filter = Mock(return_value=[]) # Non-blocking
|
|
71
|
+
self.msgloop.insert_filter(message_filter)
|
|
72
|
+
th, thread_id = self.run_msgloop_in_thread()
|
|
73
|
+
# Post some test messages
|
|
74
|
+
PostThreadMessageW(thread_id, WM_USER, 123, 456)
|
|
75
|
+
PostThreadMessageW(thread_id, WM_USER, 789, 101112)
|
|
76
|
+
time.sleep(0.3) # Give time for message processing
|
|
77
|
+
# Post WM_QUIT to terminate the message loop
|
|
78
|
+
PostThreadMessageW(thread_id, WM_QUIT, 0, 0)
|
|
79
|
+
th.join(timeout=2.0) # Wait for completion
|
|
80
|
+
self.assertFalse(th.is_alive())
|
|
81
|
+
message_filter.assert_called()
|
|
82
|
+
|
|
83
|
+
def test_multiple_filters(self):
|
|
84
|
+
filter1 = Mock(return_value=[]) # Non-blocking
|
|
85
|
+
filter2 = Mock(return_value=[True]) # Blocking
|
|
86
|
+
filter3 = Mock(return_value=[]) # should not be called
|
|
87
|
+
self.msgloop.insert_filter(filter1, index=0)
|
|
88
|
+
self.msgloop.insert_filter(filter2, index=1)
|
|
89
|
+
self.msgloop.insert_filter(filter3, index=2)
|
|
90
|
+
th, thread_id = self.run_msgloop_in_thread()
|
|
91
|
+
PostThreadMessageW(thread_id, WM_USER, 123, 456)
|
|
92
|
+
time.sleep(1.0) # Give time for message processing
|
|
93
|
+
# Post WM_QUIT to terminate the message loop
|
|
94
|
+
PostThreadMessageW(thread_id, WM_QUIT, 0, 0)
|
|
95
|
+
th.join(timeout=2.0) # Wait for completion
|
|
96
|
+
self.assertFalse(th.is_alive())
|
|
97
|
+
# any() evaluates filters in order: filter1 (falsy) then filter2 (truthy)
|
|
98
|
+
# any() stops at filter2 because it returns a truthy value.
|
|
99
|
+
filter1.assert_called()
|
|
100
|
+
filter2.assert_called()
|
|
101
|
+
filter3.assert_not_called()
|
|
102
|
+
|
|
103
|
+
def test_raises_error_on_getmsg(self):
|
|
104
|
+
# Mock GetMessage to return -1 (error condition)
|
|
105
|
+
with patch.object(comtypes.messageloop, "GetMessage", return_value=-1):
|
|
106
|
+
with self.assertRaises(OSError):
|
|
107
|
+
self.msgloop.run()
|
|
108
|
+
|
|
109
|
+
def test_exit_normally_without_error(self):
|
|
110
|
+
def run_and_exit_quickly():
|
|
111
|
+
PostQuitMessage(0) # Exit immediately
|
|
112
|
+
self.msgloop.run()
|
|
113
|
+
|
|
114
|
+
th = threading.Thread(target=run_and_exit_quickly, daemon=True)
|
|
115
|
+
th.start()
|
|
116
|
+
th.join(timeout=1.0)
|
|
117
|
+
self.assertFalse(th.is_alive())
|
|
@@ -3,7 +3,7 @@ import functools
|
|
|
3
3
|
import importlib
|
|
4
4
|
import inspect
|
|
5
5
|
import unittest
|
|
6
|
-
from ctypes import POINTER, c_double, c_long, pointer
|
|
6
|
+
from ctypes import POINTER, c_double, c_long, c_longlong, pointer
|
|
7
7
|
from decimal import Decimal
|
|
8
8
|
|
|
9
9
|
import comtypes._npsupport
|
|
@@ -16,6 +16,7 @@ from comtypes.automation import (
|
|
|
16
16
|
VT_BSTR,
|
|
17
17
|
VT_DATE,
|
|
18
18
|
VT_I4,
|
|
19
|
+
VT_I8,
|
|
19
20
|
VT_VARIANT,
|
|
20
21
|
_midlSAFEARRAY,
|
|
21
22
|
)
|
|
@@ -23,13 +24,15 @@ from comtypes.safearray import safearray_as_ndarray
|
|
|
23
24
|
|
|
24
25
|
try:
|
|
25
26
|
import numpy
|
|
27
|
+
|
|
28
|
+
IMPORT_NUMPY_FAILED = False
|
|
26
29
|
except ImportError:
|
|
27
|
-
|
|
30
|
+
IMPORT_NUMPY_FAILED = True
|
|
28
31
|
|
|
29
32
|
|
|
30
33
|
def setUpModule():
|
|
31
34
|
"""Only run the module if we can import numpy."""
|
|
32
|
-
if
|
|
35
|
+
if IMPORT_NUMPY_FAILED:
|
|
33
36
|
raise unittest.SkipTest("Skipping test_npsupport as numpy not installed.")
|
|
34
37
|
|
|
35
38
|
|
|
@@ -70,9 +73,7 @@ def enabled_disabled(disabled_error):
|
|
|
70
73
|
from comtypes import npsupport
|
|
71
74
|
|
|
72
75
|
if npsupport.enabled:
|
|
73
|
-
raise
|
|
74
|
-
"Expected numpy interop not to be enabled but it is."
|
|
75
|
-
)
|
|
76
|
+
raise OSError("Expected numpy interop not to be enabled but it is.")
|
|
76
77
|
with self.assertRaises(disabled_error):
|
|
77
78
|
func(self)
|
|
78
79
|
|
|
@@ -112,10 +113,6 @@ class NumpySupportTestCase(unittest.TestCase):
|
|
|
112
113
|
self.assertTrue(isinstance(fourth, numpy.ndarray))
|
|
113
114
|
self.assertTrue(isinstance(fifth, tuple))
|
|
114
115
|
|
|
115
|
-
@unittest.skip(
|
|
116
|
-
"Skipping because numpy cannot currently create an array of variants "
|
|
117
|
-
"because it doesn't recognise the VARIANT_BOOL typecode 'v'."
|
|
118
|
-
)
|
|
119
116
|
def test_datetime64_ndarray(self):
|
|
120
117
|
comtypes.npsupport.enable()
|
|
121
118
|
dates = numpy.array(
|
|
@@ -184,7 +181,7 @@ class NumpySupportTestCase(unittest.TestCase):
|
|
|
184
181
|
def test_VT_I4_ndarray(self):
|
|
185
182
|
t = _midlSAFEARRAY(c_long)
|
|
186
183
|
|
|
187
|
-
in_arr = numpy.array([11, 22, 33])
|
|
184
|
+
in_arr = numpy.array([11, 22, 33], dtype=numpy.int32)
|
|
188
185
|
sa = t.from_param(in_arr)
|
|
189
186
|
|
|
190
187
|
arr = get_ndarray(sa)
|
|
@@ -194,6 +191,20 @@ class NumpySupportTestCase(unittest.TestCase):
|
|
|
194
191
|
self.assertTrue((arr == in_arr).all())
|
|
195
192
|
self.assertEqual(SafeArrayGetVartype(sa), VT_I4)
|
|
196
193
|
|
|
194
|
+
@enabled_disabled(disabled_error=ValueError)
|
|
195
|
+
def test_VT_I8_ndarray(self):
|
|
196
|
+
t = _midlSAFEARRAY(c_longlong)
|
|
197
|
+
|
|
198
|
+
in_arr = numpy.array([11, 22, 33], dtype=numpy.int64)
|
|
199
|
+
sa = t.from_param(in_arr)
|
|
200
|
+
|
|
201
|
+
arr = get_ndarray(sa)
|
|
202
|
+
|
|
203
|
+
self.assertTrue(isinstance(arr, numpy.ndarray))
|
|
204
|
+
self.assertEqual(numpy.dtype(int), arr.dtype)
|
|
205
|
+
self.assertTrue((arr == in_arr).all())
|
|
206
|
+
self.assertEqual(SafeArrayGetVartype(sa), VT_I8)
|
|
207
|
+
|
|
197
208
|
@enabled_disabled(disabled_error=ValueError)
|
|
198
209
|
def test_array(self):
|
|
199
210
|
t = _midlSAFEARRAY(c_double)
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import tempfile
|
|
2
|
+
import unittest as ut
|
|
3
|
+
from _ctypes import COMError
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
from comtypes import GUID, CoCreateInstance, IPersist, hresult, persist
|
|
7
|
+
from comtypes.automation import VARIANT
|
|
8
|
+
|
|
9
|
+
CLSID_ShellLink = GUID("{00021401-0000-0000-C000-000000000046}")
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class Test_IPersist(ut.TestCase):
|
|
13
|
+
def test_GetClassID(self):
|
|
14
|
+
p = CoCreateInstance(CLSID_ShellLink).QueryInterface(IPersist)
|
|
15
|
+
self.assertEqual(p.GetClassID(), CLSID_ShellLink)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class Test_IPersistFile(ut.TestCase):
|
|
19
|
+
def setUp(self):
|
|
20
|
+
td = tempfile.TemporaryDirectory()
|
|
21
|
+
self.addCleanup(td.cleanup)
|
|
22
|
+
self.tmp_dir = Path(td.name)
|
|
23
|
+
|
|
24
|
+
def _create_pf(self) -> persist.IPersistFile:
|
|
25
|
+
return CoCreateInstance(CLSID_ShellLink).QueryInterface(persist.IPersistFile)
|
|
26
|
+
|
|
27
|
+
def test_load(self):
|
|
28
|
+
pf = self._create_pf()
|
|
29
|
+
tgt_file = (self.tmp_dir / "tgt.txt").resolve()
|
|
30
|
+
tgt_file.touch()
|
|
31
|
+
pf.Load(str(tgt_file), persist.STGM_DIRECT)
|
|
32
|
+
self.assertEqual(pf.GetCurFile(), str(tgt_file))
|
|
33
|
+
|
|
34
|
+
def test_save(self):
|
|
35
|
+
pf = self._create_pf()
|
|
36
|
+
tgt_file = self.tmp_dir / "tgt.txt"
|
|
37
|
+
self.assertFalse(tgt_file.exists())
|
|
38
|
+
pf.Save(str(tgt_file), True)
|
|
39
|
+
self.assertEqual(pf.GetCurFile(), str(tgt_file))
|
|
40
|
+
self.assertTrue(tgt_file.exists())
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class Test_DictPropertyBag(ut.TestCase):
|
|
44
|
+
def create_itf_ptr(self) -> persist.IPropertyBag:
|
|
45
|
+
# Create a DictPropertyBag instance with some initial values
|
|
46
|
+
impl = persist.DictPropertyBag(Key1="value1", Key2=123, Key3=True)
|
|
47
|
+
# Get the IPropertyBag interface pointer
|
|
48
|
+
itf = impl.QueryInterface(persist.IPropertyBag)
|
|
49
|
+
return itf
|
|
50
|
+
|
|
51
|
+
def test_read_existing_properties(self):
|
|
52
|
+
itf = self.create_itf_ptr()
|
|
53
|
+
self.assertEqual(itf.Read("Key1", VARIANT(), None), "value1")
|
|
54
|
+
self.assertEqual(itf.Read("Key2", VARIANT(), None), 123)
|
|
55
|
+
self.assertEqual(itf.Read("Key3", VARIANT(), None), True)
|
|
56
|
+
|
|
57
|
+
def test_write_new_property(self):
|
|
58
|
+
itf = self.create_itf_ptr()
|
|
59
|
+
itf.Write("Key4", "new_value")
|
|
60
|
+
self.assertEqual(itf.Read("Key4", VARIANT(), None), "new_value")
|
|
61
|
+
|
|
62
|
+
def test_update_existing_property(self):
|
|
63
|
+
itf = self.create_itf_ptr()
|
|
64
|
+
itf.Write("Key1", "updated_value")
|
|
65
|
+
self.assertEqual(itf.Read("Key1", VARIANT(), None), "updated_value")
|
|
66
|
+
|
|
67
|
+
def test_read_non_existent_property(self):
|
|
68
|
+
itf = self.create_itf_ptr()
|
|
69
|
+
with self.assertRaises(COMError) as cm:
|
|
70
|
+
itf.Read("NonExistentProp", VARIANT(), None)
|
|
71
|
+
self.assertEqual(cm.exception.hresult, hresult.E_INVALIDARG)
|
|
@@ -129,7 +129,8 @@ class SafeArrayTestCase(unittest.TestCase):
|
|
|
129
129
|
self.assertEqual(SafeArrayGetVartype(sa), VT_I4)
|
|
130
130
|
|
|
131
131
|
# TypeError: len() of unsized object
|
|
132
|
-
self.assertRaises(TypeError
|
|
132
|
+
with self.assertRaises(TypeError):
|
|
133
|
+
t.from_param(object())
|
|
133
134
|
|
|
134
135
|
def test_VT_VARIANT(self):
|
|
135
136
|
t = _midlSAFEARRAY(VARIANT)
|
|
@@ -8,7 +8,7 @@ import comtypes.typeinfo
|
|
|
8
8
|
raise unittest.SkipTest("This test module cannot run as-is. Investigate why")
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
class TypeLib
|
|
11
|
+
class TypeLib:
|
|
12
12
|
"""This class collects IDL code fragments and eventually writes
|
|
13
13
|
them into a .IDL file. The compile() method compiles the IDL file
|
|
14
14
|
into a typelibrary and registers it. A function is also
|
|
@@ -64,7 +64,7 @@ class TypeLib(object):
|
|
|
64
64
|
return tlb_path
|
|
65
65
|
|
|
66
66
|
|
|
67
|
-
class Interface
|
|
67
|
+
class Interface:
|
|
68
68
|
def __init__(self, header):
|
|
69
69
|
self.header = header
|
|
70
70
|
self.code = ""
|
|
@@ -257,7 +257,7 @@ class MyServer(comtypes.CoClass, ConnectableObjectMixin):
|
|
|
257
257
|
def test_events(self):
|
|
258
258
|
p = wrap(self.create())
|
|
259
259
|
|
|
260
|
-
class Handler
|
|
260
|
+
class Handler:
|
|
261
261
|
called = 0
|
|
262
262
|
|
|
263
263
|
def OnSomething(self, this):
|
|
@@ -269,7 +269,7 @@ class MyServer(comtypes.CoClass, ConnectableObjectMixin):
|
|
|
269
269
|
p.DoSomething()
|
|
270
270
|
self.assertEqual(handler.called, 1)
|
|
271
271
|
|
|
272
|
-
class Handler
|
|
272
|
+
class Handler:
|
|
273
273
|
called = 0
|
|
274
274
|
|
|
275
275
|
def IMyEventInterface_OnSomething(self):
|
|
@@ -292,7 +292,7 @@ class MyServer(comtypes.CoClass, ConnectableObjectMixin):
|
|
|
292
292
|
def test_DoSomethingElse(self):
|
|
293
293
|
p = wrap(self.create())
|
|
294
294
|
|
|
295
|
-
class Handler
|
|
295
|
+
class Handler:
|
|
296
296
|
called = 0
|
|
297
297
|
|
|
298
298
|
def OnSomethingElse(self):
|
|
@@ -305,7 +305,7 @@ class MyServer(comtypes.CoClass, ConnectableObjectMixin):
|
|
|
305
305
|
p.DoSomethingElse()
|
|
306
306
|
self.assertEqual(handler.called, 1)
|
|
307
307
|
|
|
308
|
-
class Handler
|
|
308
|
+
class Handler:
|
|
309
309
|
called = 0
|
|
310
310
|
|
|
311
311
|
def OnSomethingElse(self, this, presult):
|
|
@@ -3,6 +3,7 @@ import os
|
|
|
3
3
|
import sys
|
|
4
4
|
import unittest as ut
|
|
5
5
|
import winreg
|
|
6
|
+
from ctypes.wintypes import MAX_PATH
|
|
6
7
|
from unittest import mock
|
|
7
8
|
|
|
8
9
|
import comtypes
|
|
@@ -236,7 +237,7 @@ class Test_get_serverdll(ut.TestCase):
|
|
|
236
237
|
self.assertEqual(dll_path, _get_serverdll(handle))
|
|
237
238
|
(((hmodule, maxsize), _),) = GetModuleFileName.call_args_list
|
|
238
239
|
self.assertEqual(handle, hmodule)
|
|
239
|
-
self.assertEqual(
|
|
240
|
+
self.assertEqual(MAX_PATH, maxsize)
|
|
240
241
|
|
|
241
242
|
|
|
242
243
|
class Test_InterpRegistryEntries(ut.TestCase):
|
|
@@ -58,7 +58,7 @@ class Test_IStorage(unittest.TestCase):
|
|
|
58
58
|
filepath = Path(storage.Stat(STATFLAG_DEFAULT).pwcsName)
|
|
59
59
|
self.assertTrue(filepath.exists())
|
|
60
60
|
stream = storage.CreateStream("example", self.CREATE_STM_FLAG, 0, 0)
|
|
61
|
-
test_data = "Some data"
|
|
61
|
+
test_data = b"Some data"
|
|
62
62
|
pv = (c_ubyte * len(test_data)).from_buffer(bytearray(test_data))
|
|
63
63
|
stream.RemoteWrite(pv, len(test_data))
|
|
64
64
|
stream.Commit(STGC_DEFAULT)
|
|
@@ -7,7 +7,9 @@ import comtypes.client
|
|
|
7
7
|
comtypes.client.GetModule("portabledeviceapi.dll")
|
|
8
8
|
from comtypes.gen.PortableDeviceApiLib import IStream
|
|
9
9
|
|
|
10
|
+
STATFLAG_DEFAULT = 0
|
|
10
11
|
STGC_DEFAULT = 0
|
|
12
|
+
STGTY_STREAM = 2
|
|
11
13
|
STREAM_SEEK_SET = 0
|
|
12
14
|
STREAM_SEEK_CUR = 1
|
|
13
15
|
STREAM_SEEK_END = 2
|
|
@@ -35,7 +37,7 @@ def _create_stream() -> IStream:
|
|
|
35
37
|
class Test_RemoteWrite(ut.TestCase):
|
|
36
38
|
def test_RemoteWrite(self):
|
|
37
39
|
stream = _create_stream()
|
|
38
|
-
test_data = "Some data"
|
|
40
|
+
test_data = b"Some data"
|
|
39
41
|
pv = (c_ubyte * len(test_data)).from_buffer(bytearray(test_data))
|
|
40
42
|
|
|
41
43
|
written = stream.RemoteWrite(pv, len(test_data))
|
|
@@ -47,7 +49,7 @@ class Test_RemoteWrite(ut.TestCase):
|
|
|
47
49
|
class Test_RemoteRead(ut.TestCase):
|
|
48
50
|
def test_RemoteRead(self):
|
|
49
51
|
stream = _create_stream()
|
|
50
|
-
test_data = "Some data"
|
|
52
|
+
test_data = b"Some data"
|
|
51
53
|
pv = (c_ubyte * len(test_data)).from_buffer(bytearray(test_data))
|
|
52
54
|
stream.RemoteWrite(pv, len(test_data))
|
|
53
55
|
|
|
@@ -125,6 +127,24 @@ class Test_RemoteCopyTo(ut.TestCase):
|
|
|
125
127
|
self.assertEqual(bytearray(dst_buf)[0:dst_read], test_data)
|
|
126
128
|
|
|
127
129
|
|
|
130
|
+
class Test_Stat(ut.TestCase):
|
|
131
|
+
# https://learn.microsoft.com/en-us/windows/win32/api/objidl/nf-objidl-istream-stat
|
|
132
|
+
# https://learn.microsoft.com/en-us/windows/win32/api/objidl/ns-objidl-statstg
|
|
133
|
+
def test_returns_statstg_from_no_modified_stream(self):
|
|
134
|
+
stream = _create_stream()
|
|
135
|
+
statstg = stream.Stat(STATFLAG_DEFAULT)
|
|
136
|
+
self.assertIsNone(statstg.pwcsName)
|
|
137
|
+
self.assertEqual(statstg.type, STGTY_STREAM)
|
|
138
|
+
self.assertEqual(statstg.cbSize, 0)
|
|
139
|
+
mt, ct, at = statstg.mtime, statstg.ctime, statstg.atime
|
|
140
|
+
self.assertTrue(mt.dwLowDateTime == ct.dwLowDateTime == at.dwLowDateTime)
|
|
141
|
+
self.assertTrue(mt.dwHighDateTime == ct.dwHighDateTime == at.dwHighDateTime)
|
|
142
|
+
self.assertEqual(statstg.grfMode, 0)
|
|
143
|
+
self.assertEqual(statstg.grfLocksSupported, 0)
|
|
144
|
+
self.assertEqual(statstg.clsid, comtypes.GUID())
|
|
145
|
+
self.assertEqual(statstg.grfStateBits, 0)
|
|
146
|
+
|
|
147
|
+
|
|
128
148
|
class Test_Clone(ut.TestCase):
|
|
129
149
|
def test_Clone(self):
|
|
130
150
|
orig = _create_stream()
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import ctypes
|
|
2
2
|
import sys
|
|
3
3
|
import unittest
|
|
4
|
+
from ctypes.wintypes import MAX_PATH
|
|
4
5
|
|
|
5
6
|
from comtypes import GUID, COMError
|
|
6
7
|
from comtypes.typeinfo import (
|
|
@@ -96,14 +97,30 @@ class Test(unittest.TestCase):
|
|
|
96
97
|
|
|
97
98
|
class Test_GetModuleFileName(unittest.TestCase):
|
|
98
99
|
def test_null_handler(self):
|
|
99
|
-
self.assertEqual(GetModuleFileName(None,
|
|
100
|
+
self.assertEqual(GetModuleFileName(None, MAX_PATH), sys.executable)
|
|
100
101
|
|
|
101
102
|
def test_loaded_module_handle(self):
|
|
102
103
|
import _ctypes
|
|
103
104
|
|
|
104
105
|
dll_path = _ctypes.__file__
|
|
105
106
|
hmodule = ctypes.WinDLL(dll_path)._handle
|
|
106
|
-
self.assertEqual(GetModuleFileName(hmodule,
|
|
107
|
+
self.assertEqual(GetModuleFileName(hmodule, MAX_PATH), dll_path)
|
|
108
|
+
|
|
109
|
+
def test_invalid_handle(self):
|
|
110
|
+
with self.assertRaises(OSError) as ce:
|
|
111
|
+
GetModuleFileName(1, MAX_PATH)
|
|
112
|
+
ERROR_MOD_NOT_FOUND = 126
|
|
113
|
+
self.assertEqual(ce.exception.winerror, ERROR_MOD_NOT_FOUND)
|
|
114
|
+
|
|
115
|
+
def test_invalid_nsize(self):
|
|
116
|
+
import _ctypes
|
|
117
|
+
|
|
118
|
+
dll_path = _ctypes.__file__
|
|
119
|
+
hmodule = ctypes.WinDLL(dll_path)._handle
|
|
120
|
+
with self.assertRaises(OSError) as ce:
|
|
121
|
+
GetModuleFileName(hmodule, 0)
|
|
122
|
+
ERROR_INSUFFICIENT_BUFFER = 122
|
|
123
|
+
self.assertEqual(ce.exception.winerror, ERROR_INSUFFICIENT_BUFFER)
|
|
107
124
|
|
|
108
125
|
|
|
109
126
|
if __name__ == "__main__":
|
|
@@ -18,7 +18,7 @@ from comtypes.gen import urlhistLib
|
|
|
18
18
|
# generated code directly is to monkey-patch the
|
|
19
19
|
# _STATURL.__ctypes_from_outparam__ method like this.
|
|
20
20
|
@Patch(urlhistLib._STATURL)
|
|
21
|
-
class _
|
|
21
|
+
class _:
|
|
22
22
|
def __ctypes_from_outparam__(self):
|
|
23
23
|
from comtypes.util import cast_field
|
|
24
24
|
|