comtypes 1.4.7__zip → 1.4.9__zip
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {comtypes-1.4.7 → comtypes-1.4.9}/CHANGES.txt +39 -0
- {comtypes-1.4.7/comtypes.egg-info → comtypes-1.4.9}/PKG-INFO +6 -4
- {comtypes-1.4.7 → comtypes-1.4.9}/README.md +5 -3
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/GUID.py +6 -5
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/__init__.py +16 -5
- comtypes-1.4.9/comtypes/_comobject.py +507 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/_memberspec.py +81 -9
- comtypes-1.4.9/comtypes/_meta.py +95 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/_npsupport.py +2 -1
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/_post_coinit/__init__.py +1 -0
- comtypes-1.4.9/comtypes/_post_coinit/_cominterface_meta_patcher.py +153 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/_post_coinit/misc.py +21 -40
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/_post_coinit/unknwn.py +88 -209
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/_safearray.py +1 -2
- comtypes-1.4.9/comtypes/_vtbl.py +448 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/automation.py +36 -45
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/client/__init__.py +21 -31
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/client/_code_cache.py +5 -4
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/client/_constants.py +1 -1
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/client/_events.py +1 -2
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/client/_generate.py +9 -13
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/client/lazybind.py +2 -7
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/errorinfo.py +3 -3
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/git.py +2 -2
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/hints.pyi +11 -19
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/persist.py +7 -7
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/safearray.py +12 -6
- comtypes-1.4.9/comtypes/server/__init__.py +86 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/server/inprocserver.py +22 -17
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/server/localserver.py +28 -16
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/server/register.py +62 -73
- comtypes-1.4.9/comtypes/server/w_getopt.py +48 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/shelllink.py +49 -67
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/TestComServer.py +1 -1
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/TestDispServer.py +1 -1
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/__init__.py +9 -12
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/find_memleak.py +0 -1
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_BSTR.py +4 -7
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_agilent.py +0 -1
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_avmc.py +1 -1
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_casesensitivity.py +3 -5
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_clear_cache.py +1 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_collections.py +3 -3
- comtypes-1.4.9/comtypes/test/test_comobject.py +146 -0
- comtypes-1.4.9/comtypes/test/test_comserver.py +319 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_createwrappers.py +2 -6
- comtypes-1.4.9/comtypes/test/test_dispinterface.py +153 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_excel.py +22 -13
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_ie.py +2 -5
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_inout_args.py +8 -5
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_midl_safearray_create.py +9 -1
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_outparam.py +17 -10
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_safearray.py +1 -90
- comtypes-1.4.9/comtypes/test/test_server.py +350 -0
- comtypes-1.4.9/comtypes/test/test_server_register.py +536 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_shelllink.py +10 -14
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_showevents.py +7 -17
- comtypes-1.4.9/comtypes/test/test_stream.py +131 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_typeannotator.py +1 -1
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_urlhistory.py +1 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_variant.py +0 -19
- comtypes-1.4.9/comtypes/test/test_w_getopt.py +29 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_win32com_interop.py +80 -36
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_wmi.py +0 -3
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/tools/codegenerator/codegenerator.py +62 -68
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/tools/codegenerator/helpers.py +8 -8
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/tools/codegenerator/namespaces.py +97 -27
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/tools/codegenerator/packing.py +4 -4
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/tools/codegenerator/typeannotator.py +9 -11
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/tools/tlbparser.py +33 -32
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/tools/typedesc.py +3 -8
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/typeinfo.py +32 -47
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/util.py +1 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/viewobject.py +1 -5
- {comtypes-1.4.7 → comtypes-1.4.9/comtypes.egg-info}/PKG-INFO +6 -4
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes.egg-info/SOURCES.txt +6 -3
- comtypes-1.4.9/pyproject.toml +55 -0
- comtypes-1.4.7/comtypes/_comobject.py +0 -834
- comtypes-1.4.7/comtypes/_idl_stuff.py +0 -67
- comtypes-1.4.7/comtypes/_meta.py +0 -70
- comtypes-1.4.7/comtypes/server/__init__.py +0 -69
- comtypes-1.4.7/comtypes/server/w_getopt.py +0 -75
- comtypes-1.4.7/comtypes/test/test_comserver.py +0 -239
- comtypes-1.4.7/comtypes/test/test_dispinterface.py +0 -138
- comtypes-1.4.7/comtypes/test/test_propputref.py +0 -40
- comtypes-1.4.7/comtypes/test/test_server.py +0 -348
- comtypes-1.4.7/comtypes/test/test_stream.py +0 -53
- comtypes-1.4.7/pyproject.toml +0 -3
- {comtypes-1.4.7 → comtypes-1.4.9}/LICENSE.txt +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/MANIFEST.in +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/_post_coinit/bstr.py +0 -0
- /comtypes-1.4.7/comtypes/_py_instance_method.py → /comtypes-1.4.9/comtypes/_post_coinit/instancemethod.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/_tlib_version_checker.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/clear_cache.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/client/dynamic.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/connectionpoints.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/hresult.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/logutil.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/messageloop.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/patcher.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/server/automation.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/server/connectionpoints.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/stream.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/TestComServer.idl +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/TestComServer.tlb +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/TestDispServer.idl +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/TestDispServer.tlb +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/mylib.idl +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/mylib.tlb +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/mytypelib.idl +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/runtests.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/setup.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_DISPPARAMS.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_GUID.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_QueryService.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_basic.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_client.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_client_dynamic.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_client_regenerate_modules.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_dict.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_dispifc_records.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_dispifc_safearrays.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_dyndispatch.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_findgendir.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_getactiveobj.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_ienum.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_imfattributes.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_jscript.js +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_monikers.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_msscript.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_npsupport.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_persist.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_pump_events.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_recordinfo.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_sapi.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_storage.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_subinterface.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_typeinfo.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_word.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/urlhist.tlb +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/tools/__init__.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/tools/codegenerator/__init__.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/tools/codegenerator/modulenamer.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/tools/typedesc_base.py +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes.egg-info/dependency_links.txt +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes.egg-info/entry_points.txt +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/comtypes.egg-info/top_level.txt +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/setup.cfg +0 -0
- {comtypes-1.4.7 → comtypes-1.4.9}/setup.py +0 -0
|
@@ -1,23 +1,17 @@
|
|
|
1
1
|
# https://learn.microsoft.com/en-us/windows/win32/api/unknwn/
|
|
2
2
|
|
|
3
|
-
from ctypes import byref, c_ulong, c_void_p, HRESULT, POINTER
|
|
4
|
-
from _ctypes import COMError
|
|
5
|
-
|
|
6
3
|
import logging
|
|
7
4
|
import sys
|
|
8
|
-
import
|
|
9
|
-
from typing import ClassVar,
|
|
10
|
-
from typing import Optional
|
|
11
|
-
from typing import List, Type
|
|
12
|
-
|
|
13
|
-
from comtypes import GUID, patcher, _ole32_nohresult, com_interface_registry
|
|
14
|
-
from comtypes._idl_stuff import STDMETHOD
|
|
15
|
-
from comtypes._memberspec import ComMemberGenerator, DispMemberGenerator
|
|
16
|
-
from comtypes._memberspec import _ComMemberSpec, _DispMemberSpec
|
|
17
|
-
from comtypes._py_instance_method import instancemethod
|
|
5
|
+
from ctypes import HRESULT, POINTER, byref, c_ulong, c_void_p
|
|
6
|
+
from typing import TYPE_CHECKING, ClassVar, List, Optional, Type, TypeVar
|
|
18
7
|
|
|
8
|
+
from comtypes import GUID, _ole32_nohresult, com_interface_registry
|
|
9
|
+
from comtypes._memberspec import STDMETHOD, ComMemberGenerator, DispMemberGenerator
|
|
10
|
+
from comtypes._post_coinit import _cominterface_meta_patcher as _meta_patch
|
|
11
|
+
from comtypes._post_coinit.instancemethod import instancemethod
|
|
19
12
|
|
|
20
|
-
|
|
13
|
+
if TYPE_CHECKING:
|
|
14
|
+
from comtypes._memberspec import _ComMemberSpec, _DispMemberSpec
|
|
21
15
|
|
|
22
16
|
logger = logging.getLogger(__name__)
|
|
23
17
|
|
|
@@ -58,8 +52,8 @@ class _cominterface_meta(type):
|
|
|
58
52
|
|
|
59
53
|
_case_insensitive_: bool
|
|
60
54
|
_iid_: GUID
|
|
61
|
-
_methods_: List[_ComMemberSpec]
|
|
62
|
-
_disp_methods_: List[_DispMemberSpec]
|
|
55
|
+
_methods_: List["_ComMemberSpec"]
|
|
56
|
+
_disp_methods_: List["_DispMemberSpec"]
|
|
63
57
|
|
|
64
58
|
# This flag is set to True by the atexit handler which calls
|
|
65
59
|
# CoUninitialize.
|
|
@@ -69,12 +63,37 @@ class _cominterface_meta(type):
|
|
|
69
63
|
def __new__(cls, name, bases, namespace):
|
|
70
64
|
methods = namespace.pop("_methods_", None)
|
|
71
65
|
dispmethods = namespace.pop("_disp_methods_", None)
|
|
72
|
-
|
|
66
|
+
self = type.__new__(cls, name, bases, namespace)
|
|
73
67
|
|
|
74
68
|
if methods is not None:
|
|
75
|
-
|
|
69
|
+
self._methods_ = methods
|
|
76
70
|
if dispmethods is not None:
|
|
77
|
-
|
|
71
|
+
self._disp_methods_ = dispmethods
|
|
72
|
+
|
|
73
|
+
# ` _compointer_meta` is a subclass inherited from `_cominterface_meta`.
|
|
74
|
+
# `_compointer_base` uses `_compointer_meta` as its metaclass.
|
|
75
|
+
# In other words, when the `__new__` method of this metaclass is called,
|
|
76
|
+
# `_compointer_base` type or an subclass of it might be created and assigned
|
|
77
|
+
# to `self`.
|
|
78
|
+
if bases == (c_void_p,):
|
|
79
|
+
# `self` is the `_compointer_base` type.
|
|
80
|
+
# On some versions of Python, `_compointer_base` is not yet available in
|
|
81
|
+
# the accessible namespace at this point in its initialization, and
|
|
82
|
+
# referencing it could raise a `NameError`.
|
|
83
|
+
# This metaclass is intended to be used only as a base class for defining
|
|
84
|
+
# the `_compointer_meta` or as the metaclass for the `IUnknown`, so the
|
|
85
|
+
# situation where the `bases` parameter is `(c_void_p,)` is limited to when
|
|
86
|
+
# the `_compointer_meta` is specified as the metaclass of the
|
|
87
|
+
# `_compointer_base`.
|
|
88
|
+
# Prevent specifying the metaclass type instance in the `bases` parameter
|
|
89
|
+
# when instantiating it, as this would lead to infinite recursion.
|
|
90
|
+
return self
|
|
91
|
+
if issubclass(self, _compointer_base):
|
|
92
|
+
# `self` is a `POINTER(interface)` type.
|
|
93
|
+
# Prevent creating/registering a pointer to a pointer (to a pointer...),
|
|
94
|
+
# which would lead to infinite recursion.
|
|
95
|
+
# Depending on a version or revision of Python, this may be essential.
|
|
96
|
+
return self
|
|
78
97
|
|
|
79
98
|
# If we sublass a COM interface, for example:
|
|
80
99
|
#
|
|
@@ -85,77 +104,36 @@ class _cominterface_meta(type):
|
|
|
85
104
|
# subclass of POINTER(IUnknown) because of the way ctypes
|
|
86
105
|
# typechecks work.
|
|
87
106
|
if bases == (object,):
|
|
88
|
-
|
|
107
|
+
# `self` is the `IUnknown` type.
|
|
108
|
+
_ptr_bases = (self, _compointer_base)
|
|
89
109
|
else:
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
110
|
+
# `self` is an interface type derived from `IUnknown`.
|
|
111
|
+
_ptr_bases = (self, POINTER(bases[0]))
|
|
112
|
+
|
|
113
|
+
# The interface 'self' is used as a mixin.
|
|
114
|
+
# HACK: Could `type(_compointer_base)` be replaced with `_compointer_meta`?
|
|
115
|
+
# `type(klass)` returns its metaclass.
|
|
116
|
+
# Since this specification, `type(_compointer_base)` will return the
|
|
117
|
+
# `_compointer_meta` type as per the class definition.
|
|
118
|
+
# The reason for this implementation might be a remnant of the differences in
|
|
119
|
+
# how metaclasses work between Python 3.x and Python 2.x.
|
|
120
|
+
# If there are no problems with the versions of Python that `comtypes`
|
|
121
|
+
# supports, this replacement could make the process flow easier to understand.
|
|
93
122
|
p = type(_compointer_base)(
|
|
94
|
-
"POINTER(
|
|
123
|
+
f"POINTER({self.__name__})",
|
|
95
124
|
_ptr_bases,
|
|
96
|
-
{"__com_interface__":
|
|
125
|
+
{"__com_interface__": self, "_needs_com_addref_": None},
|
|
97
126
|
)
|
|
98
127
|
|
|
99
|
-
from ctypes import _pointer_type_cache
|
|
100
|
-
|
|
101
|
-
_pointer_type_cache[
|
|
102
|
-
|
|
103
|
-
if
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
def __getattr__(self, name):
|
|
109
|
-
"""Implement case insensitive access to methods and properties"""
|
|
110
|
-
try:
|
|
111
|
-
fixed_name = self.__map_case__[name.lower()]
|
|
112
|
-
except KeyError:
|
|
113
|
-
raise AttributeError(name)
|
|
114
|
-
if fixed_name != name: # prevent unbounded recursion
|
|
115
|
-
return getattr(self, fixed_name)
|
|
116
|
-
raise AttributeError(name)
|
|
117
|
-
|
|
118
|
-
# __setattr__ is pretty heavy-weight, because it is called for
|
|
119
|
-
# EVERY attribute assignment. Settings a non-com attribute
|
|
120
|
-
# through this function takes 8.6 usec, while without this
|
|
121
|
-
# function it takes 0.7 sec - 12 times slower.
|
|
122
|
-
#
|
|
123
|
-
# How much faster would this be if implemented in C?
|
|
124
|
-
def __setattr__(self, name, value):
|
|
125
|
-
"""Implement case insensitive access to methods and properties"""
|
|
126
|
-
object.__setattr__(
|
|
127
|
-
self, self.__map_case__.get(name.lower(), name), value
|
|
128
|
-
)
|
|
129
|
-
|
|
130
|
-
@patcher.Patch(POINTER(p))
|
|
131
|
-
class ReferenceFix(object):
|
|
132
|
-
def __setitem__(self, index, value):
|
|
133
|
-
# We override the __setitem__ method of the
|
|
134
|
-
# POINTER(POINTER(interface)) type, so that the COM
|
|
135
|
-
# reference count is managed correctly.
|
|
136
|
-
#
|
|
137
|
-
# This is so that we can implement COM methods that have to
|
|
138
|
-
# return COM pointers more easily and consistent. Instead of
|
|
139
|
-
# using CopyComPointer in the method implementation, we can
|
|
140
|
-
# simply do:
|
|
141
|
-
#
|
|
142
|
-
# def GetTypeInfo(self, this, ..., pptinfo):
|
|
143
|
-
# if not pptinfo: return E_POINTER
|
|
144
|
-
# pptinfo[0] = a_com_interface_pointer
|
|
145
|
-
# return S_OK
|
|
146
|
-
if index != 0:
|
|
147
|
-
# CopyComPointer, which is in _ctypes, does only
|
|
148
|
-
# handle an index of 0. This code does what
|
|
149
|
-
# CopyComPointer should do if index != 0.
|
|
150
|
-
if bool(value):
|
|
151
|
-
value.AddRef()
|
|
152
|
-
super(POINTER(p), self).__setitem__(index, value)
|
|
153
|
-
return
|
|
154
|
-
from _ctypes import CopyComPointer
|
|
155
|
-
|
|
156
|
-
CopyComPointer(value, self)
|
|
157
|
-
|
|
158
|
-
return new_cls
|
|
128
|
+
from ctypes import _pointer_type_cache # type: ignore
|
|
129
|
+
|
|
130
|
+
_pointer_type_cache[self] = p
|
|
131
|
+
|
|
132
|
+
if self._case_insensitive_:
|
|
133
|
+
_meta_patch.case_insensitive(p)
|
|
134
|
+
_meta_patch.reference_fix(POINTER(p)) # type: ignore
|
|
135
|
+
|
|
136
|
+
return self
|
|
159
137
|
|
|
160
138
|
def __setattr__(self, name, value):
|
|
161
139
|
if name == "_methods_":
|
|
@@ -184,94 +162,11 @@ class _cominterface_meta(type):
|
|
|
184
162
|
|
|
185
163
|
# XXX These special methods should be generated by the code generator.
|
|
186
164
|
if has_name("Count"):
|
|
187
|
-
|
|
188
|
-
@patcher.Patch(self)
|
|
189
|
-
class _(object):
|
|
190
|
-
def __len__(self):
|
|
191
|
-
"Return the the 'self.Count' property."
|
|
192
|
-
return self.Count
|
|
193
|
-
|
|
165
|
+
_meta_patch.sized(self)
|
|
194
166
|
if has_name("Item"):
|
|
195
|
-
|
|
196
|
-
@patcher.Patch(self)
|
|
197
|
-
class _(object):
|
|
198
|
-
# 'Item' is the 'default' value. Make it available by
|
|
199
|
-
# calling the instance (Not sure this makes sense, but
|
|
200
|
-
# win32com does this also).
|
|
201
|
-
def __call__(self, *args, **kw):
|
|
202
|
-
"Return 'self.Item(*args, **kw)'"
|
|
203
|
-
return self.Item(*args, **kw)
|
|
204
|
-
|
|
205
|
-
# does this make sense? It seems that all standard typelibs I've
|
|
206
|
-
# seen so far that support .Item also support ._NewEnum
|
|
207
|
-
@patcher.no_replace
|
|
208
|
-
def __getitem__(self, index):
|
|
209
|
-
"Return 'self.Item(index)'"
|
|
210
|
-
# Handle tuples and all-slice
|
|
211
|
-
if isinstance(index, tuple):
|
|
212
|
-
args = index
|
|
213
|
-
elif index == _all_slice:
|
|
214
|
-
args = ()
|
|
215
|
-
else:
|
|
216
|
-
args = (index,)
|
|
217
|
-
|
|
218
|
-
try:
|
|
219
|
-
result = self.Item(*args)
|
|
220
|
-
except COMError as err:
|
|
221
|
-
(hresult, text, details) = err.args
|
|
222
|
-
if hresult == -2147352565: # DISP_E_BADINDEX
|
|
223
|
-
raise IndexError("invalid index")
|
|
224
|
-
else:
|
|
225
|
-
raise
|
|
226
|
-
|
|
227
|
-
# Note that result may be NULL COM pointer. There is no way
|
|
228
|
-
# to interpret this properly, so it is returned as-is.
|
|
229
|
-
|
|
230
|
-
# Hm, should we call __ctypes_from_outparam__ on the
|
|
231
|
-
# result?
|
|
232
|
-
return result
|
|
233
|
-
|
|
234
|
-
@patcher.no_replace
|
|
235
|
-
def __setitem__(self, index, value):
|
|
236
|
-
"Attempt 'self.Item[index] = value'"
|
|
237
|
-
try:
|
|
238
|
-
self.Item[index] = value
|
|
239
|
-
except COMError as err:
|
|
240
|
-
(hresult, text, details) = err.args
|
|
241
|
-
if hresult == -2147352565: # DISP_E_BADINDEX
|
|
242
|
-
raise IndexError("invalid index")
|
|
243
|
-
else:
|
|
244
|
-
raise
|
|
245
|
-
except TypeError:
|
|
246
|
-
msg = "%r object does not support item assignment"
|
|
247
|
-
raise TypeError(msg % type(self))
|
|
248
|
-
|
|
167
|
+
_meta_patch.callable_and_subscriptable(self)
|
|
249
168
|
if has_name("_NewEnum"):
|
|
250
|
-
|
|
251
|
-
@patcher.Patch(self)
|
|
252
|
-
class _(object):
|
|
253
|
-
def __iter__(self):
|
|
254
|
-
"Return an iterator over the _NewEnum collection."
|
|
255
|
-
# This method returns a pointer to _some_ _NewEnum interface.
|
|
256
|
-
# It relies on the fact that the code generator creates next()
|
|
257
|
-
# methods for them automatically.
|
|
258
|
-
#
|
|
259
|
-
# Better would maybe to return an object that
|
|
260
|
-
# implements the Python iterator protocol, and
|
|
261
|
-
# forwards the calls to the COM interface.
|
|
262
|
-
enum = self._NewEnum
|
|
263
|
-
if isinstance(enum, types.MethodType):
|
|
264
|
-
# _NewEnum should be a propget property, with dispid -4.
|
|
265
|
-
#
|
|
266
|
-
# Sometimes, however, it is a method.
|
|
267
|
-
enum = enum()
|
|
268
|
-
if hasattr(enum, "Next"):
|
|
269
|
-
return enum
|
|
270
|
-
# _NewEnum returns an IUnknown pointer, QueryInterface() it to
|
|
271
|
-
# IEnumVARIANT
|
|
272
|
-
from comtypes.automation import IEnumVARIANT
|
|
273
|
-
|
|
274
|
-
return enum.QueryInterface(IEnumVARIANT)
|
|
169
|
+
_meta_patch.iterator(self)
|
|
275
170
|
|
|
276
171
|
def _make_case_insensitive(self):
|
|
277
172
|
# The __map_case__ dictionary maps lower case names to the
|
|
@@ -284,7 +179,7 @@ class _cominterface_meta(type):
|
|
|
284
179
|
d.update(getattr(self, "__map_case__", {}))
|
|
285
180
|
self.__map_case__ = d
|
|
286
181
|
|
|
287
|
-
def _make_dispmethods(self, methods: List[_DispMemberSpec]) -> None:
|
|
182
|
+
def _make_dispmethods(self, methods: List["_DispMemberSpec"]) -> None:
|
|
288
183
|
if self._case_insensitive_:
|
|
289
184
|
self._make_case_insensitive()
|
|
290
185
|
# create dispinterface methods and properties on the interface 'self'
|
|
@@ -308,18 +203,15 @@ class _cominterface_meta(type):
|
|
|
308
203
|
|
|
309
204
|
def __get_baseinterface_methodcount(self):
|
|
310
205
|
"Return the number of com methods in the base interfaces"
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
result += len(itf
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
raise
|
|
321
|
-
|
|
322
|
-
def _make_methods(self, methods: List[_ComMemberSpec]) -> None:
|
|
206
|
+
result = 0
|
|
207
|
+
for itf in self.mro()[1:-1]:
|
|
208
|
+
if "_methods_" in vars(itf):
|
|
209
|
+
result += len(vars(itf)["_methods_"])
|
|
210
|
+
else:
|
|
211
|
+
raise TypeError(f"baseinterface '{itf.__name__}' has no _methods_")
|
|
212
|
+
return result
|
|
213
|
+
|
|
214
|
+
def _make_methods(self, methods: List["_ComMemberSpec"]) -> None:
|
|
323
215
|
if self._case_insensitive_:
|
|
324
216
|
self._make_case_insensitive()
|
|
325
217
|
# register com interface. we insist on an _iid_ in THIS class!
|
|
@@ -337,12 +229,12 @@ class _cominterface_meta(type):
|
|
|
337
229
|
member_gen.add(m)
|
|
338
230
|
for name, func, raw_func, is_prop in member_gen.methods():
|
|
339
231
|
raw_mth = instancemethod(raw_func, None, self)
|
|
340
|
-
setattr(self, "_
|
|
232
|
+
setattr(self, f"_{self.__name__}__com_{name}", raw_mth)
|
|
341
233
|
mth = instancemethod(func, None, self)
|
|
342
234
|
if not is_prop:
|
|
343
235
|
# We install the method in the class, except when it's a property.
|
|
344
236
|
# And we make sure we don't overwrite a property that's already present.
|
|
345
|
-
mthname = name if not hasattr(self, name) else
|
|
237
|
+
mthname = name if not hasattr(self, name) else f"_{name}"
|
|
346
238
|
setattr(self, mthname, mth)
|
|
347
239
|
# For a method, this is the real name.
|
|
348
240
|
# For a property, this is the name WITHOUT the _set_ or _get_ prefix.
|
|
@@ -353,7 +245,7 @@ class _cominterface_meta(type):
|
|
|
353
245
|
# create public properties / attribute accessors
|
|
354
246
|
for name, accessor in member_gen.properties():
|
|
355
247
|
# Again, we should not overwrite class attributes that are already present.
|
|
356
|
-
propname = name if not hasattr(self, name) else
|
|
248
|
+
propname = name if not hasattr(self, name) else f"_{name}"
|
|
357
249
|
setattr(self, propname, accessor)
|
|
358
250
|
# COM is case insensitive
|
|
359
251
|
if self._case_insensitive_:
|
|
@@ -363,9 +255,11 @@ class _cominterface_meta(type):
|
|
|
363
255
|
################################################################
|
|
364
256
|
|
|
365
257
|
|
|
258
|
+
# will not work if we change the order of the two base classes!
|
|
366
259
|
class _compointer_meta(type(c_void_p), _cominterface_meta):
|
|
367
|
-
"metaclass for COM interface pointer classes"
|
|
368
|
-
|
|
260
|
+
"""metaclass for COM interface pointer classes"""
|
|
261
|
+
|
|
262
|
+
pass # no functionality, but needed to avoid a metaclass conflict
|
|
369
263
|
|
|
370
264
|
|
|
371
265
|
class _compointer_base(c_void_p, metaclass=_compointer_meta):
|
|
@@ -383,22 +277,7 @@ class _compointer_base(c_void_p, metaclass=_compointer_meta):
|
|
|
383
277
|
#
|
|
384
278
|
if not type(self)._com_shutting_down:
|
|
385
279
|
_debug("Release %s", self)
|
|
386
|
-
self.Release()
|
|
387
|
-
|
|
388
|
-
def __cmp__(self, other):
|
|
389
|
-
"""Compare pointers to COM interfaces."""
|
|
390
|
-
# COM identity rule
|
|
391
|
-
#
|
|
392
|
-
# XXX To compare COM interface pointers, should we
|
|
393
|
-
# automatically QueryInterface for IUnknown on both items, and
|
|
394
|
-
# compare the pointer values?
|
|
395
|
-
if not isinstance(other, _compointer_base):
|
|
396
|
-
return 1
|
|
397
|
-
|
|
398
|
-
# get the value property of the c_void_p baseclass, this is the pointer value
|
|
399
|
-
return cmp(
|
|
400
|
-
super(_compointer_base, self).value, super(_compointer_base, other).value
|
|
401
|
-
)
|
|
280
|
+
self.Release() # type: ignore
|
|
402
281
|
|
|
403
282
|
def __eq__(self, other):
|
|
404
283
|
if not isinstance(other, _compointer_base):
|
|
@@ -421,7 +300,7 @@ class _compointer_base(c_void_p, metaclass=_compointer_meta):
|
|
|
421
300
|
|
|
422
301
|
def __repr__(self):
|
|
423
302
|
ptr = super(_compointer_base, self).value
|
|
424
|
-
return "
|
|
303
|
+
return f"<{self.__class__.__name__} ptr=0x{ptr or 0:x} at {id(self):x}>"
|
|
425
304
|
|
|
426
305
|
# This fixes the problem when there are multiple python interface types
|
|
427
306
|
# wrapping the same COM interface. This could happen because some interfaces
|
|
@@ -457,8 +336,8 @@ class _compointer_base(c_void_p, metaclass=_compointer_meta):
|
|
|
457
336
|
# a kind of QueryInterface
|
|
458
337
|
return table[cls._iid_]
|
|
459
338
|
except KeyError:
|
|
460
|
-
raise TypeError("Interface
|
|
461
|
-
return value.QueryInterface(cls.__com_interface__)
|
|
339
|
+
raise TypeError(f"Interface {cls._iid_} not supported")
|
|
340
|
+
return value.QueryInterface(cls.__com_interface__) # type: ignore
|
|
462
341
|
|
|
463
342
|
|
|
464
343
|
################################################################
|
|
@@ -499,7 +378,7 @@ class IUnknown(_IUnknown_Base, metaclass=_cominterface_meta):
|
|
|
499
378
|
|
|
500
379
|
_case_insensitive_: ClassVar[bool] = False
|
|
501
380
|
_iid_: ClassVar[GUID] = GUID("{00000000-0000-0000-C000-000000000046}")
|
|
502
|
-
_methods_: ClassVar[List[_ComMemberSpec]] = [
|
|
381
|
+
_methods_: ClassVar[List["_ComMemberSpec"]] = [
|
|
503
382
|
STDMETHOD(HRESULT, "QueryInterface", [POINTER(GUID), POINTER(c_void_p)]),
|
|
504
383
|
STDMETHOD(c_ulong, "AddRef"),
|
|
505
384
|
STDMETHOD(c_ulong, "Release"),
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"""SAFEARRAY api functions, data types, and constants."""
|
|
2
2
|
|
|
3
3
|
from ctypes import c_uint, c_ushort, c_void_p, POINTER, Structure, WinDLL
|
|
4
|
-
from ctypes.wintypes import DWORD, LONG, UINT
|
|
4
|
+
from ctypes.wintypes import DWORD, LONG, UINT, USHORT
|
|
5
5
|
|
|
6
6
|
from comtypes import HRESULT, GUID
|
|
7
7
|
|
|
@@ -19,7 +19,6 @@ from comtypes import HRESULT, GUID
|
|
|
19
19
|
|
|
20
20
|
VARTYPE = c_ushort
|
|
21
21
|
PVOID = c_void_p
|
|
22
|
-
USHORT = c_ushort
|
|
23
22
|
|
|
24
23
|
_oleaut32 = WinDLL("oleaut32")
|
|
25
24
|
|