comtypes 1.4.6__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.6 → comtypes-1.4.7}/CHANGES.txt +18 -0
- {comtypes-1.4.6/comtypes.egg-info → comtypes-1.4.7}/PKG-INFO +28 -36
- {comtypes-1.4.6 → comtypes-1.4.7}/README.md +26 -34
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/__init__.py +1 -1
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/_post_coinit/bstr.py +13 -6
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/automation.py +9 -15
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/hints.pyi +2 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/persist.py +19 -3
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/shelllink.py +72 -21
- {comtypes-1.4.6 → 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_shelllink.py +133 -0
- comtypes-1.4.7/comtypes/test/test_storage.py +127 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/typeinfo.py +25 -22
- {comtypes-1.4.6 → comtypes-1.4.7/comtypes.egg-info}/PKG-INFO +28 -36
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes.egg-info/SOURCES.txt +5 -1
- {comtypes-1.4.6 → comtypes-1.4.7}/setup.cfg +1 -1
- {comtypes-1.4.6 → comtypes-1.4.7}/LICENSE.txt +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/MANIFEST.in +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/GUID.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/_comobject.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/_idl_stuff.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/_memberspec.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/_meta.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/_npsupport.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/_post_coinit/__init__.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/_post_coinit/misc.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/_post_coinit/unknwn.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/_py_instance_method.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/_safearray.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/_tlib_version_checker.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/clear_cache.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/client/__init__.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/client/_code_cache.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/client/_constants.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/client/_events.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/client/_generate.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/client/dynamic.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/client/lazybind.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/connectionpoints.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/errorinfo.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/git.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/hresult.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/logutil.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/messageloop.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/patcher.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/safearray.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/server/__init__.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/server/automation.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/server/connectionpoints.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/server/inprocserver.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/server/localserver.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/server/register.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/server/w_getopt.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/stream.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/test/TestComServer.idl +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/test/TestComServer.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/test/TestComServer.tlb +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/test/TestDispServer.idl +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/test/TestDispServer.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/test/TestDispServer.tlb +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/test/__init__.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/test/find_memleak.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/test/mylib.idl +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/test/mylib.tlb +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/test/mytypelib.idl +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/test/runtests.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/test/setup.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/test/test_BSTR.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/test/test_DISPPARAMS.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/test/test_GUID.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/test/test_QueryService.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/test/test_agilent.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/test/test_avmc.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/test/test_basic.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/test/test_casesensitivity.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/test/test_clear_cache.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/test/test_client_dynamic.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/test/test_client_regenerate_modules.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/test/test_collections.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/test/test_comserver.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/test/test_createwrappers.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/test/test_dict.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/test/test_dispifc_records.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/test/test_dispifc_safearrays.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/test/test_dispinterface.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/test/test_dyndispatch.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/test/test_excel.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/test/test_findgendir.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/test/test_getactiveobj.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/test/test_ie.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/test/test_ienum.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/test/test_imfattributes.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/test/test_inout_args.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/test/test_jscript.js +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/test/test_midl_safearray_create.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/test/test_msscript.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/test/test_npsupport.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/test/test_outparam.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/test/test_propputref.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/test/test_pump_events.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/test/test_recordinfo.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/test/test_safearray.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/test/test_sapi.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/test/test_server.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/test/test_showevents.py +0 -0
- /comtypes-1.4.6/comtypes/test/test_istream.py → /comtypes-1.4.7/comtypes/test/test_stream.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/test/test_subinterface.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/test/test_typeannotator.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/test/test_typeinfo.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/test/test_urlhistory.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/test/test_variant.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/test/test_win32com_interop.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/test/test_wmi.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/test/test_word.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/test/urlhist.tlb +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/tools/__init__.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/tools/codegenerator/__init__.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/tools/codegenerator/codegenerator.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/tools/codegenerator/helpers.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/tools/codegenerator/modulenamer.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/tools/codegenerator/namespaces.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/tools/codegenerator/packing.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/tools/codegenerator/typeannotator.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/tools/tlbparser.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/tools/typedesc.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/tools/typedesc_base.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/util.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes/viewobject.py +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes.egg-info/dependency_links.txt +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes.egg-info/entry_points.txt +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/comtypes.egg-info/top_level.txt +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/pyproject.toml +0 -0
- {comtypes-1.4.6 → comtypes-1.4.7}/setup.py +0 -0
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
from _ctypes import COMError
|
|
2
|
+
from ctypes import byref, POINTER
|
|
3
|
+
import contextlib
|
|
4
|
+
import unittest
|
|
5
|
+
|
|
6
|
+
import comtypes
|
|
7
|
+
from comtypes.client import GetModule, CreateObject
|
|
8
|
+
from comtypes import hresult, GUID
|
|
9
|
+
|
|
10
|
+
with contextlib.redirect_stdout(None): # supress warnings
|
|
11
|
+
GetModule("msvidctl.dll")
|
|
12
|
+
from comtypes.gen import MSVidCtlLib as msvidctl
|
|
13
|
+
from comtypes.gen.MSVidCtlLib import IBindCtx, IMoniker, IRunningObjectTable
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
MKSYS_ITEMMONIKER = 4
|
|
17
|
+
ROTFLAGS_ALLOWANYCLIENT = 1
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def _create_item_moniker(delim: str, item: str) -> IMoniker:
|
|
21
|
+
mon = POINTER(IMoniker)()
|
|
22
|
+
comtypes._ole32.CreateItemMoniker(delim, item, byref(mon))
|
|
23
|
+
return mon # type: ignore
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def _create_bctx() -> IBindCtx:
|
|
27
|
+
bctx = POINTER(IBindCtx)()
|
|
28
|
+
# The first parameter is reserved and must be 0.
|
|
29
|
+
comtypes._ole32.CreateBindCtx(0, byref(bctx))
|
|
30
|
+
return bctx # type: ignore
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def _create_rot() -> IRunningObjectTable:
|
|
34
|
+
rot = POINTER(IRunningObjectTable)()
|
|
35
|
+
# The first parameter is reserved and must be 0.
|
|
36
|
+
comtypes._ole32.GetRunningObjectTable(0, byref(rot))
|
|
37
|
+
return rot # type: ignore
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class Test_IMoniker(unittest.TestCase):
|
|
41
|
+
def test_IsSystemMoniker(self):
|
|
42
|
+
item_id = str(GUID.create_new())
|
|
43
|
+
mon = _create_item_moniker("!", item_id)
|
|
44
|
+
self.assertEqual(mon.IsSystemMoniker(), MKSYS_ITEMMONIKER)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class Test_IBindCtx(unittest.TestCase):
|
|
48
|
+
def test_EnumObjectParam(self):
|
|
49
|
+
bctx = _create_bctx()
|
|
50
|
+
with self.assertRaises(COMError) as err_ctx:
|
|
51
|
+
# calling `EnumObjectParam` results in a return value of E_NOTIMPL.
|
|
52
|
+
# https://learn.microsoft.com/en-us/windows/win32/api/objidl/nf-objidl-ibindctx-enumobjectparam#notes-to-callers
|
|
53
|
+
bctx.EnumObjectParam()
|
|
54
|
+
self.assertEqual(err_ctx.exception.hresult, hresult.E_NOTIMPL)
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
class Test_IRunningObjectTable(unittest.TestCase):
|
|
58
|
+
def test_register_and_revoke_item_moniker(self):
|
|
59
|
+
vidctl = CreateObject(msvidctl.MSVidCtl, interface=msvidctl.IMSVidCtl)
|
|
60
|
+
item_id = str(GUID.create_new())
|
|
61
|
+
mon = _create_item_moniker("!", item_id)
|
|
62
|
+
rot = _create_rot()
|
|
63
|
+
bctx = _create_bctx()
|
|
64
|
+
self.assertEqual(mon.IsRunning(bctx, None, None), hresult.S_FALSE)
|
|
65
|
+
dw_reg = rot.Register(ROTFLAGS_ALLOWANYCLIENT, vidctl, mon)
|
|
66
|
+
self.assertEqual(mon.IsRunning(bctx, None, None), hresult.S_OK)
|
|
67
|
+
self.assertEqual(f"!{item_id}", mon.GetDisplayName(bctx, None))
|
|
68
|
+
self.assertEqual(rot.GetObject(mon).QueryInterface(msvidctl.IMSVidCtl), vidctl)
|
|
69
|
+
rot.Revoke(dw_reg)
|
|
70
|
+
self.assertEqual(mon.IsRunning(bctx, None, None), hresult.S_FALSE)
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
import tempfile
|
|
3
|
+
import unittest as ut
|
|
4
|
+
|
|
5
|
+
from comtypes import CoCreateInstance, GUID, IPersist
|
|
6
|
+
from comtypes import persist
|
|
7
|
+
|
|
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())
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
import tempfile
|
|
3
|
+
import unittest as ut
|
|
4
|
+
|
|
5
|
+
from comtypes import CoCreateInstance, GUID, shelllink
|
|
6
|
+
import comtypes.hresult
|
|
7
|
+
from comtypes.persist import IPersistFile
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
CLSID_ShellLink = GUID("{00021401-0000-0000-C000-000000000046}")
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class Test_IShellLinkA(ut.TestCase):
|
|
14
|
+
def setUp(self):
|
|
15
|
+
td = tempfile.TemporaryDirectory()
|
|
16
|
+
self.addCleanup(td.cleanup)
|
|
17
|
+
self.tmp_dir = Path(td.name)
|
|
18
|
+
self.src_file = (self.tmp_dir / "src.txt").resolve()
|
|
19
|
+
self.src_file.touch()
|
|
20
|
+
|
|
21
|
+
def _create_shortcut(self) -> shelllink.IShellLinkA:
|
|
22
|
+
return CoCreateInstance(CLSID_ShellLink, interface=shelllink.IShellLinkA)
|
|
23
|
+
|
|
24
|
+
def test_set_and_get_path(self):
|
|
25
|
+
shortcut = self._create_shortcut()
|
|
26
|
+
pf = shortcut.QueryInterface(IPersistFile)
|
|
27
|
+
self.assertEqual(pf.IsDirty(), comtypes.hresult.S_FALSE)
|
|
28
|
+
shortcut.SetPath(str(self.src_file).encode("utf-8"))
|
|
29
|
+
self.assertEqual(pf.IsDirty(), comtypes.hresult.S_OK)
|
|
30
|
+
self.assertEqual(
|
|
31
|
+
shortcut.GetPath(shelllink.SLGP_UNCPRIORITY),
|
|
32
|
+
str(self.src_file).encode("utf-8"),
|
|
33
|
+
)
|
|
34
|
+
lnk_file = (self.tmp_dir / "new.lnk").resolve()
|
|
35
|
+
self.assertFalse(lnk_file.exists())
|
|
36
|
+
pf.Save(str(lnk_file), True)
|
|
37
|
+
self.assertTrue(lnk_file.exists())
|
|
38
|
+
self.assertEqual(pf.GetCurFile(), str(lnk_file))
|
|
39
|
+
|
|
40
|
+
def test_set_and_get_working_directory(self):
|
|
41
|
+
shortcut = self._create_shortcut()
|
|
42
|
+
shortcut.SetWorkingDirectory(str(self.tmp_dir).encode("utf-8"))
|
|
43
|
+
self.assertEqual(
|
|
44
|
+
shortcut.GetWorkingDirectory(), str(self.tmp_dir).encode("utf-8")
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
def test_set_and_get_arguments(self):
|
|
48
|
+
shortcut = self._create_shortcut()
|
|
49
|
+
shortcut.SetArguments(b"-f")
|
|
50
|
+
self.assertEqual(shortcut.GetArguments(), b"-f")
|
|
51
|
+
|
|
52
|
+
def test_set_and_get_hotkey(self):
|
|
53
|
+
HOTKEYF_ALT = 0x04
|
|
54
|
+
HOTKEYF_CONTROL = 0x02
|
|
55
|
+
shortcut = self._create_shortcut()
|
|
56
|
+
shortcut.Hotkey = HOTKEYF_ALT | HOTKEYF_CONTROL
|
|
57
|
+
self.assertEqual(shortcut.Hotkey, HOTKEYF_ALT | HOTKEYF_CONTROL)
|
|
58
|
+
|
|
59
|
+
def test_set_and_get_showcmd(self):
|
|
60
|
+
SW_SHOWMAXIMIZED = 0x03
|
|
61
|
+
shortcut = self._create_shortcut()
|
|
62
|
+
shortcut.ShowCmd = SW_SHOWMAXIMIZED
|
|
63
|
+
self.assertEqual(shortcut.ShowCmd, SW_SHOWMAXIMIZED)
|
|
64
|
+
|
|
65
|
+
def test_set_and_get_icon_location(self):
|
|
66
|
+
shortcut = self._create_shortcut()
|
|
67
|
+
shortcut.SetIconLocation(str(self.src_file).encode("utf-8"), 1)
|
|
68
|
+
icon_path, index = shortcut.GetIconLocation()
|
|
69
|
+
self.assertEqual(icon_path, str(self.src_file).encode("utf-8"))
|
|
70
|
+
self.assertEqual(index, 1)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
class Test_IShellLinkW(ut.TestCase):
|
|
74
|
+
def setUp(self):
|
|
75
|
+
td = tempfile.TemporaryDirectory()
|
|
76
|
+
self.addCleanup(td.cleanup)
|
|
77
|
+
self.tmp_dir = Path(td.name)
|
|
78
|
+
self.src_file = (self.tmp_dir / "src.txt").resolve()
|
|
79
|
+
self.src_file.touch()
|
|
80
|
+
|
|
81
|
+
def _create_shortcut(self) -> shelllink.IShellLinkW:
|
|
82
|
+
return CoCreateInstance(CLSID_ShellLink, interface=shelllink.IShellLinkW)
|
|
83
|
+
|
|
84
|
+
def test_set_and_get_path(self):
|
|
85
|
+
shortcut = self._create_shortcut()
|
|
86
|
+
pf = shortcut.QueryInterface(IPersistFile)
|
|
87
|
+
self.assertEqual(pf.IsDirty(), comtypes.hresult.S_FALSE)
|
|
88
|
+
shortcut.SetPath(str(self.src_file))
|
|
89
|
+
self.assertEqual(pf.IsDirty(), comtypes.hresult.S_OK)
|
|
90
|
+
self.assertEqual(
|
|
91
|
+
shortcut.GetPath(shelllink.SLGP_UNCPRIORITY),
|
|
92
|
+
str(self.src_file),
|
|
93
|
+
)
|
|
94
|
+
lnk_file = (self.tmp_dir / "new.lnk").resolve()
|
|
95
|
+
self.assertFalse(lnk_file.exists())
|
|
96
|
+
pf.Save(str(lnk_file), True)
|
|
97
|
+
self.assertTrue(lnk_file.exists())
|
|
98
|
+
self.assertEqual(pf.GetCurFile(), str(lnk_file))
|
|
99
|
+
|
|
100
|
+
def test_set_and_get_description(self):
|
|
101
|
+
shortcut = self._create_shortcut()
|
|
102
|
+
shortcut.SetDescription("sample")
|
|
103
|
+
self.assertEqual(shortcut.GetDescription(), "sample")
|
|
104
|
+
|
|
105
|
+
def test_set_and_get_working_directory(self):
|
|
106
|
+
shortcut = self._create_shortcut()
|
|
107
|
+
shortcut.SetWorkingDirectory(str(self.tmp_dir))
|
|
108
|
+
self.assertEqual(shortcut.GetWorkingDirectory(), str(self.tmp_dir))
|
|
109
|
+
|
|
110
|
+
def test_set_and_get_arguments(self):
|
|
111
|
+
shortcut = self._create_shortcut()
|
|
112
|
+
shortcut.SetArguments("-f")
|
|
113
|
+
self.assertEqual(shortcut.GetArguments(), "-f")
|
|
114
|
+
|
|
115
|
+
def test_set_and_get_hotkey(self):
|
|
116
|
+
HOTKEYF_ALT = 0x04
|
|
117
|
+
HOTKEYF_CONTROL = 0x02
|
|
118
|
+
shortcut = self._create_shortcut()
|
|
119
|
+
shortcut.Hotkey = HOTKEYF_ALT | HOTKEYF_CONTROL
|
|
120
|
+
self.assertEqual(shortcut.Hotkey, HOTKEYF_ALT | HOTKEYF_CONTROL)
|
|
121
|
+
|
|
122
|
+
def test_set_and_get_showcmd(self):
|
|
123
|
+
SW_SHOWMAXIMIZED = 0x03
|
|
124
|
+
shortcut = self._create_shortcut()
|
|
125
|
+
shortcut.ShowCmd = SW_SHOWMAXIMIZED
|
|
126
|
+
self.assertEqual(shortcut.ShowCmd, SW_SHOWMAXIMIZED)
|
|
127
|
+
|
|
128
|
+
def test_set_and_get_icon_location(self):
|
|
129
|
+
shortcut = self._create_shortcut()
|
|
130
|
+
shortcut.SetIconLocation(str(self.src_file), 1)
|
|
131
|
+
icon_path, index = shortcut.GetIconLocation()
|
|
132
|
+
self.assertEqual(icon_path, str(self.src_file))
|
|
133
|
+
self.assertEqual(index, 1)
|
|
@@ -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)
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
# generated by 'xml2py'
|
|
4
4
|
# flags '..\tools\windows.xml -m comtypes -m comtypes.automation -w -r .*TypeLibEx -r .*TypeLib -o typeinfo.py'
|
|
5
5
|
# then hacked manually
|
|
6
|
-
import os
|
|
7
6
|
import sys
|
|
8
7
|
from typing import Any, overload, TypeVar, TYPE_CHECKING
|
|
9
8
|
from typing import List, Type, Tuple
|
|
@@ -14,7 +13,7 @@ import weakref
|
|
|
14
13
|
import ctypes
|
|
15
14
|
from ctypes import HRESULT, POINTER, _Pointer, byref, c_int, c_void_p, c_wchar_p
|
|
16
15
|
from ctypes.wintypes import DWORD, LONG, UINT, ULONG, WCHAR, WORD
|
|
17
|
-
from comtypes import BSTR, _CData, COMMETHOD,
|
|
16
|
+
from comtypes import BSTR, _CData, COMMETHOD, GUID, IID, IUnknown, STDMETHOD
|
|
18
17
|
from comtypes.automation import DISPID, LCID, SCODE
|
|
19
18
|
from comtypes.automation import DISPPARAMS, EXCEPINFO, VARIANT, VARIANTARG, VARTYPE
|
|
20
19
|
|
|
@@ -219,7 +218,9 @@ class ITypeLib(IUnknown):
|
|
|
219
218
|
"""Return an ITypeComp pointer."""
|
|
220
219
|
...
|
|
221
220
|
|
|
222
|
-
def GetDocumentation(
|
|
221
|
+
def GetDocumentation(
|
|
222
|
+
self, index: int
|
|
223
|
+
) -> Tuple[str, Optional[str], int, Optional[str]]:
|
|
223
224
|
"""Return documentation for a type description."""
|
|
224
225
|
...
|
|
225
226
|
|
|
@@ -227,11 +228,11 @@ class ITypeLib(IUnknown):
|
|
|
227
228
|
"""Release TLIBATTR"""
|
|
228
229
|
...
|
|
229
230
|
|
|
230
|
-
_GetLibAttr: Callable[[], "_Pointer[TLIBATTR]"]
|
|
231
|
-
|
|
232
231
|
def GetLibAttr(self) -> "TLIBATTR":
|
|
233
232
|
"""Return type library attributes"""
|
|
234
|
-
return _deref_with_release(
|
|
233
|
+
return _deref_with_release(
|
|
234
|
+
self._GetLibAttr(), self.ReleaseTLibAttr # type: ignore
|
|
235
|
+
)
|
|
235
236
|
|
|
236
237
|
def IsName(self, name: str, lHashVal: int = 0) -> Optional[str]:
|
|
237
238
|
"""Check if there is type information for this name.
|
|
@@ -341,27 +342,30 @@ class ITypeInfo(IUnknown):
|
|
|
341
342
|
"""Releases a VARDESC previously returned by VarDesc"""
|
|
342
343
|
...
|
|
343
344
|
|
|
344
|
-
|
|
345
|
-
_GetFuncDesc: Callable[[int], "_Pointer[FUNCDESC]"]
|
|
346
|
-
_GetVarDesc: Callable[[int], "_Pointer[VARDESC]"]
|
|
347
|
-
_GetDocumentation: Callable[[int], Tuple[str, str, int, Optional[str]]]
|
|
348
|
-
|
|
349
|
-
def GetTypeAttr(self):
|
|
345
|
+
def GetTypeAttr(self) -> "TYPEATTR":
|
|
350
346
|
"""Return the TYPEATTR for this type"""
|
|
351
|
-
return _deref_with_release(
|
|
347
|
+
return _deref_with_release(
|
|
348
|
+
self._GetTypeAttr(), self.ReleaseTypeAttr # type: ignore
|
|
349
|
+
)
|
|
352
350
|
|
|
353
|
-
def GetDocumentation(
|
|
351
|
+
def GetDocumentation(
|
|
352
|
+
self, memid: int
|
|
353
|
+
) -> Tuple[str, Optional[str], int, Optional[str]]:
|
|
354
354
|
"""Return name, docstring, helpcontext, and helpfile for 'memid'."""
|
|
355
|
-
name, doc,
|
|
356
|
-
return fix_name(name), fix_name(doc),
|
|
355
|
+
name, doc, helpctx, helpfile = self._GetDocumentation(memid) # type: ignore
|
|
356
|
+
return fix_name(name), fix_name(doc), helpctx, fix_name(helpfile)
|
|
357
357
|
|
|
358
|
-
def GetFuncDesc(self, index):
|
|
358
|
+
def GetFuncDesc(self, index: int) -> "FUNCDESC":
|
|
359
359
|
"""Return FUNCDESC for index"""
|
|
360
|
-
return _deref_with_release(
|
|
360
|
+
return _deref_with_release(
|
|
361
|
+
self._GetFuncDesc(index), self.ReleaseFuncDesc # type: ignore
|
|
362
|
+
)
|
|
361
363
|
|
|
362
|
-
def GetVarDesc(self, index):
|
|
364
|
+
def GetVarDesc(self, index: int) -> "VARDESC":
|
|
363
365
|
"""Return VARDESC for index"""
|
|
364
|
-
return _deref_with_release(
|
|
366
|
+
return _deref_with_release(
|
|
367
|
+
self._GetVarDesc(index), self.ReleaseVarDesc # type: ignore
|
|
368
|
+
)
|
|
365
369
|
|
|
366
370
|
def GetNames(self, memid: int, count: int = 1) -> List[str]:
|
|
367
371
|
"""Return names for memid"""
|
|
@@ -455,13 +459,12 @@ class ICreateTypeLib2(ICreateTypeLib):
|
|
|
455
459
|
class ICreateTypeInfo(IUnknown):
|
|
456
460
|
_iid_ = GUID("{00020405-0000-0000-C000-000000000046}")
|
|
457
461
|
# C:/Programme/gccxml/bin/Vc71/PlatformSDK/oaidl.h 915
|
|
458
|
-
_SetFuncAndParamNames: Callable[[int, "ctypes.Array[c_wchar_p]", int], int]
|
|
459
462
|
|
|
460
463
|
def SetFuncAndParamNames(self, index: int, *names: str) -> int:
|
|
461
464
|
rgszNames = (c_wchar_p * len(names))()
|
|
462
465
|
for i, n in enumerate(names):
|
|
463
466
|
rgszNames[i] = n
|
|
464
|
-
return self._SetFuncAndParamNames(index, rgszNames, len(names))
|
|
467
|
+
return self._SetFuncAndParamNames(index, rgszNames, len(names)) # type: ignore
|
|
465
468
|
|
|
466
469
|
|
|
467
470
|
class IRecordInfo(IUnknown):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: comtypes
|
|
3
|
-
Version: 1.4.
|
|
3
|
+
Version: 1.4.7
|
|
4
4
|
Summary: Pure Python COM package
|
|
5
5
|
Home-page: https://github.com/enthought/comtypes
|
|
6
6
|
Download-URL: https://github.com/enthought/comtypes/releases
|
|
@@ -13,7 +13,7 @@ Classifier: Operating System :: Microsoft :: Windows
|
|
|
13
13
|
Classifier: Programming Language :: Python
|
|
14
14
|
Classifier: Programming Language :: Python :: 3
|
|
15
15
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
16
|
-
Requires-Python: >=3.
|
|
16
|
+
Requires-Python: >=3.8
|
|
17
17
|
Description-Content-Type: text/markdown
|
|
18
18
|
License-File: LICENSE.txt
|
|
19
19
|
|
|
@@ -24,47 +24,40 @@ License-File: LICENSE.txt
|
|
|
24
24
|
[](https://github.com/enthought/comtypes/stargazers) [](https://github.com/enthought/comtypes/network/members)
|
|
25
25
|
[](https://tidelift.com/subscription/pkg/pypi-comtypes?utm_source=pypi-comtypes&utm_medium=readme)
|
|
26
26
|
|
|
27
|
-
## About
|
|
28
27
|
|
|
29
|
-
`comtypes` is a lightweight
|
|
28
|
+
`comtypes` is a lightweight pure Python [COM](https://learn.microsoft.com/en-us/windows/win32/com/component-object-model--com--portal) package based on the [`ctypes`](https://docs.python.org/library/ctypes.html) foreign function interface library.
|
|
30
29
|
|
|
31
|
-
`comtypes` allows to define, call, and implement custom and dispatch-based COM interfaces in pure
|
|
30
|
+
`comtypes` allows you to define, call, and implement custom and dispatch-based COM interfaces in pure Python.
|
|
32
31
|
|
|
33
|
-
|
|
32
|
+
`comtypes` requires Windows and Python 3.8 or later.
|
|
33
|
+
- Version [1.4.6](https://pypi.org/project/comtypes/1.4.6/) is the last version to support Python 3.7.
|
|
34
|
+
- Version [1.2.1](https://pypi.org/project/comtypes/1.2.1/) is the last version to support Python 2.7 and 3.3–3.6.
|
|
35
|
+
- `comtypes` does not work with Python 3.8.1 as reported in [GH-202](https://github.com/enthought/comtypes/issues/202). This bug has been fixed in Python >= 3.8.2.
|
|
36
|
+
- Certain `comtypes` functions may not work correctly in Python 3.8 and 3.9 as reported in [GH-212](https://github.com/enthought/comtypes/issues/212). This bug has been fixed in Python >= 3.10.10 and >= 3.11.2.
|
|
34
37
|
|
|
35
|
-
|
|
36
|
-
- [`comtypes==1.2.1`](https://pypi.org/project/comtypes/1.2.1/) is the last version supporting `Python` 2.7 and 3.3-3.6.
|
|
37
|
-
- In `Python` 3.7.6 and 3.8.1, `comtypes` would not work as reported in [GH-202](https://github.com/enthought/comtypes/issues/202).
|
|
38
|
-
This bug has been fixed in `Python` >= 3.7.7 and >= 3.8.2.
|
|
39
|
-
- In `Python` 3.8 and 3.9, some of `comtypes` functionalities may not work correctly as reported in [GH-212](https://github.com/enthought/comtypes/issues/212).
|
|
40
|
-
This bug has been fixed in `Python` >= 3.10.10 and >= 3.11.2.
|
|
41
|
-
|
|
42
|
-
## Where to get it
|
|
43
|
-
|
|
44
|
-
The source code is currently hosted on GitHub at:
|
|
45
|
-
https://github.com/enthought/comtypes
|
|
46
|
-
|
|
47
|
-
An installer for the latest released version is available at the [Python Package Index (PyPI)](https://pypi.org/project/comtypes).
|
|
38
|
+
## Installation
|
|
48
39
|
|
|
40
|
+
`comtypes` is available on [PyPI](https://pypi.org/project/comtypes) and can be installed with `pip`:
|
|
49
41
|
```sh
|
|
50
42
|
# PyPI
|
|
51
43
|
pip install comtypes
|
|
52
44
|
```
|
|
53
45
|
|
|
54
|
-
|
|
46
|
+
The source code is currently hosted [here](https://github.com/enthought/comtypes) on GitHub.
|
|
47
|
+
|
|
48
|
+
### Dependencies
|
|
55
49
|
|
|
56
|
-
`comtypes`
|
|
50
|
+
`comtypes` is a pure Python package — it has no additional required dependencies.
|
|
57
51
|
|
|
58
|
-
Optional
|
|
59
|
-
- to process arrays as `numpy`'s `ndarray
|
|
60
|
-
-
|
|
52
|
+
Optional functionalities can be enabled by installing:
|
|
53
|
+
- `numpy`, in order to process arrays as `numpy`'s `ndarray`.
|
|
54
|
+
- `mypy` or other static type checkers, in order to interpret type hints.
|
|
61
55
|
|
|
62
|
-
|
|
56
|
+
None of these packages, however, are required in order to run `comtypes`.
|
|
63
57
|
|
|
64
|
-
## Community
|
|
58
|
+
## Community
|
|
65
59
|
|
|
66
|
-
|
|
67
|
-
https://github.com/enthought/comtypes
|
|
60
|
+
The [GitHub repository](https://github.com/enthought/comtypes) is used for tracking issues, reporting bugs, and contributing to the codebase and documentation.
|
|
68
61
|
|
|
69
62
|
## For Enterprise
|
|
70
63
|
|
|
@@ -77,17 +70,17 @@ This project and the maintainers of thousands of other packages are working with
|
|
|
77
70
|
## Frequently Asked Questions
|
|
78
71
|
|
|
79
72
|
### Q: Why does this package not support platforms other than Windows?
|
|
80
|
-
**A:**
|
|
73
|
+
**A:** The [Microsoft Component Object Model (COM)](https://learn.microsoft.com/en-us/windows/win32/com/com-technical-overview) is a technology that is unique to Windows and is not supported on other platforms.
|
|
81
74
|
|
|
82
75
|
[The phrase _"COM is a platform-independent"_ in the MS documentation](https://learn.microsoft.com/en-us/windows/win32/com/component-object-model--com--portal) means that COM maintains compatibility across different versions of Windows, and does NOT imply that it is supported on Linux or Mac.
|
|
83
76
|
|
|
84
|
-
|
|
77
|
+
For as long as COM is not supported outside of Windows, there is no plan to port `comtypes` to other platforms.
|
|
85
78
|
|
|
86
79
|
### Q: Why does `cannot import name 'COMError' from '_ctypes'` error occur when using this package on platforms other than Windows?
|
|
87
|
-
**A:** The [`_ctypes`](https://github.com/python/cpython/blob/main/Modules/_ctypes/_ctypes.c) is part of the internal implementation of the [`ctypes`](https://github.com/python/cpython/blob/main/Lib/ctypes/) standard library that exists for Python on all platforms.
|
|
88
|
-
However, `COMError` and COM-related features are implemented
|
|
80
|
+
**A:** The [`_ctypes`](https://github.com/python/cpython/blob/main/Modules/_ctypes/_ctypes.c) is part of the internal implementation of the [`ctypes`](https://github.com/python/cpython/blob/main/Lib/ctypes/) standard library that exists for Python on all platforms.
|
|
81
|
+
However, `COMError` and COM-related features are only implemented in Python for Windows.
|
|
89
82
|
|
|
90
|
-
In cross-platform software development, care must be taken to ensure that
|
|
83
|
+
In cross-platform software development, care must be taken to ensure that codebases that depend on `comtypes` do not execute in environments other than Windows.
|
|
91
84
|
|
|
92
85
|
### Q: Despite a script that depends on `comtypes` having run successfully before, a error (`ImportError`, `NameError`, or `SyntaxError`) is raised now, and the same error occurs again and again.
|
|
93
86
|
|
|
@@ -102,7 +95,6 @@ After deleting these partial modules and running the script again, `comtypes.cli
|
|
|
102
95
|
|
|
103
96
|
However, if the script implementation does not use `comtypes.client.GetModule` or processes generated files, it may not be a solution.
|
|
104
97
|
|
|
105
|
-
## Documentation
|
|
98
|
+
## Documentation
|
|
106
99
|
|
|
107
|
-
The documentation is currently hosted on
|
|
108
|
-
https://pythonhosted.org/comtypes
|
|
100
|
+
The documentation is currently hosted [here](https://pythonhosted.org/comtypes) on PythonHosted.
|
|
@@ -95,19 +95,23 @@ comtypes/test/test_ie.py
|
|
|
95
95
|
comtypes/test/test_ienum.py
|
|
96
96
|
comtypes/test/test_imfattributes.py
|
|
97
97
|
comtypes/test/test_inout_args.py
|
|
98
|
-
comtypes/test/test_istream.py
|
|
99
98
|
comtypes/test/test_jscript.js
|
|
100
99
|
comtypes/test/test_midl_safearray_create.py
|
|
100
|
+
comtypes/test/test_monikers.py
|
|
101
101
|
comtypes/test/test_msscript.py
|
|
102
102
|
comtypes/test/test_npsupport.py
|
|
103
103
|
comtypes/test/test_outparam.py
|
|
104
|
+
comtypes/test/test_persist.py
|
|
104
105
|
comtypes/test/test_propputref.py
|
|
105
106
|
comtypes/test/test_pump_events.py
|
|
106
107
|
comtypes/test/test_recordinfo.py
|
|
107
108
|
comtypes/test/test_safearray.py
|
|
108
109
|
comtypes/test/test_sapi.py
|
|
109
110
|
comtypes/test/test_server.py
|
|
111
|
+
comtypes/test/test_shelllink.py
|
|
110
112
|
comtypes/test/test_showevents.py
|
|
113
|
+
comtypes/test/test_storage.py
|
|
114
|
+
comtypes/test/test_stream.py
|
|
111
115
|
comtypes/test/test_subinterface.py
|
|
112
116
|
comtypes/test/test_typeannotator.py
|
|
113
117
|
comtypes/test/test_typeinfo.py
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|