comtypes 1.3.0__zip → 1.4.0__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.3.0 → comtypes-1.4.0}/CHANGES.txt +12 -0
- {comtypes-1.3.0/comtypes.egg-info → comtypes-1.4.0}/PKG-INFO +5 -29
- {comtypes-1.3.0 → comtypes-1.4.0}/README.md +4 -28
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/__init__.py +1 -1
- comtypes-1.4.0/comtypes/hints.pyi +244 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/test/test_client.py +9 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/test/test_excel.py +10 -3
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/tools/codegenerator.py +116 -31
- comtypes-1.4.0/comtypes/tools/typeannotator.py +319 -0
- {comtypes-1.3.0 → comtypes-1.4.0/comtypes.egg-info}/PKG-INFO +5 -29
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes.egg-info/SOURCES.txt +1 -0
- comtypes-1.3.0/comtypes/hints.pyi +0 -4
- {comtypes-1.3.0 → comtypes-1.4.0}/LICENSE.txt +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/MANIFEST.in +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/GUID.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/_comobject.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/_memberspec.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/_meta.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/_npsupport.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/_safearray.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/automation.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/clear_cache.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/client/__init__.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/client/_code_cache.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/client/_constants.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/client/_events.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/client/_generate.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/client/dynamic.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/client/lazybind.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/connectionpoints.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/errorinfo.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/git.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/hresult.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/logutil.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/messageloop.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/patcher.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/persist.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/safearray.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/server/__init__.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/server/automation.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/server/connectionpoints.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/server/inprocserver.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/server/localserver.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/server/register.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/server/w_getopt.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/shelllink.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/test/TestComServer.idl +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/test/TestComServer.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/test/TestComServer.tlb +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/test/TestDispServer.idl +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/test/TestDispServer.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/test/TestDispServer.tlb +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/test/__init__.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/test/find_memleak.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/test/mylib.idl +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/test/mytypelib.idl +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/test/runtests.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/test/setup.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/test/test_BSTR.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/test/test_DISPPARAMS.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/test/test_GUID.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/test/test_QueryService.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/test/test_agilent.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/test/test_avmc.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/test/test_basic.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/test/test_casesensitivity.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/test/test_clear_cache.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/test/test_client_dynamic.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/test/test_collections.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/test/test_comserver.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/test/test_createwrappers.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/test/test_dict.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/test/test_dispinterface.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/test/test_dyndispatch.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/test/test_findgendir.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/test/test_getactiveobj.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/test/test_ie.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/test/test_ienum.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/test/test_imfattributes.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/test/test_inout_args.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/test/test_jscript.js +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/test/test_msscript.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/test/test_npsupport.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/test/test_outparam.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/test/test_propputref.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/test/test_pump_events.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/test/test_safearray.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/test/test_sapi.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/test/test_server.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/test/test_showevents.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/test/test_subinterface.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/test/test_typeinfo.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/test/test_urlhistory.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/test/test_variant.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/test/test_win32com_interop.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/test/test_wmi.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/test/test_word.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/tools/__init__.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/tools/tlbparser.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/tools/typedesc.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/tools/typedesc_base.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/typeinfo.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/util.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes/viewobject.py +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes.egg-info/dependency_links.txt +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes.egg-info/entry_points.txt +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/comtypes.egg-info/top_level.txt +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/setup.cfg +0 -0
- {comtypes-1.3.0 → comtypes-1.4.0}/setup.py +0 -0
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
import abc
|
|
2
|
+
import io
|
|
3
|
+
import keyword
|
|
4
|
+
from typing import (
|
|
5
|
+
Any,
|
|
6
|
+
Dict,
|
|
7
|
+
Generic,
|
|
8
|
+
Iterable,
|
|
9
|
+
Iterator,
|
|
10
|
+
List,
|
|
11
|
+
Optional,
|
|
12
|
+
Sequence,
|
|
13
|
+
Tuple,
|
|
14
|
+
TYPE_CHECKING,
|
|
15
|
+
TypeVar,
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
from comtypes.tools import typedesc
|
|
19
|
+
|
|
20
|
+
if TYPE_CHECKING:
|
|
21
|
+
from comtypes import hints
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
if TYPE_CHECKING:
|
|
25
|
+
_T_MTD = TypeVar("_T_MTD", bound=hints._MethodTypeDesc)
|
|
26
|
+
else:
|
|
27
|
+
_T_MTD = TypeVar("_T_MTD")
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class _MethodAnnotator(abc.ABC, Generic[_T_MTD]):
|
|
31
|
+
def __init__(self, method: _T_MTD) -> None:
|
|
32
|
+
self.method = method
|
|
33
|
+
|
|
34
|
+
@property
|
|
35
|
+
def inarg_specs(self) -> Sequence[Tuple[Any, str, Optional[Any]]]:
|
|
36
|
+
index = 0
|
|
37
|
+
result = []
|
|
38
|
+
for typ, name, flags, default in self.method.arguments:
|
|
39
|
+
if "in" in flags and "lcid" not in flags or not flags:
|
|
40
|
+
index += 1
|
|
41
|
+
if "optional" in flags:
|
|
42
|
+
default = ...
|
|
43
|
+
result.append((typ, (name or f"__arg{index}"), default))
|
|
44
|
+
return result
|
|
45
|
+
|
|
46
|
+
@abc.abstractmethod
|
|
47
|
+
def getvalue(self, name: str) -> str:
|
|
48
|
+
...
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
_CatMths = Tuple[ # categorized methods
|
|
52
|
+
str, Optional[_T_MTD], Optional[_T_MTD], Optional[_T_MTD], Optional[_T_MTD]
|
|
53
|
+
]
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class _MethodsAnnotator(abc.ABC, Generic[_T_MTD]):
|
|
57
|
+
def __init__(self) -> None:
|
|
58
|
+
self.stream = io.StringIO()
|
|
59
|
+
|
|
60
|
+
@abc.abstractmethod
|
|
61
|
+
def to_method_annotator(self, method: _T_MTD) -> _MethodAnnotator[_T_MTD]:
|
|
62
|
+
...
|
|
63
|
+
|
|
64
|
+
def _iter_methods(self, members: Iterable[_T_MTD]) -> Iterator[_CatMths[_T_MTD]]:
|
|
65
|
+
methods: Dict[str, List[Optional[_T_MTD]]] = {}
|
|
66
|
+
MTH = 0
|
|
67
|
+
GET = 1
|
|
68
|
+
PUT = 2
|
|
69
|
+
PUTREF = 3
|
|
70
|
+
for mem in members:
|
|
71
|
+
if "propget" in mem.idlflags:
|
|
72
|
+
methods.setdefault(mem.name, [None] * 4)[GET] = mem
|
|
73
|
+
elif "propput" in mem.idlflags:
|
|
74
|
+
methods.setdefault(mem.name, [None] * 4)[PUT] = mem
|
|
75
|
+
elif "propputref" in mem.idlflags:
|
|
76
|
+
methods.setdefault(mem.name, [None] * 4)[PUTREF] = mem
|
|
77
|
+
else:
|
|
78
|
+
methods.setdefault(mem.name, [None] * 4)[MTH] = mem
|
|
79
|
+
for name, (fmth, fget, fput, fputref) in methods.items():
|
|
80
|
+
yield name, fmth, fget, fput, fputref
|
|
81
|
+
|
|
82
|
+
def generate(self, members: Iterable[_T_MTD]) -> str:
|
|
83
|
+
for name, fmth, fget, fput, fputref in self._iter_methods(members):
|
|
84
|
+
if fmth:
|
|
85
|
+
self._gen_method(name, fmth)
|
|
86
|
+
elif fget and not fput and not fputref:
|
|
87
|
+
self._gen_prop_get(name, fget)
|
|
88
|
+
elif fget and fput and not fputref:
|
|
89
|
+
self._gen_prop_get_put(name, fget, fput)
|
|
90
|
+
elif fget and not fput and fputref:
|
|
91
|
+
self._gen_prop_get_putref(name, fget, fputref)
|
|
92
|
+
elif fget and fput and fputref:
|
|
93
|
+
self._gen_prop_get_put_putref(name, fget, fput, fputref)
|
|
94
|
+
elif not fget and fput and not fputref:
|
|
95
|
+
self._gen_prop_put(name, fput)
|
|
96
|
+
elif not fget and not fput and fputref:
|
|
97
|
+
self._gen_prop_putref(name, fputref)
|
|
98
|
+
elif not fget and fput and fputref:
|
|
99
|
+
self._gen_prop_put_putref(name, fput, fputref)
|
|
100
|
+
else:
|
|
101
|
+
self._define_member(f"pass # what does `{name}` behave?")
|
|
102
|
+
self._patch_dunder(name)
|
|
103
|
+
return self.stream.getvalue()
|
|
104
|
+
|
|
105
|
+
def _patch_dunder(self, name: str) -> None:
|
|
106
|
+
if name == "Count":
|
|
107
|
+
self._define_member(f"__len__ = hints.to_dunder_len({name})")
|
|
108
|
+
if name == "Item":
|
|
109
|
+
self._define_member(f"__call__ = hints.to_dunder_call({name})")
|
|
110
|
+
self._define_member(f"__getitem__ = hints.to_dunder_getitem({name})")
|
|
111
|
+
self._define_member(f"__setitem__ = hints.to_dunder_setitem({name})")
|
|
112
|
+
if name == "_NewEnum":
|
|
113
|
+
self._define_member(f"__iter__ = hints.to_dunder_iter({name})")
|
|
114
|
+
|
|
115
|
+
def _define_named_prop(
|
|
116
|
+
self, mem_name: str, getter: Optional[str] = None, setter: Optional[str] = None
|
|
117
|
+
) -> None:
|
|
118
|
+
if getter and setter:
|
|
119
|
+
content = (
|
|
120
|
+
f"{mem_name} = hints.named_property('{mem_name}', {getter}, {setter})"
|
|
121
|
+
)
|
|
122
|
+
elif getter and not setter:
|
|
123
|
+
content = f"{mem_name} = hints.named_property('{mem_name}', {getter})"
|
|
124
|
+
elif not getter and setter:
|
|
125
|
+
content = f"{mem_name} = hints.named_property('{mem_name}', fset={setter})"
|
|
126
|
+
else:
|
|
127
|
+
return
|
|
128
|
+
self._define_member(content)
|
|
129
|
+
|
|
130
|
+
def _define_normal_prop(
|
|
131
|
+
self, mem_name: str, getter: Optional[str] = None, setter: Optional[str] = None
|
|
132
|
+
) -> None:
|
|
133
|
+
if getter and setter:
|
|
134
|
+
content = f"{mem_name} = hints.normal_property({getter}, {setter})"
|
|
135
|
+
elif getter and not setter:
|
|
136
|
+
content = f"{mem_name} = hints.normal_property({getter})"
|
|
137
|
+
elif not getter and setter:
|
|
138
|
+
content = f"{mem_name} = hints.normal_property(fset={setter})"
|
|
139
|
+
else:
|
|
140
|
+
return
|
|
141
|
+
self._define_member(content)
|
|
142
|
+
|
|
143
|
+
def _define_member(self, content: str) -> None:
|
|
144
|
+
print(f" {content}", file=self.stream)
|
|
145
|
+
|
|
146
|
+
def _gen_method(self, name: str, mth: _T_MTD) -> None:
|
|
147
|
+
self._define_member(self.to_method_annotator(mth).getvalue(name))
|
|
148
|
+
|
|
149
|
+
def _gen_prop_get(self, name: str, fget: _T_MTD) -> None:
|
|
150
|
+
getter_anno = self.to_method_annotator(fget)
|
|
151
|
+
self._define_member(getter_anno.getvalue(f"_get_{name}"))
|
|
152
|
+
if getter_anno.inarg_specs:
|
|
153
|
+
self._define_named_prop(name, f"_get_{name}")
|
|
154
|
+
else:
|
|
155
|
+
self._define_normal_prop(name, f"_get_{name}")
|
|
156
|
+
|
|
157
|
+
def _gen_prop_get_put(self, name: str, fget: _T_MTD, fput: _T_MTD) -> None:
|
|
158
|
+
getter_anno = self.to_method_annotator(fget)
|
|
159
|
+
setter_anno = self.to_method_annotator(fput)
|
|
160
|
+
self._define_member(getter_anno.getvalue(f"_get_{name}"))
|
|
161
|
+
self._define_member(setter_anno.getvalue(f"_set_{name}"))
|
|
162
|
+
if getter_anno.inarg_specs:
|
|
163
|
+
self._define_named_prop(name, f"_get_{name}", f"_set_{name}")
|
|
164
|
+
else:
|
|
165
|
+
self._define_normal_prop(name, f"_get_{name}", f"_set_{name}")
|
|
166
|
+
|
|
167
|
+
def _gen_prop_get_putref(self, name: str, fget: _T_MTD, fputref: _T_MTD) -> None:
|
|
168
|
+
getter_anno = self.to_method_annotator(fget)
|
|
169
|
+
setter_anno = self.to_method_annotator(fputref)
|
|
170
|
+
self._define_member(getter_anno.getvalue(f"_get_{name}"))
|
|
171
|
+
self._define_member(setter_anno.getvalue(f"_setref_{name}"))
|
|
172
|
+
if getter_anno.inarg_specs:
|
|
173
|
+
self._define_named_prop(name, f"_get_{name}", f"_setref_{name}")
|
|
174
|
+
else:
|
|
175
|
+
self._define_normal_prop(name, f"_get_{name}", f"_setref_{name}")
|
|
176
|
+
|
|
177
|
+
def _gen_prop_get_put_putref(
|
|
178
|
+
self, name: str, fget: _T_MTD, fput: _T_MTD, fputref: _T_MTD
|
|
179
|
+
) -> None:
|
|
180
|
+
getter_anno = self.to_method_annotator(fget)
|
|
181
|
+
put_anno = self.to_method_annotator(fput)
|
|
182
|
+
putref_anno = self.to_method_annotator(fputref)
|
|
183
|
+
self._define_member(getter_anno.getvalue(f"_get_{name}"))
|
|
184
|
+
self._define_member(put_anno.getvalue(f"_set_{name}"))
|
|
185
|
+
self._define_member(putref_anno.getvalue(f"_setref_{name}"))
|
|
186
|
+
setter = f"hints.put_or_putref(_set_{name}, _setref_{name})"
|
|
187
|
+
if getter_anno.inarg_specs:
|
|
188
|
+
self._define_named_prop(name, f"_get_{name}", setter)
|
|
189
|
+
else:
|
|
190
|
+
self._define_normal_prop(name, f"_get_{name}", setter)
|
|
191
|
+
|
|
192
|
+
def _gen_prop_put(self, name: str, fput: _T_MTD) -> None:
|
|
193
|
+
setter_anno = self.to_method_annotator(fput)
|
|
194
|
+
self._define_member(setter_anno.getvalue(f"_set_{name}"))
|
|
195
|
+
if len(setter_anno.inarg_specs) >= 2:
|
|
196
|
+
self._define_named_prop(name, setter=f"_set_{name}")
|
|
197
|
+
else:
|
|
198
|
+
self._define_normal_prop(name, setter=f"_set_{name}")
|
|
199
|
+
|
|
200
|
+
def _gen_prop_putref(self, name: str, fputref: _T_MTD) -> None:
|
|
201
|
+
setter_anno = self.to_method_annotator(fputref)
|
|
202
|
+
self._define_member(setter_anno.getvalue(f"_setref_{name}"))
|
|
203
|
+
if len(setter_anno.inarg_specs) >= 2:
|
|
204
|
+
self._define_named_prop(name, setter=f"_setref_{name}")
|
|
205
|
+
else:
|
|
206
|
+
self._define_normal_prop(name, setter=f"_setref_{name}")
|
|
207
|
+
|
|
208
|
+
def _gen_prop_put_putref(self, name: str, fput: _T_MTD, fputref: _T_MTD) -> None:
|
|
209
|
+
put_anno = self.to_method_annotator(fput)
|
|
210
|
+
putref_anno = self.to_method_annotator(fputref)
|
|
211
|
+
self._define_member(put_anno.getvalue(f"_set_{name}"))
|
|
212
|
+
self._define_member(putref_anno.getvalue(f"_setref_{name}"))
|
|
213
|
+
setter = f"hints.put_or_putref(_set_{name}, _setref_{name})"
|
|
214
|
+
if len(put_anno.inarg_specs) >= 2:
|
|
215
|
+
self._define_named_prop(name, setter=setter)
|
|
216
|
+
else:
|
|
217
|
+
self._define_normal_prop(name, setter=setter)
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
class ComMethodAnnotator(_MethodAnnotator[typedesc.ComMethod]):
|
|
221
|
+
def _iter_outarg_specs(self) -> Iterator[Tuple[Any, str]]:
|
|
222
|
+
for typ, name, flags, _ in self.method.arguments:
|
|
223
|
+
if "out" in flags:
|
|
224
|
+
yield typ, name
|
|
225
|
+
|
|
226
|
+
def getvalue(self, name: str) -> str:
|
|
227
|
+
inargs = []
|
|
228
|
+
has_optional = False
|
|
229
|
+
for _, argname, default in self.inarg_specs:
|
|
230
|
+
if keyword.iskeyword(argname):
|
|
231
|
+
inargs = ["*args: Any", "**kwargs: Any"]
|
|
232
|
+
break
|
|
233
|
+
if default is None:
|
|
234
|
+
if has_optional:
|
|
235
|
+
# probably propput or propputref
|
|
236
|
+
# HACK: Something that goes into this conditional branch
|
|
237
|
+
# should be a special callback.
|
|
238
|
+
inargs.append("**kwargs: Any")
|
|
239
|
+
break
|
|
240
|
+
inargs.append(f"{argname}: Any")
|
|
241
|
+
else:
|
|
242
|
+
inargs.append(f"{argname}: Any = ...")
|
|
243
|
+
has_optional = True
|
|
244
|
+
outargs = ["Any" for _ in self._iter_outarg_specs()]
|
|
245
|
+
if not outargs:
|
|
246
|
+
out = "Any"
|
|
247
|
+
elif len(outargs) == 1:
|
|
248
|
+
out = outargs[0]
|
|
249
|
+
else:
|
|
250
|
+
out = "Tuple[" + ", ".join(outargs) + "]"
|
|
251
|
+
in_ = ("self, " + ", ".join(inargs)) if inargs else "self"
|
|
252
|
+
return f"def {name}({in_}) -> {out}: ..."
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
class ComMethodsAnnotator(_MethodsAnnotator[typedesc.ComMethod]):
|
|
256
|
+
def to_method_annotator(self, m: typedesc.ComMethod) -> ComMethodAnnotator:
|
|
257
|
+
return ComMethodAnnotator(m)
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
class ComInterfaceMembersAnnotator(object):
|
|
261
|
+
def __init__(self, itf: typedesc.ComInterface):
|
|
262
|
+
self.itf = itf
|
|
263
|
+
|
|
264
|
+
def generate(self) -> str:
|
|
265
|
+
return ComMethodsAnnotator().generate(self.itf.members)
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
class DispMethodAnnotator(_MethodAnnotator[typedesc.DispMethod]):
|
|
269
|
+
def getvalue(self, name: str) -> str:
|
|
270
|
+
inargs = []
|
|
271
|
+
has_optional = False
|
|
272
|
+
for _, argname, default in self.inarg_specs:
|
|
273
|
+
if keyword.iskeyword(argname):
|
|
274
|
+
inargs = ["*args: Any", "**kwargs: Any"]
|
|
275
|
+
break
|
|
276
|
+
if default is None:
|
|
277
|
+
if has_optional:
|
|
278
|
+
# probably propput or propputref
|
|
279
|
+
# HACK: Something that goes into this conditional branch
|
|
280
|
+
# should be a special callback.
|
|
281
|
+
inargs.append("**kwargs: Any")
|
|
282
|
+
break
|
|
283
|
+
inargs.append(f"{argname}: Any")
|
|
284
|
+
else:
|
|
285
|
+
inargs.append(f"{argname}: Any = ...")
|
|
286
|
+
has_optional = True
|
|
287
|
+
out = "Any"
|
|
288
|
+
in_ = ("self, " + ", ".join(inargs)) if inargs else "self"
|
|
289
|
+
return f"def {name}({in_}) -> {out}: ..."
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
class DispMethodsAnnotator(_MethodsAnnotator[typedesc.DispMethod]):
|
|
293
|
+
def to_method_annotator(self, m: typedesc.DispMethod) -> DispMethodAnnotator:
|
|
294
|
+
return DispMethodAnnotator(m)
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
class DispInterfaceMembersAnnotator(object):
|
|
298
|
+
def __init__(self, itf: typedesc.DispInterface):
|
|
299
|
+
self.itf = itf
|
|
300
|
+
self.stream = io.StringIO()
|
|
301
|
+
|
|
302
|
+
def _categorize_members(
|
|
303
|
+
self,
|
|
304
|
+
) -> Tuple[Iterable[typedesc.DispProperty], Iterable[typedesc.DispMethod]]:
|
|
305
|
+
props: List[typedesc.DispProperty] = []
|
|
306
|
+
methods: List[typedesc.DispMethod] = []
|
|
307
|
+
for mem in self.itf.members:
|
|
308
|
+
if isinstance(mem, typedesc.DispMethod):
|
|
309
|
+
methods.append(mem)
|
|
310
|
+
elif isinstance(mem, typedesc.DispProperty):
|
|
311
|
+
props.append(mem)
|
|
312
|
+
return props, methods
|
|
313
|
+
|
|
314
|
+
def generate(self) -> str:
|
|
315
|
+
props, methods = self._categorize_members()
|
|
316
|
+
for mem in props:
|
|
317
|
+
print(" @property # dispprop", file=self.stream)
|
|
318
|
+
print(f" def {mem.name}(self) -> Any: ...", file=self.stream)
|
|
319
|
+
return self.stream.getvalue() + DispMethodsAnnotator().generate(methods)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: comtypes
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.4.0
|
|
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
|
|
@@ -19,13 +19,14 @@ License-File: LICENSE.txt
|
|
|
19
19
|
|
|
20
20
|
# comtypes
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
[
|
|
23
|
+
[](https://pypi.org/project/comtypes/) [](https://pypi.org/project/comtypes/) [](https://pypi.org/project/comtypes/) [](https://pypi.org/project/comtypes/)
|
|
24
|
+
[](https://github.com/enthought/comtypes/stargazers) [](https://github.com/enthought/comtypes/network/members)
|
|
24
25
|
[](https://tidelift.com/subscription/pkg/pypi-comtypes?utm_source=pypi-comtypes&utm_medium=readme)
|
|
25
26
|
|
|
26
27
|
## About
|
|
27
28
|
|
|
28
|
-
`comtypes` is a lightweight `Python` COM package, based on the [`ctypes`](https://docs.python.org/library/ctypes.html) FFI library.
|
|
29
|
+
`comtypes` is a lightweight `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) FFI library.
|
|
29
30
|
|
|
30
31
|
`comtypes` allows to define, call, and implement custom and dispatch-based COM interfaces in pure `Python`.
|
|
31
32
|
|
|
@@ -66,31 +67,6 @@ But these third-parties are not required as a prerequisite for runtime.
|
|
|
66
67
|
Tracking issues, reporting bugs and contributing to the codebase and documentation are on GitHub at:
|
|
67
68
|
https://github.com/enthought/comtypes
|
|
68
69
|
|
|
69
|
-
<a id="ongoing-plans"></a>
|
|
70
|
-
### Ongoing plans
|
|
71
|
-
#### `GetModule` will also generate static typing for methods and properties
|
|
72
|
-
`comtypes.client.GetModule` generates `Python` wrapper modules from a COM type library, containing interface classes, coclasses, constants, and structures. The `.py` files are generated in the `comtypes.gen` package.
|
|
73
|
-
|
|
74
|
-
In the current `comtypes` specification, type checkers could not infer static type information from generated modules codebase, since methods and properties were mostly defined and implemented by metaclasses.
|
|
75
|
-
In future release, in generated modules, static typing will be added to part of methods and properties.
|
|
76
|
-
|
|
77
|
-
Static type information is added only under [`if TYPE_CHECKING:`](https://docs.python.org/3/library/typing.html#typing.TYPE_CHECKING) blocks. Consequently, it will **not** override any methods defined with metaclasses at runtime, ensuring that the runtime behavior remains unchanged.
|
|
78
|
-
|
|
79
|
-
Please refer to [the GitHub issue](https://github.com/enthought/comtypes/issues/400) for details.
|
|
80
|
-
|
|
81
|
-
#### In friendly modules, the names that were used as aliases for `ctypes.c_int` will be used for enumeration types implemented with `enum`
|
|
82
|
-
`comtypes.client.GetModule` generates two `Python` modules in the `comtypes.gen` package with a single call.
|
|
83
|
-
|
|
84
|
-
A first wrapper module is created with a long name that is derived from the type library guid, version number and lcid. It contains interface classes, coclasses, constants, and structures.
|
|
85
|
-
A second friendly module is created with a shorter name derived from the type library name itself. It imports items from the wrapper module, and will be the module returned from `GetModule`.
|
|
86
|
-
|
|
87
|
-
In the current `comtypes` specification, if a COM type kind is defined as an enumeration type, that type name is used as an alias for [`ctypes.c_int`](https://docs.python.org/3/library/ctypes.html#ctypes.c_int) in the wrapper module, and that symbol is imported into the friendly module.
|
|
88
|
-
In future release, in friendly modules, their names will no longer be aliases for `c_int`. Instead, they will be defined as enumerations implemented with [`enum`](https://docs.python.org/3/library/enum.html).
|
|
89
|
-
|
|
90
|
-
When imported into the friendly module, the wrapper module will be aliased with an abstracted name (`__wrapper_module__`). This allows users to continue using the old definitions by modifying the import sections of their codebase.
|
|
91
|
-
|
|
92
|
-
Please refer to [the GitHub issue](https://github.com/enthought/comtypes/issues/345) for details.
|
|
93
|
-
|
|
94
70
|
## For Enterprise
|
|
95
71
|
|
|
96
72
|
Available as part of the Tidelift Subscription.
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|