comtypes 1.4.5__zip → 1.4.7__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.5 → comtypes-1.4.7}/CHANGES.txt +30 -0
- {comtypes-1.4.5/comtypes.egg-info → comtypes-1.4.7}/PKG-INFO +28 -36
- {comtypes-1.4.5 → comtypes-1.4.7}/README.md +26 -34
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/GUID.py +24 -24
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/__init__.py +1 -1
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/_memberspec.py +4 -12
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/_post_coinit/bstr.py +13 -6
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/automation.py +21 -54
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/client/__init__.py +2 -9
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/client/_code_cache.py +2 -2
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/hints.pyi +8 -18
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/persist.py +19 -3
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/shelllink.py +72 -21
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/test/test_client.py +9 -0
- comtypes-1.4.7/comtypes/test/test_monikers.py +70 -0
- comtypes-1.4.7/comtypes/test/test_persist.py +40 -0
- comtypes-1.4.7/comtypes/test/test_recordinfo.py +79 -0
- comtypes-1.4.7/comtypes/test/test_shelllink.py +133 -0
- comtypes-1.4.7/comtypes/test/test_storage.py +127 -0
- comtypes-1.4.7/comtypes/test/test_typeannotator.py +127 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/tools/codegenerator/codegenerator.py +0 -1
- comtypes-1.4.7/comtypes/tools/codegenerator/modulenamer.py +23 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/tools/codegenerator/typeannotator.py +27 -22
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/tools/tlbparser.py +22 -24
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/tools/typedesc_base.py +2 -8
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/typeinfo.py +57 -56
- {comtypes-1.4.5 → comtypes-1.4.7/comtypes.egg-info}/PKG-INFO +28 -36
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes.egg-info/SOURCES.txt +7 -1
- {comtypes-1.4.5 → comtypes-1.4.7}/setup.cfg +1 -1
- comtypes-1.4.5/comtypes/tools/codegenerator/modulenamer.py +0 -24
- {comtypes-1.4.5 → comtypes-1.4.7}/LICENSE.txt +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/MANIFEST.in +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/_comobject.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/_idl_stuff.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/_meta.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/_npsupport.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/_post_coinit/__init__.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/_post_coinit/misc.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/_post_coinit/unknwn.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/_py_instance_method.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/_safearray.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/_tlib_version_checker.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/clear_cache.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/client/_constants.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/client/_events.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/client/_generate.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/client/dynamic.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/client/lazybind.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/connectionpoints.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/errorinfo.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/git.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/hresult.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/logutil.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/messageloop.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/patcher.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/safearray.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/server/__init__.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/server/automation.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/server/connectionpoints.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/server/inprocserver.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/server/localserver.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/server/register.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/server/w_getopt.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/stream.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/test/TestComServer.idl +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/test/TestComServer.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/test/TestComServer.tlb +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/test/TestDispServer.idl +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/test/TestDispServer.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/test/TestDispServer.tlb +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/test/__init__.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/test/find_memleak.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/test/mylib.idl +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/test/mylib.tlb +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/test/mytypelib.idl +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/test/runtests.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/test/setup.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/test/test_BSTR.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/test/test_DISPPARAMS.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/test/test_GUID.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/test/test_QueryService.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/test/test_agilent.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/test/test_avmc.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/test/test_basic.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/test/test_casesensitivity.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/test/test_clear_cache.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/test/test_client_dynamic.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/test/test_client_regenerate_modules.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/test/test_collections.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/test/test_comserver.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/test/test_createwrappers.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/test/test_dict.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/test/test_dispifc_records.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/test/test_dispifc_safearrays.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/test/test_dispinterface.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/test/test_dyndispatch.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/test/test_excel.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/test/test_findgendir.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/test/test_getactiveobj.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/test/test_ie.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/test/test_ienum.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/test/test_imfattributes.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/test/test_inout_args.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/test/test_jscript.js +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/test/test_midl_safearray_create.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/test/test_msscript.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/test/test_npsupport.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/test/test_outparam.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/test/test_propputref.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/test/test_pump_events.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/test/test_safearray.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/test/test_sapi.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/test/test_server.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/test/test_showevents.py +0 -0
- /comtypes-1.4.5/comtypes/test/test_istream.py → /comtypes-1.4.7/comtypes/test/test_stream.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/test/test_subinterface.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/test/test_typeinfo.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/test/test_urlhistory.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/test/test_variant.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/test/test_win32com_interop.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/test/test_wmi.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/test/test_word.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/test/urlhist.tlb +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/tools/__init__.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/tools/codegenerator/__init__.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/tools/codegenerator/helpers.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/tools/codegenerator/namespaces.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/tools/codegenerator/packing.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/tools/typedesc.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/util.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes/viewobject.py +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes.egg-info/dependency_links.txt +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes.egg-info/entry_points.txt +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/comtypes.egg-info/top_level.txt +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/pyproject.toml +0 -0
- {comtypes-1.4.5 → comtypes-1.4.7}/setup.py +0 -0
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
from _ctypes import COMError
|
|
2
|
+
from ctypes import byref, c_ubyte, POINTER
|
|
3
|
+
import contextlib
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
import unittest
|
|
6
|
+
|
|
7
|
+
import comtypes
|
|
8
|
+
import comtypes.client
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
with contextlib.redirect_stdout(None): # supress warnings
|
|
12
|
+
mod = comtypes.client.GetModule("msvidctl.dll")
|
|
13
|
+
|
|
14
|
+
from comtypes.gen.MSVidCtlLib import IStorage
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
STATFLAG_DEFAULT = 0
|
|
18
|
+
STGC_DEFAULT = 0
|
|
19
|
+
STGM_CREATE = 0x00001000
|
|
20
|
+
STGM_DIRECT = 0x00000000
|
|
21
|
+
STGM_DELETEONRELEASE = 0x04000000
|
|
22
|
+
STGM_READ = 0x00000000
|
|
23
|
+
STGM_READWRITE = 0x00000002
|
|
24
|
+
STGM_SHARE_EXCLUSIVE = 0x00000010
|
|
25
|
+
STGM_TRANSACTED = 0x00010000
|
|
26
|
+
STGMOVE_MOVE = 0
|
|
27
|
+
STREAM_SEEK_SET = 0
|
|
28
|
+
|
|
29
|
+
STG_E_PATHNOTFOUND = -2147287038
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class Test_IStorage(unittest.TestCase):
|
|
33
|
+
CREATE_DOC_FLAG = (
|
|
34
|
+
STGM_DIRECT
|
|
35
|
+
| STGM_READWRITE
|
|
36
|
+
| STGM_CREATE
|
|
37
|
+
| STGM_SHARE_EXCLUSIVE
|
|
38
|
+
| STGM_DELETEONRELEASE
|
|
39
|
+
)
|
|
40
|
+
CREATE_STM_FLAG = STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE
|
|
41
|
+
OPEN_STM_FLAG = STGM_READ | STGM_SHARE_EXCLUSIVE
|
|
42
|
+
CREATE_STG_FLAG = STGM_TRANSACTED | STGM_READWRITE | STGM_SHARE_EXCLUSIVE
|
|
43
|
+
OPEN_STG_FLAG = STGM_TRANSACTED | STGM_READWRITE | STGM_SHARE_EXCLUSIVE
|
|
44
|
+
|
|
45
|
+
def _create_docfile(self) -> IStorage:
|
|
46
|
+
stg = POINTER(IStorage)()
|
|
47
|
+
comtypes._ole32.StgCreateDocfile(None, self.CREATE_DOC_FLAG, 0, byref(stg))
|
|
48
|
+
return stg # type: ignore
|
|
49
|
+
|
|
50
|
+
def test_CreateStream(self):
|
|
51
|
+
storage = self._create_docfile()
|
|
52
|
+
filepath = Path(storage.Stat(STATFLAG_DEFAULT).pwcsName)
|
|
53
|
+
self.assertTrue(filepath.exists())
|
|
54
|
+
stream = storage.CreateStream("example", self.CREATE_STM_FLAG, 0, 0)
|
|
55
|
+
test_data = "Some data".encode("utf-8")
|
|
56
|
+
pv = (c_ubyte * len(test_data)).from_buffer(bytearray(test_data))
|
|
57
|
+
stream.RemoteWrite(pv, len(test_data))
|
|
58
|
+
stream.Commit(STGC_DEFAULT)
|
|
59
|
+
stream.RemoteSeek(0, STREAM_SEEK_SET)
|
|
60
|
+
read_buffer, data_read = stream.RemoteRead(1024)
|
|
61
|
+
self.assertEqual(bytearray(read_buffer)[0:data_read], test_data)
|
|
62
|
+
storage.Commit(STGC_DEFAULT)
|
|
63
|
+
self.assertTrue(filepath.exists())
|
|
64
|
+
del storage
|
|
65
|
+
self.assertFalse(filepath.exists())
|
|
66
|
+
|
|
67
|
+
def test_CreateStorage(self):
|
|
68
|
+
parent = self._create_docfile()
|
|
69
|
+
child = parent.CreateStorage("child", self.CREATE_STG_FLAG, 0, 0)
|
|
70
|
+
self.assertEqual("child", child.Stat(STATFLAG_DEFAULT).pwcsName)
|
|
71
|
+
|
|
72
|
+
def test_OpenStorage(self):
|
|
73
|
+
parent = self._create_docfile()
|
|
74
|
+
created_child = parent.CreateStorage("child", self.CREATE_STG_FLAG, 0, 0)
|
|
75
|
+
del created_child
|
|
76
|
+
opened_child = parent.OpenStorage("child", None, self.OPEN_STG_FLAG, None, 0)
|
|
77
|
+
self.assertEqual("child", opened_child.Stat(STATFLAG_DEFAULT).pwcsName)
|
|
78
|
+
|
|
79
|
+
def test_RemoteCopyTo(self):
|
|
80
|
+
src_stg = self._create_docfile()
|
|
81
|
+
src_stg.CreateStorage("child", self.CREATE_STG_FLAG, 0, 0)
|
|
82
|
+
dst_stg = self._create_docfile()
|
|
83
|
+
src_stg.RemoteCopyTo(0, None, None, dst_stg)
|
|
84
|
+
src_stg.Commit(STGC_DEFAULT)
|
|
85
|
+
del src_stg
|
|
86
|
+
opened_stg = dst_stg.OpenStorage("child", None, self.OPEN_STG_FLAG, None, 0)
|
|
87
|
+
self.assertEqual("child", opened_stg.Stat(STATFLAG_DEFAULT).pwcsName)
|
|
88
|
+
|
|
89
|
+
def test_MoveElementTo(self):
|
|
90
|
+
src_stg = self._create_docfile()
|
|
91
|
+
src_stg.CreateStorage("foo", self.CREATE_STG_FLAG, 0, 0)
|
|
92
|
+
dst_stg = self._create_docfile()
|
|
93
|
+
src_stg.MoveElementTo("foo", dst_stg, "bar", STGMOVE_MOVE)
|
|
94
|
+
opened_stg = dst_stg.OpenStorage("bar", None, self.OPEN_STG_FLAG, None, 0)
|
|
95
|
+
self.assertEqual("bar", opened_stg.Stat(STATFLAG_DEFAULT).pwcsName)
|
|
96
|
+
with self.assertRaises(COMError) as ctx:
|
|
97
|
+
src_stg.OpenStorage("foo", None, self.OPEN_STG_FLAG, None, 0)
|
|
98
|
+
self.assertEqual(ctx.exception.hresult, STG_E_PATHNOTFOUND)
|
|
99
|
+
|
|
100
|
+
def test_Revert(self):
|
|
101
|
+
storage = self._create_docfile()
|
|
102
|
+
foo = storage.CreateStorage("foo", self.CREATE_STG_FLAG, 0, 0)
|
|
103
|
+
foo.CreateStorage("bar", self.CREATE_STG_FLAG, 0, 0)
|
|
104
|
+
bar = foo.OpenStorage("bar", None, self.OPEN_STG_FLAG, None, 0)
|
|
105
|
+
self.assertEqual("bar", bar.Stat(STATFLAG_DEFAULT).pwcsName)
|
|
106
|
+
foo.Revert()
|
|
107
|
+
with self.assertRaises(COMError) as ctx:
|
|
108
|
+
foo.OpenStorage("bar", None, self.OPEN_STG_FLAG, None, 0)
|
|
109
|
+
self.assertEqual(ctx.exception.hresult, STG_E_PATHNOTFOUND)
|
|
110
|
+
|
|
111
|
+
def test_DestroyElement(self):
|
|
112
|
+
storage = self._create_docfile()
|
|
113
|
+
storage.CreateStorage("example", self.CREATE_STG_FLAG, 0, 0)
|
|
114
|
+
storage.DestroyElement("example")
|
|
115
|
+
with self.assertRaises(COMError) as ctx:
|
|
116
|
+
storage.OpenStorage("example", None, self.OPEN_STG_FLAG, None, 0)
|
|
117
|
+
self.assertEqual(ctx.exception.hresult, STG_E_PATHNOTFOUND)
|
|
118
|
+
|
|
119
|
+
def test_RenameElement(self):
|
|
120
|
+
storage = self._create_docfile()
|
|
121
|
+
storage.CreateStorage("example", self.CREATE_STG_FLAG, 0, 0)
|
|
122
|
+
storage.RenameElement("example", "sample")
|
|
123
|
+
sample = storage.OpenStorage("sample", None, self.OPEN_STG_FLAG, None, 0)
|
|
124
|
+
self.assertEqual("sample", sample.Stat(STATFLAG_DEFAULT).pwcsName)
|
|
125
|
+
with self.assertRaises(COMError) as ctx:
|
|
126
|
+
storage.OpenStorage("example", None, self.OPEN_STG_FLAG, None, 0)
|
|
127
|
+
self.assertEqual(ctx.exception.hresult, STG_E_PATHNOTFOUND)
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import unittest
|
|
2
|
+
|
|
3
|
+
from comtypes.tools import typedesc
|
|
4
|
+
from comtypes.tools.codegenerator import typeannotator
|
|
5
|
+
from comtypes.tools.tlbparser import (
|
|
6
|
+
BSTR_type,
|
|
7
|
+
HRESULT_type,
|
|
8
|
+
VARIANT_type,
|
|
9
|
+
VARIANT_BOOL_type,
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
iunknown_type = typedesc.ComInterface(
|
|
14
|
+
"IUnknown", None, "{00000000-0000-0000-C000-000000000046}", ["hidden"], None
|
|
15
|
+
)
|
|
16
|
+
idispatch_type = typedesc.ComInterface(
|
|
17
|
+
"IDispatch",
|
|
18
|
+
iunknown_type,
|
|
19
|
+
"{00020400-0000-0000-C000-000000000046}",
|
|
20
|
+
["restricted"],
|
|
21
|
+
None,
|
|
22
|
+
)
|
|
23
|
+
void_type = typedesc.FundamentalType("void", 0, 0)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class Test_AvoidUsingKeywords(unittest.TestCase):
|
|
27
|
+
def _create_typedesc_disp_interface(self) -> typedesc.DispInterface:
|
|
28
|
+
guid = "{00000000-0000-0000-0000-000000000000}"
|
|
29
|
+
itf = typedesc.DispInterface("IDispDerived", idispatch_type, guid, [], None)
|
|
30
|
+
ham = typedesc.DispProperty(0, "ham", BSTR_type, ["readonly"], None)
|
|
31
|
+
bacon = typedesc.DispMethod(
|
|
32
|
+
472, 1, "bacon", VARIANT_BOOL_type, ["hidden"], None
|
|
33
|
+
)
|
|
34
|
+
bacon.add_argument(VARIANT_type, "and", ["in"], None)
|
|
35
|
+
bacon.add_argument(VARIANT_type, "foo", ["in"], None)
|
|
36
|
+
get_spam = typedesc.DispMethod(6, 2, "spam", VARIANT_type, ["propget"], None)
|
|
37
|
+
get_spam.add_argument(VARIANT_type, "arg1", ["in", "optional"], None)
|
|
38
|
+
put_spam = typedesc.DispMethod(6, 4, "spam", void_type, ["propput"], None)
|
|
39
|
+
put_spam.add_argument(VARIANT_type, "arg1", ["in", "optional"], None)
|
|
40
|
+
put_spam.add_argument(VARIANT_type, "arg2", ["in"], None)
|
|
41
|
+
except_ = typedesc.DispProperty(1, "except", BSTR_type, ["readonly"], None)
|
|
42
|
+
raise_ = typedesc.DispMethod(
|
|
43
|
+
474, 1, "raise", VARIANT_BOOL_type, ["hidden"], None
|
|
44
|
+
)
|
|
45
|
+
raise_.add_argument(VARIANT_type, "foo", ["in"], None)
|
|
46
|
+
raise_.add_argument(VARIANT_type, "bar", ["in", "optional"], None)
|
|
47
|
+
get_def = typedesc.DispMethod(8, 2, "def", VARIANT_type, ["propget"], None)
|
|
48
|
+
get_def.add_argument(VARIANT_type, "arg1", ["in", "optional"], None)
|
|
49
|
+
put_def = typedesc.DispMethod(8, 4, "def", void_type, ["propput"], None)
|
|
50
|
+
put_def.add_argument(VARIANT_type, "arg1", ["in", "optional"], None)
|
|
51
|
+
put_def.add_argument(VARIANT_type, "arg2", ["in"], None)
|
|
52
|
+
for m in [ham, bacon, get_spam, put_spam, except_, raise_, get_def, put_def]:
|
|
53
|
+
itf.add_member(m)
|
|
54
|
+
return itf
|
|
55
|
+
|
|
56
|
+
def test_disp_interface(self):
|
|
57
|
+
itf = self._create_typedesc_disp_interface()
|
|
58
|
+
expected = (
|
|
59
|
+
" @property # dispprop\n"
|
|
60
|
+
" def ham(self) -> hints.Incomplete: ...\n"
|
|
61
|
+
" pass # @property # dispprop\n"
|
|
62
|
+
" pass # avoid using a keyword for def except(self) -> hints.Incomplete: ...\n" # noqa
|
|
63
|
+
" def bacon(self, *args: hints.Any, **kwargs: hints.Any) -> hints.Incomplete: ...\n" # noqa
|
|
64
|
+
" def _get_spam(self, arg1: hints.Incomplete = ...) -> hints.Incomplete: ...\n" # noqa
|
|
65
|
+
" def _set_spam(self, arg1: hints.Incomplete = ..., **kwargs: hints.Any) -> hints.Incomplete: ...\n" # noqa
|
|
66
|
+
" spam = hints.named_property('spam', _get_spam, _set_spam)\n"
|
|
67
|
+
" pass # avoid using a keyword for def raise(self, foo: hints.Incomplete, bar: hints.Incomplete = ...) -> hints.Incomplete: ...\n" # noqa
|
|
68
|
+
" def _get_def(self, arg1: hints.Incomplete = ...) -> hints.Incomplete: ...\n" # noqa
|
|
69
|
+
" def _set_def(self, arg1: hints.Incomplete = ..., **kwargs: hints.Any) -> hints.Incomplete: ...\n" # noqa
|
|
70
|
+
" pass # avoid using a keyword for def = hints.named_property('def', _get_def, _set_def)" # noqa
|
|
71
|
+
)
|
|
72
|
+
self.assertEqual(
|
|
73
|
+
expected, typeannotator.DispInterfaceMembersAnnotator(itf).generate()
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
def _create_typedesc_com_interface(self) -> typedesc.ComInterface:
|
|
77
|
+
guid = "{00000000-0000-0000-0000-000000000000}"
|
|
78
|
+
itf = typedesc.ComInterface(
|
|
79
|
+
"IUnkDerived", iunknown_type, guid, ["hidden"], None
|
|
80
|
+
)
|
|
81
|
+
spam = typedesc.ComMethod(
|
|
82
|
+
2, 1610678269, "spam", HRESULT_type, ["propget"], None
|
|
83
|
+
)
|
|
84
|
+
get_ham = typedesc.ComMethod(
|
|
85
|
+
2, 1610678270, "ham", HRESULT_type, ["propget"], None
|
|
86
|
+
)
|
|
87
|
+
put_ham = typedesc.ComMethod(
|
|
88
|
+
4, 1610678270, "ham", HRESULT_type, ["propput"], None
|
|
89
|
+
)
|
|
90
|
+
bacon = typedesc.ComMethod(1, 1610678271, "bacon", HRESULT_type, [], None)
|
|
91
|
+
bacon.add_argument(VARIANT_type, "foo", ["in"], None)
|
|
92
|
+
bacon.add_argument(VARIANT_type, "or", ["in"], None)
|
|
93
|
+
global_ = typedesc.ComMethod(
|
|
94
|
+
2, 1610678272, "global", HRESULT_type, ["propget"], None
|
|
95
|
+
)
|
|
96
|
+
get_class = typedesc.ComMethod(
|
|
97
|
+
2, 1610678273, "class", HRESULT_type, ["propget"], None
|
|
98
|
+
)
|
|
99
|
+
put_class = typedesc.ComMethod(
|
|
100
|
+
4, 1610678273, "class", HRESULT_type, ["propput"], None
|
|
101
|
+
)
|
|
102
|
+
pass_ = typedesc.ComMethod(1, 1610678274, "pass", HRESULT_type, [], None)
|
|
103
|
+
pass_.add_argument(VARIANT_type, "foo", ["in"], None)
|
|
104
|
+
pass_.add_argument(VARIANT_type, "bar", ["in", "optional"], None)
|
|
105
|
+
members = [spam, get_ham, put_ham, bacon, global_, get_class, put_class, pass_]
|
|
106
|
+
itf.extend_members(members)
|
|
107
|
+
return itf
|
|
108
|
+
|
|
109
|
+
def test_com_interface(self):
|
|
110
|
+
itf = self._create_typedesc_com_interface()
|
|
111
|
+
expected = (
|
|
112
|
+
" def _get_spam(self) -> hints.Hresult: ...\n"
|
|
113
|
+
" spam = hints.normal_property(_get_spam)\n"
|
|
114
|
+
" def _get_ham(self) -> hints.Hresult: ...\n"
|
|
115
|
+
" def _set_ham(self) -> hints.Hresult: ...\n"
|
|
116
|
+
" ham = hints.normal_property(_get_ham, _set_ham)\n"
|
|
117
|
+
" def bacon(self, *args: hints.Any, **kwargs: hints.Any) -> hints.Hresult: ...\n" # noqa
|
|
118
|
+
" def _get_global(self) -> hints.Hresult: ...\n"
|
|
119
|
+
" pass # avoid using a keyword for global = hints.normal_property(_get_global)\n" # noqa
|
|
120
|
+
" def _get_class(self) -> hints.Hresult: ...\n"
|
|
121
|
+
" def _set_class(self) -> hints.Hresult: ...\n"
|
|
122
|
+
" pass # avoid using a keyword for class = hints.normal_property(_get_class, _set_class)\n" # noqa
|
|
123
|
+
" pass # avoid using a keyword for def pass(self, foo: hints.Incomplete, bar: hints.Incomplete = ...) -> hints.Hresult: ..." # noqa
|
|
124
|
+
)
|
|
125
|
+
self.assertEqual(
|
|
126
|
+
expected, typeannotator.ComInterfaceMembersAnnotator(itf).generate()
|
|
127
|
+
)
|
|
@@ -196,7 +196,6 @@ class CodeGenerator(object):
|
|
|
196
196
|
print("from typing import TYPE_CHECKING", file=output)
|
|
197
197
|
print(file=output)
|
|
198
198
|
print("if TYPE_CHECKING:", file=output)
|
|
199
|
-
print(" from typing import Any, Tuple", file=output)
|
|
200
199
|
print(" from comtypes import hints", file=output)
|
|
201
200
|
print(file=output)
|
|
202
201
|
print(file=output)
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
from typing import Optional
|
|
2
|
+
|
|
3
|
+
import comtypes
|
|
4
|
+
from comtypes import typeinfo
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def name_wrapper_module(tlib: typeinfo.ITypeLib) -> str:
|
|
8
|
+
"""Determine the name of a typelib wrapper module"""
|
|
9
|
+
libattr = tlib.GetLibAttr()
|
|
10
|
+
guid = str(libattr.guid)[1:-1].replace("-", "_")
|
|
11
|
+
modname = f"_{guid}_{libattr.lcid}_{libattr.wMajorVerNum}_{libattr.wMinorVerNum}"
|
|
12
|
+
return f"comtypes.gen.{modname}"
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def name_friendly_module(tlib: typeinfo.ITypeLib) -> Optional[str]:
|
|
16
|
+
"""Determine the friendly-name of a typelib module.
|
|
17
|
+
If cannot get friendly-name from typelib, returns `None`.
|
|
18
|
+
"""
|
|
19
|
+
try:
|
|
20
|
+
modulename = tlib.GetDocumentation(-1)[0]
|
|
21
|
+
except comtypes.COMError:
|
|
22
|
+
return
|
|
23
|
+
return f"comtypes.gen.{modulename}"
|
|
@@ -1,18 +1,8 @@
|
|
|
1
1
|
import abc
|
|
2
2
|
import keyword
|
|
3
|
-
from typing import
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
Generic,
|
|
7
|
-
Iterable,
|
|
8
|
-
Iterator,
|
|
9
|
-
List,
|
|
10
|
-
Optional,
|
|
11
|
-
Sequence,
|
|
12
|
-
Tuple,
|
|
13
|
-
TYPE_CHECKING,
|
|
14
|
-
TypeVar,
|
|
15
|
-
)
|
|
3
|
+
from typing import Any, Generic, TypeVar, TYPE_CHECKING
|
|
4
|
+
from typing import Dict, List, Optional, Sequence, Tuple
|
|
5
|
+
from typing import Iterable, Iterator
|
|
16
6
|
|
|
17
7
|
from comtypes.tools import typedesc
|
|
18
8
|
|
|
@@ -124,6 +114,8 @@ class _MethodsAnnotator(abc.ABC, Generic[_T_MTD]):
|
|
|
124
114
|
content = f"{mem_name} = hints.named_property('{mem_name}', fset={setter})"
|
|
125
115
|
else:
|
|
126
116
|
return
|
|
117
|
+
if keyword.iskeyword(mem_name):
|
|
118
|
+
content = f"pass # avoid using a keyword for {content}"
|
|
127
119
|
self._define_member(content)
|
|
128
120
|
|
|
129
121
|
def _define_normal_prop(
|
|
@@ -137,6 +129,8 @@ class _MethodsAnnotator(abc.ABC, Generic[_T_MTD]):
|
|
|
137
129
|
content = f"{mem_name} = hints.normal_property(fset={setter})"
|
|
138
130
|
else:
|
|
139
131
|
return
|
|
132
|
+
if keyword.iskeyword(mem_name):
|
|
133
|
+
content = f"pass # avoid using a keyword for {content}"
|
|
140
134
|
self._define_member(content)
|
|
141
135
|
|
|
142
136
|
def _define_member(self, content: str) -> None:
|
|
@@ -242,14 +236,14 @@ class ComMethodAnnotator(_MethodAnnotator[typedesc.ComMethod]):
|
|
|
242
236
|
has_optional = False
|
|
243
237
|
for _, argname, default in self.inarg_specs:
|
|
244
238
|
if keyword.iskeyword(argname):
|
|
245
|
-
inargs = ["*args: Any", "**kwargs: Any"]
|
|
239
|
+
inargs = ["*args: hints.Any", "**kwargs: hints.Any"]
|
|
246
240
|
break
|
|
247
241
|
if default is None:
|
|
248
242
|
if has_optional:
|
|
249
243
|
# probably propput or propputref
|
|
250
244
|
# HACK: Something that goes into this conditional branch
|
|
251
245
|
# should be a special callback.
|
|
252
|
-
inargs.append("**kwargs: Any")
|
|
246
|
+
inargs.append("**kwargs: hints.Any")
|
|
253
247
|
break
|
|
254
248
|
inargs.append(f"{argname}: hints.Incomplete")
|
|
255
249
|
else:
|
|
@@ -261,9 +255,12 @@ class ComMethodAnnotator(_MethodAnnotator[typedesc.ComMethod]):
|
|
|
261
255
|
elif len(outargs) == 1:
|
|
262
256
|
out = outargs[0]
|
|
263
257
|
else:
|
|
264
|
-
out = "Tuple[" + ", ".join(outargs) + "]"
|
|
258
|
+
out = "hints.Tuple[" + ", ".join(outargs) + "]"
|
|
265
259
|
in_ = ("self, " + ", ".join(inargs)) if inargs else "self"
|
|
266
|
-
|
|
260
|
+
content = f"def {name}({in_}) -> {out}: ..."
|
|
261
|
+
if keyword.iskeyword(name):
|
|
262
|
+
content = f"pass # avoid using a keyword for {content}"
|
|
263
|
+
return content
|
|
267
264
|
|
|
268
265
|
|
|
269
266
|
class ComMethodsAnnotator(_MethodsAnnotator[typedesc.ComMethod]):
|
|
@@ -285,14 +282,14 @@ class DispMethodAnnotator(_MethodAnnotator[typedesc.DispMethod]):
|
|
|
285
282
|
has_optional = False
|
|
286
283
|
for _, argname, default in self.inarg_specs:
|
|
287
284
|
if keyword.iskeyword(argname):
|
|
288
|
-
inargs = ["*args: Any", "**kwargs: Any"]
|
|
285
|
+
inargs = ["*args: hints.Any", "**kwargs: hints.Any"]
|
|
289
286
|
break
|
|
290
287
|
if default is None:
|
|
291
288
|
if has_optional:
|
|
292
289
|
# probably propput or propputref
|
|
293
290
|
# HACK: Something that goes into this conditional branch
|
|
294
291
|
# should be a special callback.
|
|
295
|
-
inargs.append("**kwargs: Any")
|
|
292
|
+
inargs.append("**kwargs: hints.Any")
|
|
296
293
|
break
|
|
297
294
|
inargs.append(f"{argname}: hints.Incomplete")
|
|
298
295
|
else:
|
|
@@ -300,7 +297,10 @@ class DispMethodAnnotator(_MethodAnnotator[typedesc.DispMethod]):
|
|
|
300
297
|
has_optional = True
|
|
301
298
|
out = _to_outtype(self.method.returns)
|
|
302
299
|
in_ = ("self, " + ", ".join(inargs)) if inargs else "self"
|
|
303
|
-
|
|
300
|
+
content = f"def {name}({in_}) -> {out}: ..."
|
|
301
|
+
if keyword.iskeyword(name):
|
|
302
|
+
content = f"pass # avoid using a keyword for {content}"
|
|
303
|
+
return content
|
|
304
304
|
|
|
305
305
|
|
|
306
306
|
class DispMethodsAnnotator(_MethodsAnnotator[typedesc.DispMethod]):
|
|
@@ -328,9 +328,14 @@ class DispInterfaceMembersAnnotator(object):
|
|
|
328
328
|
props, methods = self._categorize_members()
|
|
329
329
|
property_lines: List[str] = []
|
|
330
330
|
for mem in props:
|
|
331
|
-
property_lines.append("@property # dispprop")
|
|
332
331
|
out = _to_outtype(mem.typ)
|
|
333
|
-
|
|
332
|
+
decorator = "@property # dispprop"
|
|
333
|
+
content = f"def {mem.name}(self) -> {out}: ..."
|
|
334
|
+
if keyword.iskeyword(mem.name):
|
|
335
|
+
decorator = f"pass # {decorator}"
|
|
336
|
+
content = f"pass # avoid using a keyword for {content}"
|
|
337
|
+
property_lines.append(decorator)
|
|
338
|
+
property_lines.append(content)
|
|
334
339
|
dispprops = "\n".join(f" {p}" for p in property_lines)
|
|
335
340
|
dispmethods = DispMethodsAnnotator().generate(methods)
|
|
336
341
|
return "\n".join(d for d in (dispprops, dispmethods) if d)
|
|
@@ -298,27 +298,25 @@ class Parser(object):
|
|
|
298
298
|
names = tinfo.GetNames(fd.memid, fd.cParams + 1)
|
|
299
299
|
names.append("rhs")
|
|
300
300
|
names = names[: fd.cParams + 1]
|
|
301
|
+
# function name first, then parameter names
|
|
301
302
|
assert len(names) == fd.cParams + 1
|
|
302
303
|
flags = self.func_flags(fd.wFuncFlags)
|
|
303
304
|
flags += self.inv_kind(fd.invkind)
|
|
304
305
|
mth = typedesc.ComMethod(
|
|
305
306
|
fd.invkind, fd.memid, func_name, returns, flags, func_doc
|
|
306
307
|
)
|
|
307
|
-
for
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
308
|
+
for j in range(fd.cParams):
|
|
309
|
+
elemdesc = fd.lprgelemdescParam[j]
|
|
310
|
+
typ = self.make_type(elemdesc.tdesc, tinfo)
|
|
311
|
+
name = names[j + 1]
|
|
312
|
+
paramdesc = elemdesc._.paramdesc
|
|
313
|
+
if paramdesc.wParamFlags & typeinfo.PARAMFLAG_FHASDEFAULT:
|
|
312
314
|
# XXX should be handled by VARIANT itself
|
|
313
|
-
|
|
314
|
-
fd.lprgelemdescParam[p]
|
|
315
|
-
._.paramdesc.pparamdescex[0]
|
|
316
|
-
.varDefaultValue
|
|
317
|
-
)
|
|
318
|
-
default: Any = var.value
|
|
315
|
+
default: Any = paramdesc.pparamdescex[0].varDefaultValue.value
|
|
319
316
|
else:
|
|
320
317
|
default = None
|
|
321
|
-
|
|
318
|
+
param_flags = self.param_flags(paramdesc.wParamFlags)
|
|
319
|
+
mth.add_argument(typ, name, param_flags, default)
|
|
322
320
|
members.append((fd.oVft, mth))
|
|
323
321
|
# Sort the methods by oVft (VTable offset): Some typeinfo
|
|
324
322
|
# don't list methods in VTable order.
|
|
@@ -386,25 +384,25 @@ class Parser(object):
|
|
|
386
384
|
names = tinfo.GetNames(fd.memid, fd.cParams + 1)
|
|
387
385
|
names.append("rhs")
|
|
388
386
|
names = names[: fd.cParams + 1]
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
) # function name first, then parameter names
|
|
387
|
+
# function name first, then parameter names
|
|
388
|
+
assert len(names) == fd.cParams + 1
|
|
392
389
|
flags = self.func_flags(fd.wFuncFlags)
|
|
393
390
|
flags += self.inv_kind(fd.invkind)
|
|
394
391
|
mth = typedesc.DispMethod(
|
|
395
392
|
fd.memid, fd.invkind, func_name, returns, flags, func_doc
|
|
396
393
|
)
|
|
397
|
-
for
|
|
398
|
-
|
|
399
|
-
typ = self.make_type(
|
|
400
|
-
name = names[
|
|
401
|
-
|
|
402
|
-
if
|
|
403
|
-
|
|
404
|
-
default: Any =
|
|
394
|
+
for j in range(fd.cParams):
|
|
395
|
+
elemdesc = fd.lprgelemdescParam[j]
|
|
396
|
+
typ = self.make_type(elemdesc.tdesc, tinfo)
|
|
397
|
+
name = names[j + 1]
|
|
398
|
+
paramdesc = elemdesc._.paramdesc
|
|
399
|
+
if paramdesc.wParamFlags & typeinfo.PARAMFLAG_FHASDEFAULT:
|
|
400
|
+
# XXX should be handled by VARIANT itself
|
|
401
|
+
default: Any = paramdesc.pparamdescex[0].varDefaultValue.value
|
|
405
402
|
else:
|
|
406
403
|
default = None
|
|
407
|
-
|
|
404
|
+
param_flags = self.param_flags(paramdesc.wParamFlags)
|
|
405
|
+
mth.add_argument(typ, name, param_flags, default)
|
|
408
406
|
itf.add_member(mth)
|
|
409
407
|
return itf
|
|
410
408
|
|
|
@@ -1,12 +1,6 @@
|
|
|
1
1
|
# typedesc.py - classes representing C type descriptions
|
|
2
|
-
from typing import
|
|
3
|
-
|
|
4
|
-
List,
|
|
5
|
-
Optional,
|
|
6
|
-
Tuple,
|
|
7
|
-
Union as _UnionT,
|
|
8
|
-
SupportsInt,
|
|
9
|
-
)
|
|
2
|
+
from typing import Any, SupportsInt
|
|
3
|
+
from typing import List, Optional, Tuple, Union as _UnionT
|
|
10
4
|
|
|
11
5
|
import comtypes
|
|
12
6
|
|