comtypes 1.4.16__tar.gz → 1.4.17__tar.gz
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.16 → comtypes-1.4.17}/CHANGES.txt +11 -0
- {comtypes-1.4.16/comtypes.egg-info → comtypes-1.4.17}/PKG-INFO +1 -1
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/__init__.py +1 -1
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/_post_coinit/misc.py +8 -7
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/client/_activeobj.py +17 -3
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/client/_create.py +47 -11
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/client/_events.py +13 -1
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/git.py +15 -26
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/messageloop.py +21 -3
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/test_basic.py +8 -11
- comtypes-1.4.17/comtypes/test/test_eventinterface.py +155 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/test_git.py +7 -9
- comtypes-1.4.17/comtypes/test/test_packing.py +49 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/test_util.py +20 -1
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/tools/codegenerator/packing.py +6 -1
- {comtypes-1.4.16 → comtypes-1.4.17/comtypes.egg-info}/PKG-INFO +1 -1
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes.egg-info/SOURCES.txt +1 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/pyproject.toml +0 -1
- comtypes-1.4.16/comtypes/test/test_eventinterface.py +0 -150
- {comtypes-1.4.16 → comtypes-1.4.17}/LICENSE.txt +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/MANIFEST.in +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/README.md +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/GUID.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/_comobject.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/_memberspec.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/_meta.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/_npsupport.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/_post_coinit/__init__.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/_post_coinit/_cominterface_meta_patcher.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/_post_coinit/activeobj.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/_post_coinit/bstr.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/_post_coinit/instancemethod.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/_post_coinit/unknwn.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/_safearray.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/_tlib_version_checker.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/_vtbl.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/automation.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/clear_cache.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/client/__init__.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/client/_code_cache.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/client/_constants.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/client/_generate.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/client/_managing.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/client/dynamic.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/client/lazybind.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/connectionpoints.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/errorinfo.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/hints.pyi +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/hresult.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/logutil.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/malloc.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/patcher.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/persist.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/safearray.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/server/__init__.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/server/automation.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/server/connectionpoints.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/server/inprocserver.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/server/localserver.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/server/register.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/server/w_getopt.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/shelllink.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/stream.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/TestComServer.idl +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/TestComServer.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/TestComServer.tlb +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/TestDispServer.idl +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/TestDispServer.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/TestDispServer.tlb +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/__init__.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/find_memleak.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/gdi_helper.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/monikers_helper.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/mylib.idl +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/mylib.tlb +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/mytypelib.idl +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/runtests.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/setup.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/test_BSTR.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/test_DISPPARAMS.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/test_GUID.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/test_QueryService.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/test_agilent.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/test_avmc.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/test_bctx.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/test_casesensitivity.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/test_classfactory.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/test_clear_cache.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/test_client.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/test_client_dynamic.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/test_client_regenerate_modules.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/test_collections.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/test_comobject.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/test_comserver.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/test_connectionpoints.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/test_createwrappers.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/test_dict.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/test_dispifc_records.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/test_dispifc_safearrays.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/test_dispinterface.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/test_dyndispatch.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/test_errorinfo.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/test_excel.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/test_findgendir.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/test_getactiveobj.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/test_hresult.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/test_ienum.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/test_imfattributes.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/test_inout_args.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/test_jscript.js +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/test_logutil.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/test_malloc.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/test_messageloop.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/test_midl_safearray_create.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/test_moniker.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/test_msscript.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/test_npsupport.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/test_outparam.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/test_persist.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/test_pump_events.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/test_puredispatch.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/test_recordinfo.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/test_rot.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/test_safearray.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/test_sapi.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/test_server.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/test_server_automation.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/test_server_register.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/test_shelllink.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/test_showevents.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/test_storage.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/test_stream.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/test_subinterface.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/test_typeannotator.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/test_typeinfo.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/test_typeinfo_create.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/test_urlhistory.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/test_variant.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/test_variant_outparam.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/test_viewobject.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/test_w_getopt.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/test_win32com_interop.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/test_word.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/time_structs_helper.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/test/urlhist.tlb +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/tools/__init__.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/tools/codegenerator/__init__.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/tools/codegenerator/codegenerator.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/tools/codegenerator/comments.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/tools/codegenerator/heads.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/tools/codegenerator/helpers.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/tools/codegenerator/modulenamer.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/tools/codegenerator/namespaces.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/tools/codegenerator/typeannotator.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/tools/tlbparser.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/tools/typedesc.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/tools/typedesc_base.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/typeinfo.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/util.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes/viewobject.py +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes.egg-info/dependency_links.txt +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes.egg-info/entry_points.txt +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/comtypes.egg-info/top_level.txt +0 -0
- {comtypes-1.4.16 → comtypes-1.4.17}/setup.cfg +0 -0
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
Comtypes CHANGELOG
|
|
2
2
|
==================
|
|
3
3
|
|
|
4
|
+
Release 1.4.17
|
|
5
|
+
--------------
|
|
6
|
+
* Unify Windows message handling APIs in ``messageloop.py``. By @junkmd.
|
|
7
|
+
* Replace Internet Explorer with MSXML in ``test_eventinterface.py``. By @junkmd.
|
|
8
|
+
* Improve error handling for ``GetEvents`` with currently unsupported COM servers. By @junkmd.
|
|
9
|
+
* Refactor ``test_basic.py`` to use public APIs. By @junkmd.
|
|
10
|
+
* Skip tests using ``util`` on Python 3.15 alpha/beta. By @junkmd.
|
|
11
|
+
* Refine type hints for COM object creation and retrieval. By @junkmd.
|
|
12
|
+
* Modernize ``IGlobalInterfaceTable`` with type hints. By @junkmd.
|
|
13
|
+
* Fix ``UnboundLocalError`` when all struct packings fail in ``calc_packing``. By @ryanda9910.
|
|
14
|
+
|
|
4
15
|
Release 1.4.16
|
|
5
16
|
--------------
|
|
6
17
|
* Decompose ``IStorage`` tests and enhance coverage. By @junkmd.
|
|
@@ -14,6 +14,7 @@ from ctypes import (
|
|
|
14
14
|
)
|
|
15
15
|
from ctypes.wintypes import DWORD, LPCWSTR, LPVOID
|
|
16
16
|
from typing import TYPE_CHECKING, Any, Optional, TypeVar, overload
|
|
17
|
+
from typing import Union as _UnionT
|
|
17
18
|
|
|
18
19
|
from comtypes import CLSCTX_LOCAL_SERVER, CLSCTX_REMOTE_SERVER, CLSCTX_SERVER, GUID
|
|
19
20
|
from comtypes._memberspec import COMMETHOD
|
|
@@ -21,7 +22,7 @@ from comtypes._post_coinit.unknwn import IUnknown
|
|
|
21
22
|
from comtypes.GUID import REFCLSID
|
|
22
23
|
|
|
23
24
|
if TYPE_CHECKING:
|
|
24
|
-
from ctypes import _Pointer
|
|
25
|
+
from ctypes import _CArgObject, _Pointer
|
|
25
26
|
|
|
26
27
|
from comtypes import hints as hints # noqa # type: ignore
|
|
27
28
|
|
|
@@ -146,20 +147,20 @@ def CoCreateInstance(
|
|
|
146
147
|
def CoGetClassObject(
|
|
147
148
|
clsid: GUID,
|
|
148
149
|
clsctx: Optional[int] = None,
|
|
149
|
-
pServerInfo: "
|
|
150
|
+
pServerInfo: "_UnionT[None, _CArgObject, COSERVERINFO]" = None,
|
|
150
151
|
interface: None = None,
|
|
151
152
|
) -> "hints.IClassFactory": ...
|
|
152
153
|
@overload
|
|
153
154
|
def CoGetClassObject(
|
|
154
155
|
clsid: GUID,
|
|
155
156
|
clsctx: Optional[int] = None,
|
|
156
|
-
pServerInfo: "
|
|
157
|
+
pServerInfo: "_UnionT[None, _CArgObject, COSERVERINFO]" = None,
|
|
157
158
|
interface: type[_T_IUnknown] = IUnknown,
|
|
158
159
|
) -> _T_IUnknown: ...
|
|
159
160
|
def CoGetClassObject(
|
|
160
161
|
clsid: GUID,
|
|
161
162
|
clsctx: Optional[int] = None,
|
|
162
|
-
pServerInfo: "
|
|
163
|
+
pServerInfo: "_UnionT[None, _CArgObject, COSERVERINFO]" = None,
|
|
163
164
|
interface: Optional[type[IUnknown]] = None,
|
|
164
165
|
) -> IUnknown:
|
|
165
166
|
if clsctx is None:
|
|
@@ -337,7 +338,7 @@ def CoCreateInstanceEx(
|
|
|
337
338
|
interface: None = None,
|
|
338
339
|
clsctx: Optional[int] = None,
|
|
339
340
|
machine: Optional[str] = None,
|
|
340
|
-
pServerInfo:
|
|
341
|
+
pServerInfo: "_UnionT[None, _CArgObject, COSERVERINFO]" = None,
|
|
341
342
|
) -> IUnknown: ...
|
|
342
343
|
@overload
|
|
343
344
|
def CoCreateInstanceEx(
|
|
@@ -345,14 +346,14 @@ def CoCreateInstanceEx(
|
|
|
345
346
|
interface: type[_T_IUnknown],
|
|
346
347
|
clsctx: Optional[int] = None,
|
|
347
348
|
machine: Optional[str] = None,
|
|
348
|
-
pServerInfo:
|
|
349
|
+
pServerInfo: "_UnionT[None, _CArgObject, COSERVERINFO]" = None,
|
|
349
350
|
) -> _T_IUnknown: ...
|
|
350
351
|
def CoCreateInstanceEx(
|
|
351
352
|
clsid: GUID,
|
|
352
353
|
interface: Optional[type[IUnknown]] = None,
|
|
353
354
|
clsctx: Optional[int] = None,
|
|
354
355
|
machine: Optional[str] = None,
|
|
355
|
-
pServerInfo:
|
|
356
|
+
pServerInfo: "_UnionT[None, _CArgObject, COSERVERINFO]" = None,
|
|
356
357
|
) -> IUnknown:
|
|
357
358
|
"""The basic windows api to create a COM class object and return a
|
|
358
359
|
pointer to an interface, possibly on another machine.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from typing import Any, Optional, TypeVar, overload
|
|
1
|
+
from typing import Any, Literal, Optional, TypeVar, overload
|
|
2
2
|
from typing import Union as _UnionT
|
|
3
3
|
|
|
4
4
|
import comtypes
|
|
@@ -14,10 +14,24 @@ _T_IUnknown = TypeVar("_T_IUnknown", bound=IUnknown)
|
|
|
14
14
|
# Object creation
|
|
15
15
|
#
|
|
16
16
|
@overload
|
|
17
|
-
def GetActiveObject(
|
|
17
|
+
def GetActiveObject(
|
|
18
|
+
progid: _UnionT[str, type[CoClass], GUID],
|
|
19
|
+
interface: None = None,
|
|
20
|
+
dynamic: Literal[False] = False,
|
|
21
|
+
) -> Any: ...
|
|
22
|
+
@overload
|
|
23
|
+
def GetActiveObject(
|
|
24
|
+
progid: _UnionT[str, type[CoClass], GUID],
|
|
25
|
+
interface: None = None,
|
|
26
|
+
dynamic: Literal[True] = True,
|
|
27
|
+
) -> _UnionT[
|
|
28
|
+
"comtypes.client.lazybind.Dispatch", "comtypes.client.dynamic._Dispatch"
|
|
29
|
+
]: ...
|
|
18
30
|
@overload
|
|
19
31
|
def GetActiveObject(
|
|
20
|
-
progid: _UnionT[str, type[CoClass], GUID],
|
|
32
|
+
progid: _UnionT[str, type[CoClass], GUID],
|
|
33
|
+
interface: type[_T_IUnknown] = IUnknown,
|
|
34
|
+
dynamic: Literal[False] = False,
|
|
21
35
|
) -> _T_IUnknown: ...
|
|
22
36
|
def GetActiveObject(
|
|
23
37
|
progid: _UnionT[str, type[CoClass], GUID],
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import logging
|
|
2
|
-
from typing import TYPE_CHECKING, Any, Optional, TypeVar, overload
|
|
2
|
+
from typing import TYPE_CHECKING, Any, Literal, Optional, TypeVar, overload
|
|
3
3
|
from typing import Union as _UnionT
|
|
4
4
|
|
|
5
5
|
import comtypes
|
|
@@ -8,6 +8,8 @@ from comtypes import COSERVERINFO, GUID, CoClass, IUnknown, automation
|
|
|
8
8
|
from comtypes.client._managing import _manage
|
|
9
9
|
|
|
10
10
|
if TYPE_CHECKING:
|
|
11
|
+
from ctypes import _CArgObject
|
|
12
|
+
|
|
11
13
|
from comtypes import hints # type: ignore
|
|
12
14
|
|
|
13
15
|
|
|
@@ -23,20 +25,20 @@ logger = logging.getLogger(__name__)
|
|
|
23
25
|
def GetClassObject(
|
|
24
26
|
progid: _UnionT[str, type[CoClass], GUID],
|
|
25
27
|
clsctx: Optional[int] = None,
|
|
26
|
-
pServerInfo:
|
|
28
|
+
pServerInfo: "_UnionT[None, _CArgObject, COSERVERINFO]" = None,
|
|
27
29
|
interface: None = None,
|
|
28
30
|
) -> "hints.IClassFactory": ...
|
|
29
31
|
@overload
|
|
30
32
|
def GetClassObject(
|
|
31
33
|
progid: _UnionT[str, type[CoClass], GUID],
|
|
32
34
|
clsctx: Optional[int] = None,
|
|
33
|
-
pServerInfo:
|
|
35
|
+
pServerInfo: "_UnionT[None, _CArgObject, COSERVERINFO]" = None,
|
|
34
36
|
interface: type[_T_IUnknown] = IUnknown,
|
|
35
37
|
) -> _T_IUnknown: ...
|
|
36
38
|
def GetClassObject(
|
|
37
39
|
progid: _UnionT[str, type[CoClass], GUID],
|
|
38
40
|
clsctx: Optional[int] = None,
|
|
39
|
-
pServerInfo:
|
|
41
|
+
pServerInfo: "_UnionT[None, _CArgObject, COSERVERINFO]" = None,
|
|
40
42
|
interface: Optional[type[IUnknown]] = None,
|
|
41
43
|
) -> IUnknown:
|
|
42
44
|
"""Create and return the class factory for a COM object.
|
|
@@ -56,9 +58,29 @@ def CreateObject(
|
|
|
56
58
|
progid: _UnionT[str, type[CoClass], GUID],
|
|
57
59
|
clsctx: Optional[int] = None,
|
|
58
60
|
machine: Optional[str] = None,
|
|
59
|
-
interface:
|
|
60
|
-
dynamic:
|
|
61
|
-
pServerInfo:
|
|
61
|
+
interface: None = None,
|
|
62
|
+
dynamic: Literal[False] = False,
|
|
63
|
+
pServerInfo: "_UnionT[None, _CArgObject, COSERVERINFO]" = None,
|
|
64
|
+
) -> Any: ...
|
|
65
|
+
@overload
|
|
66
|
+
def CreateObject(
|
|
67
|
+
progid: _UnionT[str, type[CoClass], GUID],
|
|
68
|
+
clsctx: Optional[int] = None,
|
|
69
|
+
machine: Optional[str] = None,
|
|
70
|
+
interface: None = None,
|
|
71
|
+
dynamic: Literal[True] = True,
|
|
72
|
+
pServerInfo: "_UnionT[None, _CArgObject, COSERVERINFO]" = None,
|
|
73
|
+
) -> _UnionT[
|
|
74
|
+
"comtypes.client.lazybind.Dispatch", "comtypes.client.dynamic._Dispatch"
|
|
75
|
+
]: ...
|
|
76
|
+
@overload
|
|
77
|
+
def CreateObject(
|
|
78
|
+
progid: _UnionT[str, type[CoClass], GUID],
|
|
79
|
+
clsctx: Optional[int] = None,
|
|
80
|
+
machine: Optional[str] = None,
|
|
81
|
+
interface: type[_T_IUnknown] = IUnknown,
|
|
82
|
+
dynamic: Literal[False] = False,
|
|
83
|
+
pServerInfo: "_UnionT[None, _CArgObject, COSERVERINFO]" = None,
|
|
62
84
|
) -> _T_IUnknown: ...
|
|
63
85
|
def CreateObject(
|
|
64
86
|
progid: _UnionT[str, type[CoClass], GUID], # which object to create
|
|
@@ -66,7 +88,7 @@ def CreateObject(
|
|
|
66
88
|
machine: Optional[str] = None, # where to create the object
|
|
67
89
|
interface: Optional[type[IUnknown]] = None, # the interface we want
|
|
68
90
|
dynamic: bool = False, # use dynamic dispatch
|
|
69
|
-
pServerInfo:
|
|
91
|
+
pServerInfo: "_UnionT[None, _CArgObject, COSERVERINFO]" = None, # server info struct for remoting
|
|
70
92
|
) -> Any:
|
|
71
93
|
"""Create a COM object from 'progid', and try to QueryInterface()
|
|
72
94
|
it to the most useful interface, generating typelib support on
|
|
@@ -122,12 +144,26 @@ def CreateObject(
|
|
|
122
144
|
return _manage(obj, clsid, interface=interface)
|
|
123
145
|
|
|
124
146
|
|
|
125
|
-
@overload
|
|
126
|
-
def CoGetObject(displayname: str, interface: type[_T_IUnknown]) -> _T_IUnknown: ...
|
|
127
147
|
@overload
|
|
128
148
|
def CoGetObject(
|
|
129
|
-
displayname: str,
|
|
149
|
+
displayname: str,
|
|
150
|
+
interface: None = None,
|
|
151
|
+
dynamic: Literal[False] = False,
|
|
130
152
|
) -> Any: ...
|
|
153
|
+
@overload
|
|
154
|
+
def CoGetObject(
|
|
155
|
+
displayname: str,
|
|
156
|
+
interface: None = None,
|
|
157
|
+
dynamic: Literal[True] = True,
|
|
158
|
+
) -> _UnionT[
|
|
159
|
+
"comtypes.client.lazybind.Dispatch", "comtypes.client.dynamic._Dispatch"
|
|
160
|
+
]: ...
|
|
161
|
+
@overload
|
|
162
|
+
def CoGetObject(
|
|
163
|
+
displayname: str,
|
|
164
|
+
interface: type[_T_IUnknown],
|
|
165
|
+
dynamic: Literal[False] = False,
|
|
166
|
+
) -> _T_IUnknown: ...
|
|
131
167
|
def CoGetObject(
|
|
132
168
|
displayname: str,
|
|
133
169
|
interface: Optional[type[IUnknown]] = None,
|
|
@@ -120,6 +120,10 @@ def FindOutgoingInterface(source: IUnknown) -> type[IUnknown]:
|
|
|
120
120
|
except COMError:
|
|
121
121
|
pass
|
|
122
122
|
else:
|
|
123
|
+
if guid == comtypes.GUID():
|
|
124
|
+
# Some COM servers, even if they implement `IProvideClassInfo2`,
|
|
125
|
+
# may return GUID_NULL instead of the default source interface's GUID.
|
|
126
|
+
raise NotImplementedError("retrieved outgoing interface IID is GUID_NULL")
|
|
123
127
|
# another try: block needed?
|
|
124
128
|
try:
|
|
125
129
|
interface = comtypes.com_interface_registry[str(guid)]
|
|
@@ -258,7 +262,15 @@ def CreateEventReceiver(interface: type[IUnknown], handler: Any) -> COMObject:
|
|
|
258
262
|
# Can dispid be at a different index? Should check code generator...
|
|
259
263
|
# ...but hand-written code should also work...
|
|
260
264
|
dispid = m.idlflags[0]
|
|
261
|
-
|
|
265
|
+
if not isinstance(dispid, comtypes.dispid):
|
|
266
|
+
# The interface is a subclass of `IDispatch` but its methods do not
|
|
267
|
+
# have DISPIDs, indicating it's not an interface suitable for event
|
|
268
|
+
# handling.
|
|
269
|
+
raise NotImplementedError(
|
|
270
|
+
"Event receiver creation requires event methods to have DISPIDs "
|
|
271
|
+
f"for dispatching, but '{interface.__name__}' ({interface._iid_}) "
|
|
272
|
+
"lacks them, even though it inherits from 'IDispatch'."
|
|
273
|
+
)
|
|
262
274
|
impl = finder.get_impl(interface, m.name, m.paramflags, m.idlflags)
|
|
263
275
|
# XXX Wouldn't work for 'propget', 'propput', 'propputref'
|
|
264
276
|
# methods - are they allowed on event interfaces?
|
|
@@ -4,12 +4,12 @@ The global interface table provides a way to marshal interface pointers
|
|
|
4
4
|
between different threading appartments.
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
|
-
from ctypes import
|
|
7
|
+
from ctypes import POINTER
|
|
8
8
|
from ctypes.wintypes import DWORD
|
|
9
|
+
from typing import Type, TypeVar
|
|
9
10
|
|
|
10
11
|
from comtypes import (
|
|
11
12
|
CLSCTX_INPROC_SERVER,
|
|
12
|
-
COMMETHOD,
|
|
13
13
|
GUID,
|
|
14
14
|
HRESULT,
|
|
15
15
|
STDMETHOD,
|
|
@@ -17,6 +17,8 @@ from comtypes import (
|
|
|
17
17
|
IUnknown,
|
|
18
18
|
)
|
|
19
19
|
|
|
20
|
+
_T_IUnknown = TypeVar("_T_IUnknown", bound=IUnknown)
|
|
21
|
+
|
|
20
22
|
|
|
21
23
|
class IGlobalInterfaceTable(IUnknown):
|
|
22
24
|
_iid_ = GUID("{00000146-0000-0000-C000-000000000046}")
|
|
@@ -34,18 +36,22 @@ class IGlobalInterfaceTable(IUnknown):
|
|
|
34
36
|
),
|
|
35
37
|
]
|
|
36
38
|
|
|
37
|
-
def RegisterInterfaceInGlobal(
|
|
39
|
+
def RegisterInterfaceInGlobal(
|
|
40
|
+
self, obj: IUnknown, interface: Type[_T_IUnknown] = IUnknown
|
|
41
|
+
) -> int:
|
|
38
42
|
cookie = DWORD()
|
|
39
|
-
self.__com_RegisterInterfaceInGlobal(obj, interface._iid_, cookie)
|
|
43
|
+
self.__com_RegisterInterfaceInGlobal(obj, interface._iid_, cookie) # type: ignore
|
|
40
44
|
return cookie.value
|
|
41
45
|
|
|
42
|
-
def GetInterfaceFromGlobal(
|
|
46
|
+
def GetInterfaceFromGlobal(
|
|
47
|
+
self, cookie: int, interface: Type[_T_IUnknown] = IUnknown
|
|
48
|
+
) -> _T_IUnknown:
|
|
43
49
|
ptr = POINTER(interface)()
|
|
44
|
-
self.__com_GetInterfaceFromGlobal(cookie, interface._iid_, ptr)
|
|
45
|
-
return ptr
|
|
50
|
+
self.__com_GetInterfaceFromGlobal(cookie, interface._iid_, ptr) # type: ignore
|
|
51
|
+
return ptr # type: ignore
|
|
46
52
|
|
|
47
|
-
def RevokeInterfaceFromGlobal(self, cookie):
|
|
48
|
-
self.__com_RevokeInterfaceFromGlobal(cookie)
|
|
53
|
+
def RevokeInterfaceFromGlobal(self, cookie: int) -> None:
|
|
54
|
+
self.__com_RevokeInterfaceFromGlobal(cookie) # type: ignore
|
|
49
55
|
|
|
50
56
|
|
|
51
57
|
# It was a pain to get this CLSID: it's neither in the registry, nor
|
|
@@ -69,20 +75,3 @@ __all__ = [
|
|
|
69
75
|
"GetInterfaceFromGlobal",
|
|
70
76
|
]
|
|
71
77
|
# fmt: on
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
if __name__ == "__main__":
|
|
75
|
-
from comtypes.typeinfo import CreateTypeLib, ICreateTypeLib
|
|
76
|
-
|
|
77
|
-
tlib = CreateTypeLib("foo.bar") # we don not save it later
|
|
78
|
-
assert (tlib.AddRef(), tlib.Release()) == (2, 1)
|
|
79
|
-
|
|
80
|
-
cookie = RegisterInterfaceInGlobal(tlib)
|
|
81
|
-
assert (tlib.AddRef(), tlib.Release()) == (3, 2)
|
|
82
|
-
|
|
83
|
-
GetInterfaceFromGlobal(cookie, ICreateTypeLib)
|
|
84
|
-
GetInterfaceFromGlobal(cookie, ICreateTypeLib)
|
|
85
|
-
GetInterfaceFromGlobal(cookie)
|
|
86
|
-
assert (tlib.AddRef(), tlib.Release()) == (3, 2)
|
|
87
|
-
RevokeInterfaceFromGlobal(cookie)
|
|
88
|
-
assert (tlib.AddRef(), tlib.Release()) == (2, 1)
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import ctypes
|
|
2
|
-
from ctypes import WinDLL, WinError, byref
|
|
3
|
-
from ctypes.wintypes import MSG
|
|
2
|
+
from ctypes import POINTER, WinDLL, WinError, byref
|
|
3
|
+
from ctypes.wintypes import BOOL, HWND, MSG
|
|
4
|
+
from ctypes.wintypes import LPLONG as LRESULT
|
|
4
5
|
from typing import TYPE_CHECKING, SupportsIndex
|
|
5
6
|
|
|
6
7
|
if TYPE_CHECKING:
|
|
@@ -10,12 +11,29 @@ if TYPE_CHECKING:
|
|
|
10
11
|
|
|
11
12
|
_FilterCallable = Callable[["_CArgObject"], Iterable[Any]] # type: ignore
|
|
12
13
|
|
|
14
|
+
# PeekMessage options
|
|
15
|
+
PM_NOREMOVE = 0x0000
|
|
16
|
+
PM_REMOVE = 0x0001
|
|
17
|
+
PM_NOYIELD = 0x0002
|
|
18
|
+
|
|
13
19
|
_user32 = WinDLL("user32")
|
|
14
20
|
|
|
15
21
|
GetMessage = _user32.GetMessageA
|
|
16
|
-
GetMessage.argtypes = [
|
|
22
|
+
GetMessage.argtypes = [POINTER(MSG), HWND, ctypes.c_uint, ctypes.c_uint]
|
|
23
|
+
GetMessage.restype = BOOL
|
|
24
|
+
|
|
17
25
|
TranslateMessage = _user32.TranslateMessage
|
|
26
|
+
TranslateMessage.argtypes = [POINTER(MSG)]
|
|
27
|
+
TranslateMessage.restype = BOOL
|
|
28
|
+
|
|
18
29
|
DispatchMessage = _user32.DispatchMessageA
|
|
30
|
+
DispatchMessage.argtypes = [POINTER(MSG)]
|
|
31
|
+
DispatchMessage.restype = LRESULT
|
|
32
|
+
|
|
33
|
+
# https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-peekmessagea
|
|
34
|
+
PeekMessage = _user32.PeekMessageA
|
|
35
|
+
PeekMessage.argtypes = [POINTER(MSG), HWND, ctypes.c_uint, ctypes.c_uint, ctypes.c_uint]
|
|
36
|
+
PeekMessage.restype = BOOL
|
|
19
37
|
|
|
20
38
|
|
|
21
39
|
class _MessageLoop:
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
##import ut
|
|
2
1
|
import unittest as ut
|
|
3
|
-
from ctypes import HRESULT, POINTER
|
|
2
|
+
from ctypes import HRESULT, POINTER
|
|
4
3
|
|
|
5
4
|
from comtypes import GUID, STDMETHOD, IUnknown
|
|
6
|
-
from comtypes.typeinfo import
|
|
5
|
+
from comtypes.typeinfo import SYS_WIN32, CreateTypeLib, ICreateTypeLib2
|
|
7
6
|
|
|
8
7
|
# XXX leaks references!
|
|
9
8
|
|
|
@@ -14,8 +13,6 @@ def method_count(interface):
|
|
|
14
13
|
|
|
15
14
|
class BasicTest(ut.TestCase):
|
|
16
15
|
def test_IUnknown(self):
|
|
17
|
-
from comtypes import IUnknown
|
|
18
|
-
|
|
19
16
|
self.assertEqual(method_count(IUnknown), 3)
|
|
20
17
|
|
|
21
18
|
def test_release(self):
|
|
@@ -24,8 +21,9 @@ class BasicTest(ut.TestCase):
|
|
|
24
21
|
def test_refcounts(self):
|
|
25
22
|
# Since all COM interfaces derive from IUnknown and have the same reference counting behavior, any interface
|
|
26
23
|
# — whether ICreateTypeLib2 or otherwise — could be used for this test.
|
|
27
|
-
p =
|
|
28
|
-
|
|
24
|
+
p = CreateTypeLib("blabla", syskind=SYS_WIN32)
|
|
25
|
+
self.assertIsInstance(p, ICreateTypeLib2)
|
|
26
|
+
self.assertIsInstance(p, IUnknown)
|
|
29
27
|
# initial refcount is 2
|
|
30
28
|
for i in range(2, 10):
|
|
31
29
|
self.assertEqual(p.AddRef(), i)
|
|
@@ -35,8 +33,9 @@ class BasicTest(ut.TestCase):
|
|
|
35
33
|
def test_qi(self):
|
|
36
34
|
# Since all COM interfaces derive from IUnknown and have the same QueryInterface behavior, any interface
|
|
37
35
|
# — whether ICreateTypeLib2 or otherwise — could be used for this test.
|
|
38
|
-
p =
|
|
39
|
-
|
|
36
|
+
p = CreateTypeLib("blabla", syskind=SYS_WIN32)
|
|
37
|
+
self.assertIsInstance(p, ICreateTypeLib2)
|
|
38
|
+
self.assertIsInstance(p, IUnknown)
|
|
40
39
|
self.assertEqual(p.AddRef(), 2)
|
|
41
40
|
self.assertEqual(p.Release(), 1)
|
|
42
41
|
|
|
@@ -115,8 +114,6 @@ class BasicTest(ut.TestCase):
|
|
|
115
114
|
self.assertEqual(a, b)
|
|
116
115
|
self.assertEqual(hash(a), hash(b))
|
|
117
116
|
|
|
118
|
-
from comtypes.typeinfo import CreateTypeLib
|
|
119
|
-
|
|
120
117
|
# we do not save the lib, so no file will be created.
|
|
121
118
|
# these should NOT be identical
|
|
122
119
|
a = CreateTypeLib("blahblah")
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import gc
|
|
2
|
+
import tempfile
|
|
3
|
+
import time
|
|
4
|
+
import unittest as ut
|
|
5
|
+
from ctypes import HRESULT, byref
|
|
6
|
+
from ctypes.wintypes import MSG
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
|
|
9
|
+
from comtypes import COMMETHOD, GUID, IUnknown
|
|
10
|
+
from comtypes.automation import DISPID
|
|
11
|
+
from comtypes.client import CreateObject, GetEvents
|
|
12
|
+
from comtypes.messageloop import (
|
|
13
|
+
PM_REMOVE,
|
|
14
|
+
DispatchMessage,
|
|
15
|
+
PeekMessage,
|
|
16
|
+
TranslateMessage,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
# The primary goal is to verify how `GetEvents` behaves when the
|
|
20
|
+
# `interface` argument is explicitly specified versus when it is omitted,
|
|
21
|
+
# using an object that has multiple outgoing event interfaces.
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class IPropertyNotifySink(IUnknown):
|
|
25
|
+
# https://learn.microsoft.com/en-us/windows/win32/api/ocidl/nn-ocidl-ipropertynotifysink
|
|
26
|
+
_iid_ = GUID("{9BFBBC02-EFF1-101A-84ED-00AA00341D07}")
|
|
27
|
+
_methods_ = [
|
|
28
|
+
# Called when a property has changed.
|
|
29
|
+
COMMETHOD([], HRESULT, "OnChanged", (["in"], DISPID, "dispid")),
|
|
30
|
+
# Called when an object wants to know if it's okay to change a property.
|
|
31
|
+
COMMETHOD([], HRESULT, "OnRequestEdit", (["in"], DISPID, "dispid")),
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class EventSink:
|
|
36
|
+
def __init__(self):
|
|
37
|
+
self._events = []
|
|
38
|
+
|
|
39
|
+
# Events from the default dispatch interface
|
|
40
|
+
def onreadystatechange(self, this, *args):
|
|
41
|
+
self._events.append("onreadystatechange")
|
|
42
|
+
|
|
43
|
+
def ondataavailable(self, this, *args):
|
|
44
|
+
self._events.append("ondataavailable")
|
|
45
|
+
|
|
46
|
+
# Events from `IPropertyNotifySink`
|
|
47
|
+
def OnChanged(self, this, *args):
|
|
48
|
+
self._events.append("OnChanged")
|
|
49
|
+
|
|
50
|
+
def OnRequestEdit(self, this, *args):
|
|
51
|
+
self._events.append("OnRequestEdit")
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def PumpWaitingMessages():
|
|
55
|
+
msg = MSG()
|
|
56
|
+
while PeekMessage(byref(msg), 0, 0, 0, PM_REMOVE):
|
|
57
|
+
TranslateMessage(byref(msg))
|
|
58
|
+
DispatchMessage(byref(msg))
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
class Test_MSXML(ut.TestCase):
|
|
62
|
+
def setUp(self):
|
|
63
|
+
# We use `Msxml2.DOMDocument` because it is a built-in Windows
|
|
64
|
+
# component that supports both a default source interface and the
|
|
65
|
+
# `IPropertyNotifySink` connection point.
|
|
66
|
+
self.doc = CreateObject("Msxml2.DOMDocument")
|
|
67
|
+
self.doc.async_ = True
|
|
68
|
+
|
|
69
|
+
def tearDown(self):
|
|
70
|
+
del self.doc
|
|
71
|
+
# Force garbage collection and wait slightly to ensure COM resources
|
|
72
|
+
# are released properly between tests.
|
|
73
|
+
gc.collect()
|
|
74
|
+
time.sleep(2)
|
|
75
|
+
|
|
76
|
+
def test_default_eventinterface(self):
|
|
77
|
+
# Verify that `GetEvents` automatically connects to the default source
|
|
78
|
+
# interface (dispatch events like `onreadystatechange`) when no
|
|
79
|
+
# interface is explicitly requested.
|
|
80
|
+
sink = EventSink()
|
|
81
|
+
conn = GetEvents(self.doc, sink)
|
|
82
|
+
self.doc.loadXML("<root/>")
|
|
83
|
+
|
|
84
|
+
# Give the message loop time to process incoming events.
|
|
85
|
+
for _ in range(50):
|
|
86
|
+
PumpWaitingMessages()
|
|
87
|
+
time.sleep(0.1)
|
|
88
|
+
# Should receive events from the default dispatch interface, but not
|
|
89
|
+
# events from `IPropertyNotifySink`.
|
|
90
|
+
self.assertIn("onreadystatechange", sink._events)
|
|
91
|
+
self.assertNotIn("OnChanged", sink._events)
|
|
92
|
+
|
|
93
|
+
del conn
|
|
94
|
+
|
|
95
|
+
def test_nondefault_eventinterface(self):
|
|
96
|
+
# Verify that `GetEvents` can connect to a non-default interface
|
|
97
|
+
# (like `IPropertyNotifySink`) when it is explicitly provided.
|
|
98
|
+
sink = EventSink()
|
|
99
|
+
|
|
100
|
+
conn = GetEvents(self.doc, sink, interface=IPropertyNotifySink)
|
|
101
|
+
|
|
102
|
+
self.doc.loadXML("<root/>")
|
|
103
|
+
|
|
104
|
+
# Give the message loop time to process incoming events.
|
|
105
|
+
for _ in range(50):
|
|
106
|
+
PumpWaitingMessages()
|
|
107
|
+
time.sleep(0.1)
|
|
108
|
+
# Should receive events from `IPropertyNotifySink`, but not events from
|
|
109
|
+
# the default dispatch interface.
|
|
110
|
+
self.assertNotIn("onreadystatechange", sink._events)
|
|
111
|
+
self.assertIn("OnChanged", sink._events)
|
|
112
|
+
|
|
113
|
+
del conn
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
class Test_MSHTML(ut.TestCase):
|
|
117
|
+
def test_retrieved_outgoing_iid_is_guid_null(self):
|
|
118
|
+
doc = CreateObject("htmlfile")
|
|
119
|
+
sink = object()
|
|
120
|
+
# MSHTML's HTMLDocument (which is what `CreateObject('htmlfile')`
|
|
121
|
+
# returns) does not expose a valid default source interface through
|
|
122
|
+
# `IProvideClassInfo2`.
|
|
123
|
+
with self.assertRaises(NotImplementedError):
|
|
124
|
+
GetEvents(doc, sink)
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
class Test_IMAPI2FS(ut.TestCase):
|
|
128
|
+
def setUp(self):
|
|
129
|
+
CLSID_MsftFileSystemImage = GUID("{2C941FC5-975B-59BE-A960-9A2A262853A5}")
|
|
130
|
+
self.image = CreateObject(CLSID_MsftFileSystemImage)
|
|
131
|
+
self.image.FileSystemsToCreate = 1 # FsiFileSystemISO9660
|
|
132
|
+
td = tempfile.TemporaryDirectory()
|
|
133
|
+
self.tmp_dir = Path(td.name)
|
|
134
|
+
self.addCleanup(td.cleanup)
|
|
135
|
+
|
|
136
|
+
def tearDown(self):
|
|
137
|
+
del self.image
|
|
138
|
+
# Force garbage collection and wait slightly to ensure COM resources
|
|
139
|
+
# are released properly between tests.
|
|
140
|
+
gc.collect()
|
|
141
|
+
time.sleep(2)
|
|
142
|
+
|
|
143
|
+
def test_event_methods_lack_dispids(self):
|
|
144
|
+
sink = object()
|
|
145
|
+
# The default event interface for IMAPI2's FileSystemImage is
|
|
146
|
+
# `DFileSystemImageEvents`. Although it inherits from `IDispatch`,
|
|
147
|
+
# it is a custom interface (`TKIND_INTERFACE`), not a dual or pure
|
|
148
|
+
# dispatch interface (`TKIND_DISPATCH`); therefore, its methods
|
|
149
|
+
# do not have DISPIDs.
|
|
150
|
+
with self.assertRaises(NotImplementedError):
|
|
151
|
+
GetEvents(self.image, sink)
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
if __name__ == "__main__":
|
|
155
|
+
ut.main()
|
|
@@ -7,7 +7,7 @@ import unittest as ut
|
|
|
7
7
|
from _ctypes import COMError
|
|
8
8
|
from collections.abc import Iterator
|
|
9
9
|
from ctypes import HRESULT, POINTER, OleDLL, WinDLL, byref
|
|
10
|
-
from ctypes.wintypes import BOOL, DWORD, HANDLE,
|
|
10
|
+
from ctypes.wintypes import BOOL, DWORD, HANDLE, MSG
|
|
11
11
|
from pathlib import Path
|
|
12
12
|
from queue import Queue
|
|
13
13
|
|
|
@@ -18,16 +18,16 @@ from comtypes.git import (
|
|
|
18
18
|
RegisterInterfaceInGlobal,
|
|
19
19
|
RevokeInterfaceFromGlobal,
|
|
20
20
|
)
|
|
21
|
-
from comtypes.messageloop import
|
|
21
|
+
from comtypes.messageloop import (
|
|
22
|
+
PM_REMOVE,
|
|
23
|
+
DispatchMessage,
|
|
24
|
+
PeekMessage,
|
|
25
|
+
TranslateMessage,
|
|
26
|
+
)
|
|
22
27
|
from comtypes.persist import STGM_READ, IPersistFile
|
|
23
28
|
|
|
24
29
|
_user32 = WinDLL("user32")
|
|
25
30
|
|
|
26
|
-
# https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-peekmessagea
|
|
27
|
-
PeekMessage = _user32.PeekMessageA
|
|
28
|
-
PeekMessage.argtypes = [POINTER(MSG), HWND, UINT, UINT, UINT]
|
|
29
|
-
PeekMessage.restype = BOOL
|
|
30
|
-
|
|
31
31
|
# https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-msgwaitformultipleobjects
|
|
32
32
|
MsgWaitForMultipleObjects = _user32.MsgWaitForMultipleObjects
|
|
33
33
|
MsgWaitForMultipleObjects.restype = DWORD
|
|
@@ -49,8 +49,6 @@ _CoGetApartmentType.restype = HRESULT
|
|
|
49
49
|
|
|
50
50
|
QS_ALLINPUT = 0x04FF # All message types including SendMessage
|
|
51
51
|
|
|
52
|
-
PM_REMOVE = 0x0001 # Remove message from queue after Peek
|
|
53
|
-
|
|
54
52
|
APTTYPE_MAINSTA = 3
|
|
55
53
|
|
|
56
54
|
RPC_E_WRONG_THREAD = -2147417842 # 0x8001010E
|