comtypes 1.4.1__zip → 1.4.3__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.1 → comtypes-1.4.3}/CHANGES.txt +24 -1
- {comtypes-1.4.1/comtypes.egg-info → comtypes-1.4.3}/PKG-INFO +29 -1
- {comtypes-1.4.1 → comtypes-1.4.3}/README.md +28 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/__init__.py +6 -8
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/automation.py +26 -2
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/client/_generate.py +105 -80
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/hints.pyi +29 -2
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_GUID.py +23 -2
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_client.py +14 -4
- comtypes-1.4.3/comtypes/test/test_client_regenerate_modules.py +158 -0
- comtypes-1.4.3/comtypes/test/test_dispifc_records.py +90 -0
- comtypes-1.4.3/comtypes/test/test_findgendir.py +87 -0
- comtypes-1.4.3/comtypes/tools/codegenerator/__init__.py +5 -0
- {comtypes-1.4.1/comtypes/tools → comtypes-1.4.3/comtypes/tools/codegenerator}/codegenerator.py +140 -716
- comtypes-1.4.3/comtypes/tools/codegenerator/helpers.py +357 -0
- comtypes-1.4.3/comtypes/tools/codegenerator/modulenamer.py +24 -0
- comtypes-1.4.3/comtypes/tools/codegenerator/namespaces.py +212 -0
- comtypes-1.4.3/comtypes/tools/codegenerator/packing.py +81 -0
- {comtypes-1.4.1/comtypes/tools → comtypes-1.4.3/comtypes/tools/codegenerator}/typeannotator.py +32 -15
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/tools/tlbparser.py +19 -49
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/tools/typedesc.py +58 -10
- {comtypes-1.4.1 → comtypes-1.4.3/comtypes.egg-info}/PKG-INFO +29 -1
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes.egg-info/SOURCES.txt +10 -3
- {comtypes-1.4.1 → comtypes-1.4.3}/setup.py +1 -0
- comtypes-1.4.1/comtypes/test/test_findgendir.py +0 -94
- {comtypes-1.4.1 → comtypes-1.4.3}/LICENSE.txt +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/MANIFEST.in +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/GUID.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/_comobject.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/_memberspec.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/_meta.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/_npsupport.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/_safearray.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/clear_cache.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/client/__init__.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/client/_code_cache.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/client/_constants.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/client/_events.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/client/dynamic.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/client/lazybind.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/connectionpoints.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/errorinfo.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/git.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/hresult.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/logutil.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/messageloop.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/patcher.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/persist.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/safearray.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/server/__init__.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/server/automation.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/server/connectionpoints.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/server/inprocserver.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/server/localserver.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/server/register.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/server/w_getopt.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/shelllink.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/TestComServer.idl +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/TestComServer.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/TestComServer.tlb +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/TestDispServer.idl +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/TestDispServer.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/TestDispServer.tlb +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/__init__.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/find_memleak.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/mylib.idl +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/mytypelib.idl +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/runtests.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/setup.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_BSTR.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_DISPPARAMS.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_QueryService.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_agilent.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_avmc.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_basic.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_casesensitivity.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_clear_cache.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_client_dynamic.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_collections.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_comserver.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_createwrappers.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_dict.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_dispinterface.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_dyndispatch.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_excel.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_getactiveobj.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_ie.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_ienum.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_imfattributes.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_inout_args.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_jscript.js +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_msscript.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_npsupport.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_outparam.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_propputref.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_pump_events.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_safearray.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_sapi.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_server.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_showevents.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_subinterface.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_typeinfo.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_urlhistory.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_variant.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_win32com_interop.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_wmi.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/test/test_word.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/tools/__init__.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/tools/typedesc_base.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/typeinfo.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/util.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes/viewobject.py +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes.egg-info/dependency_links.txt +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes.egg-info/entry_points.txt +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/comtypes.egg-info/top_level.txt +0 -0
- {comtypes-1.4.1 → comtypes-1.4.3}/setup.cfg +0 -0
{comtypes-1.4.1/comtypes/tools → comtypes-1.4.3/comtypes/tools/codegenerator}/codegenerator.py
RENAMED
|
@@ -1,28 +1,30 @@
|
|
|
1
1
|
# Code generator to generate code for everything contained in COM type
|
|
2
2
|
# libraries.
|
|
3
|
-
from __future__ import print_function
|
|
4
|
-
import ctypes
|
|
5
3
|
import keyword
|
|
6
4
|
import logging
|
|
7
5
|
import os
|
|
8
|
-
import sys
|
|
9
6
|
import textwrap
|
|
10
|
-
from typing import
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
List,
|
|
15
|
-
Optional,
|
|
16
|
-
Sequence,
|
|
17
|
-
Set,
|
|
18
|
-
Tuple,
|
|
19
|
-
Union as _UnionT,
|
|
20
|
-
)
|
|
7
|
+
from typing import Any
|
|
8
|
+
from typing import Dict, List, Tuple
|
|
9
|
+
from typing import Sequence
|
|
10
|
+
from typing import Optional, Union as _UnionT
|
|
21
11
|
import io
|
|
22
12
|
|
|
23
13
|
import comtypes
|
|
24
14
|
from comtypes import typeinfo
|
|
25
|
-
from comtypes.tools import tlbparser, typedesc
|
|
15
|
+
from comtypes.tools import tlbparser, typedesc
|
|
16
|
+
from comtypes.tools.codegenerator import namespaces
|
|
17
|
+
from comtypes.tools.codegenerator import packing
|
|
18
|
+
from comtypes.tools.codegenerator.modulenamer import name_wrapper_module
|
|
19
|
+
from comtypes.tools.codegenerator.helpers import (
|
|
20
|
+
get_real_type,
|
|
21
|
+
ASSUME_STRINGS,
|
|
22
|
+
ComMethodGenerator,
|
|
23
|
+
DispMethodGenerator,
|
|
24
|
+
DispPropertyGenerator,
|
|
25
|
+
TypeNamer,
|
|
26
|
+
)
|
|
27
|
+
from comtypes.tools.codegenerator import typeannotator
|
|
26
28
|
|
|
27
29
|
|
|
28
30
|
version = comtypes.__version__
|
|
@@ -32,417 +34,45 @@ logger = logging.getLogger(__name__)
|
|
|
32
34
|
__warn_on_munge__ = __debug__
|
|
33
35
|
|
|
34
36
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
class dispid(object):
|
|
44
|
-
def __init__(self, memid):
|
|
45
|
-
self.memid = memid
|
|
46
|
-
|
|
47
|
-
def __repr__(self):
|
|
48
|
-
return "dispid(%s)" % self.memid
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
class helpstring(object):
|
|
52
|
-
def __init__(self, text):
|
|
53
|
-
self.text = text
|
|
54
|
-
|
|
55
|
-
def __repr__(self):
|
|
56
|
-
return "helpstring(%r)" % self.text
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
# XXX Should this be in ctypes itself?
|
|
60
|
-
ctypes_names = {
|
|
61
|
-
"unsigned char": "c_ubyte",
|
|
62
|
-
"signed char": "c_byte",
|
|
63
|
-
"char": "c_char",
|
|
64
|
-
"wchar_t": "c_wchar",
|
|
65
|
-
"short unsigned int": "c_ushort",
|
|
66
|
-
"short int": "c_short",
|
|
67
|
-
"long unsigned int": "c_ulong",
|
|
68
|
-
"long int": "c_long",
|
|
69
|
-
"long signed int": "c_long",
|
|
70
|
-
"unsigned int": "c_uint",
|
|
71
|
-
"int": "c_int",
|
|
72
|
-
"long long unsigned int": "c_ulonglong",
|
|
73
|
-
"long long int": "c_longlong",
|
|
74
|
-
"double": "c_double",
|
|
75
|
-
"float": "c_float",
|
|
76
|
-
# Hm...
|
|
77
|
-
"void": "None",
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
def get_real_type(tp):
|
|
82
|
-
if type(tp) is typedesc.Typedef:
|
|
83
|
-
return get_real_type(tp.typ)
|
|
84
|
-
elif isinstance(tp, typedesc.CvQualifiedType):
|
|
85
|
-
return get_real_type(tp.typ)
|
|
86
|
-
return tp
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
ASSUME_STRINGS = True
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
def _calc_packing(struct, fields, pack, isStruct):
|
|
93
|
-
# Try a certain packing, raise PackingError if field offsets,
|
|
94
|
-
# total size ot total alignment is wrong.
|
|
95
|
-
if struct.size is None: # incomplete struct
|
|
96
|
-
return -1
|
|
97
|
-
if struct.name in dont_assert_size:
|
|
98
|
-
return None
|
|
99
|
-
if struct.bases:
|
|
100
|
-
size = struct.bases[0].size
|
|
101
|
-
total_align = struct.bases[0].align
|
|
102
|
-
else:
|
|
103
|
-
size = 0
|
|
104
|
-
total_align = 8 # in bits
|
|
105
|
-
for i, f in enumerate(fields):
|
|
106
|
-
if f.bits: # this code cannot handle bit field sizes.
|
|
107
|
-
# print "##XXX FIXME"
|
|
108
|
-
return -2 # XXX FIXME
|
|
109
|
-
s, a = storage(f.typ)
|
|
110
|
-
if pack is not None:
|
|
111
|
-
a = min(pack, a)
|
|
112
|
-
if size % a:
|
|
113
|
-
size += a - size % a
|
|
114
|
-
if isStruct:
|
|
115
|
-
if size != f.offset:
|
|
116
|
-
raise PackingError("field %s offset (%s/%s)" % (f.name, size, f.offset))
|
|
117
|
-
size += s
|
|
118
|
-
else:
|
|
119
|
-
size = max(size, s)
|
|
120
|
-
total_align = max(total_align, a)
|
|
121
|
-
if total_align != struct.align:
|
|
122
|
-
raise PackingError("total alignment (%s/%s)" % (total_align, struct.align))
|
|
123
|
-
a = total_align
|
|
124
|
-
if pack is not None:
|
|
125
|
-
a = min(pack, a)
|
|
126
|
-
if size % a:
|
|
127
|
-
size += a - size % a
|
|
128
|
-
if size != struct.size:
|
|
129
|
-
raise PackingError("total size (%s/%s)" % (size, struct.size))
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
def calc_packing(struct, fields):
|
|
133
|
-
# try several packings, starting with unspecified packing
|
|
134
|
-
isStruct = isinstance(struct, typedesc.Structure)
|
|
135
|
-
for pack in [None, 16 * 8, 8 * 8, 4 * 8, 2 * 8, 1 * 8]:
|
|
136
|
-
try:
|
|
137
|
-
_calc_packing(struct, fields, pack, isStruct)
|
|
138
|
-
except PackingError as details:
|
|
139
|
-
continue
|
|
140
|
-
else:
|
|
141
|
-
if pack is None:
|
|
142
|
-
return None
|
|
143
|
-
|
|
144
|
-
return int(pack / 8)
|
|
145
|
-
|
|
146
|
-
raise PackingError("PACKING FAILED: %s" % details)
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
class PackingError(Exception):
|
|
150
|
-
pass
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
# XXX These should be filtered out in gccxmlparser.
|
|
154
|
-
dont_assert_size = set(
|
|
155
|
-
[
|
|
156
|
-
"__si_class_type_info_pseudo",
|
|
157
|
-
"__class_type_info_pseudo",
|
|
158
|
-
]
|
|
159
|
-
)
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
def storage(t):
|
|
163
|
-
# return the size and alignment of a type
|
|
164
|
-
if isinstance(t, typedesc.Typedef):
|
|
165
|
-
return storage(t.typ)
|
|
166
|
-
elif isinstance(t, typedesc.ArrayType):
|
|
167
|
-
s, a = storage(t.typ)
|
|
168
|
-
return s * (int(t.max) - int(t.min) + 1), a
|
|
169
|
-
return int(t.size), int(t.align)
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
################################################################
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
def name_wrapper_module(tlib):
|
|
176
|
-
"""Determine the name of a typelib wrapper module"""
|
|
177
|
-
libattr = tlib.GetLibAttr()
|
|
178
|
-
modname = "_%s_%s_%s_%s" % (
|
|
179
|
-
str(libattr.guid)[1:-1].replace("-", "_"),
|
|
180
|
-
libattr.lcid,
|
|
181
|
-
libattr.wMajorVerNum,
|
|
182
|
-
libattr.wMinorVerNum,
|
|
183
|
-
)
|
|
184
|
-
return "comtypes.gen.%s" % modname
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
def name_friendly_module(tlib):
|
|
188
|
-
"""Determine the friendly-name of a typelib module.
|
|
189
|
-
If cannot get friendly-name from typelib, returns `None`.
|
|
190
|
-
"""
|
|
191
|
-
try:
|
|
192
|
-
modulename = tlib.GetDocumentation(-1)[0]
|
|
193
|
-
except comtypes.COMError:
|
|
194
|
-
return
|
|
195
|
-
return "comtypes.gen.%s" % modulename
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
################################################################
|
|
199
|
-
|
|
200
|
-
_DefValType = _UnionT["lcid", Any, None]
|
|
201
|
-
_IdlFlagType = _UnionT[str, dispid, helpstring]
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
def _to_arg_definition(
|
|
205
|
-
type_name: str,
|
|
206
|
-
arg_name: str,
|
|
207
|
-
idlflags: List[str],
|
|
208
|
-
default: _DefValType,
|
|
209
|
-
) -> str:
|
|
210
|
-
if default is not None:
|
|
211
|
-
elms = (idlflags, type_name, arg_name, default)
|
|
212
|
-
code = " (%r, %s, '%s', %r)" % elms
|
|
213
|
-
if len(code) > 80:
|
|
214
|
-
code = (
|
|
215
|
-
" (\n"
|
|
216
|
-
" %r,\n"
|
|
217
|
-
" %s,\n"
|
|
218
|
-
" '%s',\n"
|
|
219
|
-
" %r\n"
|
|
220
|
-
" )"
|
|
221
|
-
) % elms
|
|
222
|
-
else:
|
|
223
|
-
elms = (idlflags, type_name, arg_name)
|
|
224
|
-
code = " (%r, %s, '%s')" % elms
|
|
225
|
-
if len(code) > 80:
|
|
226
|
-
code = (
|
|
227
|
-
" (\n"
|
|
228
|
-
" %r,\n"
|
|
229
|
-
" %s,\n"
|
|
230
|
-
" '%s',\n"
|
|
231
|
-
" )"
|
|
232
|
-
) % elms
|
|
233
|
-
return code
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
class ComMethodGenerator(object):
|
|
237
|
-
def __init__(self, m: typedesc.ComMethod, isdual: bool) -> None:
|
|
238
|
-
self._m = m
|
|
239
|
-
self._isdual = isdual
|
|
240
|
-
self._stream = io.StringIO()
|
|
241
|
-
self._to_type_name = TypeNamer()
|
|
242
|
-
|
|
243
|
-
def generate(self):
|
|
244
|
-
# () -> str
|
|
245
|
-
if not self._m.arguments:
|
|
246
|
-
self._make_noargs()
|
|
247
|
-
else:
|
|
248
|
-
self._make_withargs()
|
|
249
|
-
return self._stream.getvalue()
|
|
250
|
-
|
|
251
|
-
def _get_common_elms(self) -> Tuple[List[_IdlFlagType], str, str]:
|
|
252
|
-
idlflags: List[_IdlFlagType] = []
|
|
253
|
-
if self._isdual:
|
|
254
|
-
idlflags.append(dispid(self._m.memid))
|
|
255
|
-
idlflags.extend(self._m.idlflags)
|
|
256
|
-
else: # We don't include the dispid for non-dispatch COM interfaces
|
|
257
|
-
idlflags.extend(self._m.idlflags)
|
|
258
|
-
if __debug__ and self._m.doc:
|
|
259
|
-
idlflags.insert(1, helpstring(self._m.doc))
|
|
260
|
-
type_name = self._to_type_name(self._m.returns)
|
|
261
|
-
return (idlflags, type_name, self._m.name)
|
|
262
|
-
|
|
263
|
-
def _make_noargs(self) -> None:
|
|
264
|
-
elms = self._get_common_elms()
|
|
265
|
-
code = " COMMETHOD(%r, %s, '%s')," % elms
|
|
266
|
-
if len(code) > 80:
|
|
267
|
-
code = (
|
|
268
|
-
" COMMETHOD(\n"
|
|
269
|
-
" %r,\n"
|
|
270
|
-
" %s,\n"
|
|
271
|
-
" '%s',\n"
|
|
272
|
-
" ),"
|
|
273
|
-
) % elms
|
|
274
|
-
print(code, file=self._stream)
|
|
275
|
-
|
|
276
|
-
def _make_withargs(self) -> None:
|
|
277
|
-
code = (
|
|
278
|
-
" COMMETHOD(\n" " %r,\n" " %s,\n" " '%s',"
|
|
279
|
-
) % self._get_common_elms()
|
|
280
|
-
print(code, file=self._stream)
|
|
281
|
-
arglist = [_to_arg_definition(*i) for i in self._iter_args()]
|
|
282
|
-
print(",\n".join(arglist), file=self._stream)
|
|
283
|
-
print(" ),", file=self._stream)
|
|
284
|
-
|
|
285
|
-
def _iter_args(self) -> Iterator[Tuple[str, str, List[str], _DefValType]]:
|
|
286
|
-
for typ, arg_name, _f, _defval in self._m.arguments:
|
|
287
|
-
###########################################################
|
|
288
|
-
# IDL files that contain 'open arrays' or 'conformant
|
|
289
|
-
# varying arrays' method parameters are strange.
|
|
290
|
-
# These arrays have both a 'size_is()' and
|
|
291
|
-
# 'length_is()' attribute, like this example from
|
|
292
|
-
# dia2.idl (in the DIA SDK):
|
|
293
|
-
#
|
|
294
|
-
# interface IDiaSymbol: IUnknown {
|
|
295
|
-
# ...
|
|
296
|
-
# HRESULT get_dataBytes(
|
|
297
|
-
# [in] DWORD cbData,
|
|
298
|
-
# [out] DWORD *pcbData,
|
|
299
|
-
# [out, size_is(cbData),
|
|
300
|
-
# length_is(*pcbData)] BYTE data[]
|
|
301
|
-
# );
|
|
302
|
-
#
|
|
303
|
-
# The really strange thing is that the decompiled type
|
|
304
|
-
# library then contains this declaration, which declares
|
|
305
|
-
# the interface itself as [out] method parameter:
|
|
306
|
-
#
|
|
307
|
-
# interface IDiaSymbol: IUnknown {
|
|
308
|
-
# ...
|
|
309
|
-
# HRESULT _stdcall get_dataBytes(
|
|
310
|
-
# [in] unsigned long cbData,
|
|
311
|
-
# [out] unsigned long* pcbData,
|
|
312
|
-
# [out] IDiaSymbol data);
|
|
313
|
-
#
|
|
314
|
-
# Of course, comtypes does not accept a COM interface
|
|
315
|
-
# as method parameter; so replace the parameter type
|
|
316
|
-
# with the comtypes spelling of 'unsigned char *', and
|
|
317
|
-
# mark the parameter as [in, out], so the IDL
|
|
318
|
-
# equivalent would be like this:
|
|
319
|
-
#
|
|
320
|
-
# interface IDiaSymbol: IUnknown {
|
|
321
|
-
# ...
|
|
322
|
-
# HRESULT _stdcall get_dataBytes(
|
|
323
|
-
# [in] unsigned long cbData,
|
|
324
|
-
# [out] unsigned long* pcbData,
|
|
325
|
-
# [in, out] BYTE data[]);
|
|
326
|
-
###########################################################
|
|
327
|
-
idlflags = list(_f) # shallow copy to avoid side effects
|
|
328
|
-
if isinstance(typ, typedesc.ComInterface):
|
|
329
|
-
type_name = "OPENARRAY"
|
|
330
|
-
if "in" not in idlflags:
|
|
331
|
-
idlflags.append("in")
|
|
332
|
-
else:
|
|
333
|
-
type_name = self._to_type_name(typ)
|
|
334
|
-
if "lcid" in idlflags: # and 'in' in idlflags:
|
|
335
|
-
default = lcid
|
|
336
|
-
else:
|
|
337
|
-
default = _defval
|
|
338
|
-
yield (type_name, arg_name, idlflags, default)
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
class DispMethodGenerator(object):
|
|
342
|
-
def __init__(self, m: typedesc.DispMethod) -> None:
|
|
343
|
-
self._m = m
|
|
344
|
-
self._stream = io.StringIO()
|
|
345
|
-
self._to_type_name = TypeNamer()
|
|
346
|
-
|
|
347
|
-
def generate(self):
|
|
348
|
-
# () -> str
|
|
349
|
-
if not self._m.arguments:
|
|
350
|
-
self._make_noargs()
|
|
351
|
-
else:
|
|
352
|
-
self._make_withargs()
|
|
353
|
-
return self._stream.getvalue()
|
|
354
|
-
|
|
355
|
-
def _get_common_elms(self) -> Tuple[List[_IdlFlagType], str, str]:
|
|
356
|
-
idlflags: List[_IdlFlagType] = []
|
|
357
|
-
idlflags.append(dispid(self._m.dispid))
|
|
358
|
-
idlflags.extend(self._m.idlflags)
|
|
359
|
-
if __debug__ and self._m.doc:
|
|
360
|
-
idlflags.insert(1, helpstring(self._m.doc))
|
|
361
|
-
type_name = self._to_type_name(self._m.returns)
|
|
362
|
-
return (idlflags, type_name, self._m.name)
|
|
363
|
-
|
|
364
|
-
def _make_noargs(self) -> None:
|
|
365
|
-
elms = self._get_common_elms()
|
|
366
|
-
code = " DISPMETHOD(%r, %s, '%s')," % elms
|
|
367
|
-
if len(code) > 80:
|
|
368
|
-
code = (
|
|
369
|
-
" DISPMETHOD(\n"
|
|
370
|
-
" %r,\n"
|
|
371
|
-
" %s,\n"
|
|
372
|
-
" '%s',\n"
|
|
373
|
-
" ),"
|
|
374
|
-
) % elms
|
|
375
|
-
print(code, file=self._stream)
|
|
376
|
-
|
|
377
|
-
def _make_withargs(self) -> None:
|
|
378
|
-
code = (
|
|
379
|
-
" DISPMETHOD(\n" " %r,\n" " %s,\n" " '%s',"
|
|
380
|
-
) % self._get_common_elms()
|
|
381
|
-
print(code, file=self._stream)
|
|
382
|
-
arglist = [_to_arg_definition(*i) for i in self._iter_args()]
|
|
383
|
-
print(",\n".join(arglist), file=self._stream)
|
|
384
|
-
print(" ),", file=self._stream)
|
|
385
|
-
|
|
386
|
-
def _iter_args(self) -> Iterator[Tuple[str, str, List[str], _DefValType]]:
|
|
387
|
-
for typ, arg_name, idlflags, default in self._m.arguments:
|
|
388
|
-
type_name = self._to_type_name(typ)
|
|
389
|
-
yield (type_name, arg_name, idlflags, default)
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
class DispPropertyGenerator(object):
|
|
393
|
-
def __init__(self, m: typedesc.DispProperty) -> None:
|
|
394
|
-
self._m = m
|
|
395
|
-
self._to_type_name = TypeNamer()
|
|
396
|
-
|
|
397
|
-
def generate(self):
|
|
398
|
-
# () -> str
|
|
399
|
-
elms = self._get_common_elms()
|
|
400
|
-
code = " DISPPROPERTY(%r, %s, '%s')," % elms
|
|
401
|
-
if len(code) > 80:
|
|
402
|
-
code = (
|
|
403
|
-
" DISPPROPERTY(\n"
|
|
404
|
-
" %r,\n"
|
|
405
|
-
" %s,\n"
|
|
406
|
-
" '%s'\n"
|
|
407
|
-
" ),"
|
|
408
|
-
) % elms
|
|
409
|
-
return code + "\n"
|
|
410
|
-
|
|
411
|
-
def _get_common_elms(self) -> Tuple[List[_IdlFlagType], str, str]:
|
|
412
|
-
idlflags: List[_IdlFlagType] = []
|
|
413
|
-
idlflags.append(dispid(self._m.dispid))
|
|
414
|
-
idlflags.extend(self._m.idlflags)
|
|
415
|
-
if __debug__ and self._m.doc:
|
|
416
|
-
idlflags.insert(1, helpstring(self._m.doc))
|
|
417
|
-
type_name = self._to_type_name(self._m.typ)
|
|
418
|
-
return (idlflags, type_name, self._m.name)
|
|
37
|
+
_InterfaceTypeDesc = _UnionT[
|
|
38
|
+
typedesc.ComInterface,
|
|
39
|
+
typedesc.ComInterfaceHead,
|
|
40
|
+
typedesc.ComInterfaceBody,
|
|
41
|
+
typedesc.DispInterface,
|
|
42
|
+
typedesc.DispInterfaceHead,
|
|
43
|
+
typedesc.DispInterfaceBody,
|
|
44
|
+
]
|
|
419
45
|
|
|
420
46
|
|
|
421
47
|
class CodeGenerator(object):
|
|
422
|
-
def __init__(self, known_symbols=None):
|
|
48
|
+
def __init__(self, known_symbols=None, known_interfaces=None) -> None:
|
|
423
49
|
self.stream = io.StringIO()
|
|
424
|
-
self.imports = ImportedNamespaces()
|
|
425
|
-
self.declarations = DeclaredNamespaces()
|
|
426
|
-
self.enums = EnumerationNamespaces()
|
|
50
|
+
self.imports = namespaces.ImportedNamespaces()
|
|
51
|
+
self.declarations = namespaces.DeclaredNamespaces()
|
|
52
|
+
self.enums = namespaces.EnumerationNamespaces()
|
|
53
|
+
self.unnamed_enum_members: List[Tuple[str, int]] = []
|
|
427
54
|
self._to_type_name = TypeNamer()
|
|
428
55
|
self.known_symbols = known_symbols or {}
|
|
56
|
+
self.known_interfaces = known_interfaces or {}
|
|
429
57
|
|
|
430
58
|
self.done = set() # type descriptions that have been generated
|
|
431
59
|
self.names = set() # names that have been generated
|
|
432
60
|
self.externals = [] # typelibs imported to generated module
|
|
433
|
-
self.
|
|
61
|
+
self.enum_aliases: Dict[str, str] = {}
|
|
434
62
|
self.last_item_class = False
|
|
435
63
|
|
|
436
64
|
def generate(self, item):
|
|
437
65
|
if item in self.done:
|
|
438
66
|
return
|
|
67
|
+
if self._is_interface_typedesc(item):
|
|
68
|
+
self._define_interface(item)
|
|
69
|
+
return
|
|
439
70
|
if isinstance(item, typedesc.StructureHead):
|
|
440
71
|
name = getattr(item.struct, "name", None)
|
|
441
72
|
else:
|
|
442
73
|
name = getattr(item, "name", None)
|
|
443
74
|
if name in self.known_symbols:
|
|
444
75
|
self.imports.add(name, symbols=self.known_symbols)
|
|
445
|
-
|
|
446
76
|
self.done.add(item)
|
|
447
77
|
if isinstance(item, typedesc.Structure):
|
|
448
78
|
self.done.add(item.get_head())
|
|
@@ -572,6 +202,19 @@ class CodeGenerator(object):
|
|
|
572
202
|
print(file=output)
|
|
573
203
|
print(self.declarations.getvalue(), file=output)
|
|
574
204
|
print(file=output)
|
|
205
|
+
if self.unnamed_enum_members:
|
|
206
|
+
print("# values for unnamed enumeration", file=output)
|
|
207
|
+
for n, v in self.unnamed_enum_members:
|
|
208
|
+
print(f"{n} = {v}", file=output)
|
|
209
|
+
print(file=output)
|
|
210
|
+
if self.enums:
|
|
211
|
+
print(self.enums.to_constants(), file=output)
|
|
212
|
+
print(file=output)
|
|
213
|
+
if self.enum_aliases:
|
|
214
|
+
print("# aliases for enums", file=output)
|
|
215
|
+
for k, v in self.enum_aliases.items():
|
|
216
|
+
print(f"{k} = {v}", file=output)
|
|
217
|
+
print(file=output)
|
|
575
218
|
print(self.stream.getvalue(), file=output)
|
|
576
219
|
print(self._make_dunder_all_part(), file=output)
|
|
577
220
|
print(file=output)
|
|
@@ -596,12 +239,12 @@ class CodeGenerator(object):
|
|
|
596
239
|
print(self._make_friendly_module_import_part(modname), file=output)
|
|
597
240
|
print(file=output)
|
|
598
241
|
print(file=output)
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
if enum_aliases:
|
|
604
|
-
for k, v in enum_aliases.items():
|
|
242
|
+
if self.enums:
|
|
243
|
+
print(self.enums.to_intflags(), file=output)
|
|
244
|
+
print(file=output)
|
|
245
|
+
print(file=output)
|
|
246
|
+
if self.enum_aliases:
|
|
247
|
+
for k, v in self.enum_aliases.items():
|
|
605
248
|
print(f"{k} = {v}", file=output)
|
|
606
249
|
print(file=output)
|
|
607
250
|
print(file=output)
|
|
@@ -639,10 +282,6 @@ class CodeGenerator(object):
|
|
|
639
282
|
part = f"from {modname} import (\n{joined_names}\n)"
|
|
640
283
|
return part
|
|
641
284
|
|
|
642
|
-
@property
|
|
643
|
-
def enum_aliases(self) -> Dict[str, str]:
|
|
644
|
-
return {k: v for k, v in self.aliases.items() if v in self.enums}
|
|
645
|
-
|
|
646
285
|
def need_VARIANT_imports(self, value):
|
|
647
286
|
text = repr(value)
|
|
648
287
|
if "Decimal(" in text:
|
|
@@ -667,23 +306,19 @@ class CodeGenerator(object):
|
|
|
667
306
|
if keyword.iskeyword(tp.name):
|
|
668
307
|
# XXX use logging!
|
|
669
308
|
if __warn_on_munge__:
|
|
670
|
-
print("# Fixing keyword as EnumValue for
|
|
309
|
+
print(f"# Fixing keyword as EnumValue for {tp.name}")
|
|
671
310
|
tp_name = self._to_type_name(tp)
|
|
672
|
-
print("%s = %d" % (tp_name, value), file=self.stream)
|
|
673
311
|
if tp.enumeration.name:
|
|
674
312
|
self.enums.add(tp.enumeration.name, tp_name, value)
|
|
313
|
+
else:
|
|
314
|
+
self.unnamed_enum_members.append((tp_name, value))
|
|
675
315
|
self.names.add(tp_name)
|
|
676
316
|
|
|
677
317
|
def Enumeration(self, tp: typedesc.Enumeration) -> None:
|
|
678
318
|
self.last_item_class = False
|
|
679
|
-
if tp.name:
|
|
680
|
-
print("# values for enumeration '%s'" % tp.name, file=self.stream)
|
|
681
|
-
else:
|
|
682
|
-
print("# values for unnamed enumeration", file=self.stream)
|
|
683
319
|
for item in tp.values:
|
|
684
320
|
self.generate(item)
|
|
685
321
|
if tp.name:
|
|
686
|
-
print("%s = c_int # enum" % tp.name, file=self.stream)
|
|
687
322
|
self.names.add(tp.name)
|
|
688
323
|
|
|
689
324
|
def Typedef(self, tp: typedesc.Typedef) -> None:
|
|
@@ -697,9 +332,11 @@ class CodeGenerator(object):
|
|
|
697
332
|
if definition in self.known_symbols:
|
|
698
333
|
self.declarations.add(tp.name, definition)
|
|
699
334
|
else:
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
335
|
+
if isinstance(tp.typ, typedesc.Enumeration):
|
|
336
|
+
self.enum_aliases[tp.name] = definition
|
|
337
|
+
else:
|
|
338
|
+
print(f"{tp.name} = {definition}", file=self.stream)
|
|
339
|
+
self.last_item_class = False
|
|
703
340
|
self.names.add(tp.name)
|
|
704
341
|
|
|
705
342
|
def FundamentalType(self, item: typedesc.FundamentalType) -> None:
|
|
@@ -823,11 +460,11 @@ class CodeGenerator(object):
|
|
|
823
460
|
# on COM interfaces:
|
|
824
461
|
if not methods:
|
|
825
462
|
try:
|
|
826
|
-
pack = calc_packing(body.struct, fields)
|
|
463
|
+
pack = packing.calc_packing(body.struct, fields)
|
|
827
464
|
if pack is not None:
|
|
828
465
|
self.last_item_class = False
|
|
829
466
|
print("%s._pack_ = %s" % (body.struct.name, pack), file=self.stream)
|
|
830
|
-
except PackingError as details:
|
|
467
|
+
except packing.PackingError as details:
|
|
831
468
|
# if packing fails, write a warning comment to the output.
|
|
832
469
|
import warnings
|
|
833
470
|
|
|
@@ -884,7 +521,7 @@ class CodeGenerator(object):
|
|
|
884
521
|
"# The size and alignment check for %s is skipped."
|
|
885
522
|
)
|
|
886
523
|
print(msg % body.struct.name, file=self.stream)
|
|
887
|
-
elif body.struct.name not in dont_assert_size:
|
|
524
|
+
elif body.struct.name not in packing.dont_assert_size:
|
|
888
525
|
print(file=self.stream)
|
|
889
526
|
size = body.struct.size // 8
|
|
890
527
|
print(
|
|
@@ -1015,14 +652,14 @@ class CodeGenerator(object):
|
|
|
1015
652
|
self.last_item_class = True
|
|
1016
653
|
|
|
1017
654
|
print("class %s(CoClass):" % coclass.name, file=self.stream)
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
print(self._to_docstring(doc), file=self.stream)
|
|
655
|
+
if coclass.doc:
|
|
656
|
+
print(self._to_docstring(coclass.doc), file=self.stream)
|
|
1021
657
|
print(" _reg_clsid_ = GUID(%r)" % coclass.clsid, file=self.stream)
|
|
1022
658
|
print(" _idlflags_ = %s" % coclass.idlflags, file=self.stream)
|
|
1023
659
|
if self.filename is not None:
|
|
1024
660
|
print(" _typelib_path_ = typelib_path", file=self.stream)
|
|
1025
|
-
# X print
|
|
661
|
+
# X print
|
|
662
|
+
# >> self.stream, "POINTER(%s).__ctypes_from_outparam__ = wrap" % coclass.name
|
|
1026
663
|
|
|
1027
664
|
libid = coclass.tlibattr.guid
|
|
1028
665
|
wMajor, wMinor = coclass.tlibattr.wMajorVerNum, coclass.tlibattr.wMinorVerNum
|
|
@@ -1033,23 +670,11 @@ class CodeGenerator(object):
|
|
|
1033
670
|
print(file=self.stream)
|
|
1034
671
|
print(file=self.stream)
|
|
1035
672
|
|
|
1036
|
-
for itf,
|
|
673
|
+
for itf, _ in coclass.interfaces:
|
|
1037
674
|
self.generate(itf.get_head())
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
for
|
|
1041
|
-
# item is (interface class, impltypeflags)
|
|
1042
|
-
if item[1] & 2: # IMPLTYPEFLAG_FSOURCE
|
|
1043
|
-
# source interface
|
|
1044
|
-
where = sources
|
|
1045
|
-
else:
|
|
1046
|
-
# sink interface
|
|
1047
|
-
where = implemented
|
|
1048
|
-
if item[1] & 1: # IMPLTYPEFLAG_FDEAULT
|
|
1049
|
-
# The default interface should be the first item on the list
|
|
1050
|
-
where.insert(0, self._to_type_name(item[0]))
|
|
1051
|
-
else:
|
|
1052
|
-
where.append(self._to_type_name(item[0]))
|
|
675
|
+
impl, src = typedesc.groupby_impltypeflags(coclass.interfaces)
|
|
676
|
+
implemented = [self._to_type_name(itf) for itf in impl]
|
|
677
|
+
sources = [self._to_type_name(itf) for itf in src]
|
|
1053
678
|
|
|
1054
679
|
if implemented:
|
|
1055
680
|
self.last_item_class = False
|
|
@@ -1066,11 +691,63 @@ class CodeGenerator(object):
|
|
|
1066
691
|
|
|
1067
692
|
self.names.add(coclass.name)
|
|
1068
693
|
|
|
694
|
+
def _is_interface_typedesc(
|
|
695
|
+
self, item: Any
|
|
696
|
+
) -> "comtypes.hints.TypeGuard[_InterfaceTypeDesc]":
|
|
697
|
+
return isinstance(
|
|
698
|
+
item,
|
|
699
|
+
(
|
|
700
|
+
typedesc.ComInterface,
|
|
701
|
+
typedesc.ComInterfaceHead,
|
|
702
|
+
typedesc.ComInterfaceBody,
|
|
703
|
+
typedesc.DispInterface,
|
|
704
|
+
typedesc.DispInterfaceHead,
|
|
705
|
+
typedesc.DispInterfaceBody,
|
|
706
|
+
),
|
|
707
|
+
)
|
|
708
|
+
|
|
709
|
+
def _define_interface(self, item: _InterfaceTypeDesc) -> None:
|
|
710
|
+
if isinstance(
|
|
711
|
+
item,
|
|
712
|
+
(
|
|
713
|
+
typedesc.ComInterfaceHead,
|
|
714
|
+
typedesc.ComInterfaceBody,
|
|
715
|
+
typedesc.DispInterfaceHead,
|
|
716
|
+
typedesc.DispInterfaceBody,
|
|
717
|
+
),
|
|
718
|
+
):
|
|
719
|
+
if self._is_known_interface(item.itf):
|
|
720
|
+
self.imports.add(item.itf.name, symbols=self.known_symbols)
|
|
721
|
+
self.done.add(item)
|
|
722
|
+
return
|
|
723
|
+
elif isinstance(item, (typedesc.ComInterface, typedesc.DispInterface)):
|
|
724
|
+
if self._is_known_interface(item):
|
|
725
|
+
self.imports.add(item.name, symbols=self.known_symbols)
|
|
726
|
+
self.done.add(item)
|
|
727
|
+
self.done.add(item.get_head())
|
|
728
|
+
self.done.add(item.get_body())
|
|
729
|
+
return
|
|
730
|
+
else:
|
|
731
|
+
raise TypeError
|
|
732
|
+
self.done.add(item) # to avoid infinite recursion.
|
|
733
|
+
mth = getattr(self, type(item).__name__)
|
|
734
|
+
mth(item)
|
|
735
|
+
|
|
1069
736
|
def ComInterface(self, itf: typedesc.ComInterface) -> None:
|
|
1070
737
|
self.generate(itf.get_head())
|
|
1071
738
|
self.generate(itf.get_body())
|
|
1072
739
|
self.names.add(itf.name)
|
|
1073
740
|
|
|
741
|
+
def _is_known_interface(
|
|
742
|
+
self, item: _UnionT[typedesc.ComInterface, typedesc.DispInterface]
|
|
743
|
+
) -> bool:
|
|
744
|
+
"""Returns whether an interface is statically defined in `comtypes`,
|
|
745
|
+
based on its name and iid.
|
|
746
|
+
"""
|
|
747
|
+
if item.name in self.known_interfaces:
|
|
748
|
+
return self.known_interfaces[item.name] == item.iid
|
|
749
|
+
return False
|
|
750
|
+
|
|
1074
751
|
def _is_enuminterface(self, itf: typedesc.ComInterface) -> bool:
|
|
1075
752
|
# Check if this is an IEnumXXX interface
|
|
1076
753
|
if not itf.name.startswith("IEnum"):
|
|
@@ -1082,14 +759,11 @@ class CodeGenerator(object):
|
|
|
1082
759
|
return True
|
|
1083
760
|
|
|
1084
761
|
def ComInterfaceHead(self, head: typedesc.ComInterfaceHead) -> None:
|
|
1085
|
-
if head.itf.name in self.known_symbols:
|
|
1086
|
-
return
|
|
1087
|
-
base = head.itf.base
|
|
1088
762
|
if head.itf.base is None:
|
|
1089
763
|
# we don't beed to generate IUnknown
|
|
1090
764
|
return
|
|
1091
|
-
self.generate(base.get_head())
|
|
1092
|
-
self.more.add(base)
|
|
765
|
+
self.generate(head.itf.base.get_head())
|
|
766
|
+
self.more.add(head.itf.base)
|
|
1093
767
|
basename = self._to_type_name(head.itf.base)
|
|
1094
768
|
|
|
1095
769
|
self.imports.add("comtypes", "GUID")
|
|
@@ -1101,9 +775,8 @@ class CodeGenerator(object):
|
|
|
1101
775
|
self.last_item_class = True
|
|
1102
776
|
|
|
1103
777
|
print("class %s(%s):" % (head.itf.name, basename), file=self.stream)
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
print(self._to_docstring(doc), file=self.stream)
|
|
778
|
+
if head.itf.doc:
|
|
779
|
+
print(self._to_docstring(head.itf.doc), file=self.stream)
|
|
1107
780
|
|
|
1108
781
|
print(" _case_insensitive_ = True", file=self.stream)
|
|
1109
782
|
print(" _iid_ = GUID(%r)" % head.itf.iid, file=self.stream)
|
|
@@ -1130,11 +803,11 @@ class CodeGenerator(object):
|
|
|
1130
803
|
print(" return item", file=self.stream)
|
|
1131
804
|
print(" raise IndexError(index)", file=self.stream)
|
|
1132
805
|
|
|
1133
|
-
|
|
1134
|
-
if
|
|
806
|
+
annotations = typeannotator.ComInterfaceMembersAnnotator(head.itf).generate()
|
|
807
|
+
if annotations:
|
|
1135
808
|
print(file=self.stream)
|
|
1136
809
|
print(" if TYPE_CHECKING: # commembers", file=self.stream)
|
|
1137
|
-
print(
|
|
810
|
+
print(annotations, file=self.stream)
|
|
1138
811
|
|
|
1139
812
|
print(file=self.stream)
|
|
1140
813
|
print(file=self.stream)
|
|
@@ -1250,19 +923,18 @@ class CodeGenerator(object):
|
|
|
1250
923
|
self.last_item_class = True
|
|
1251
924
|
|
|
1252
925
|
print("class %s(%s):" % (head.itf.name, basename), file=self.stream)
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
print(self._to_docstring(doc), file=self.stream)
|
|
926
|
+
if head.itf.doc:
|
|
927
|
+
print(self._to_docstring(head.itf.doc), file=self.stream)
|
|
1256
928
|
print(" _case_insensitive_ = True", file=self.stream)
|
|
1257
929
|
print(" _iid_ = GUID(%r)" % head.itf.iid, file=self.stream)
|
|
1258
930
|
print(" _idlflags_ = %s" % head.itf.idlflags, file=self.stream)
|
|
1259
931
|
print(" _methods_ = []", file=self.stream)
|
|
1260
932
|
|
|
1261
|
-
|
|
1262
|
-
if
|
|
933
|
+
annotations = typeannotator.DispInterfaceMembersAnnotator(head.itf).generate()
|
|
934
|
+
if annotations:
|
|
1263
935
|
print(file=self.stream)
|
|
1264
936
|
print(" if TYPE_CHECKING: # dispmembers", file=self.stream)
|
|
1265
|
-
print(
|
|
937
|
+
print(annotations, file=self.stream)
|
|
1266
938
|
|
|
1267
939
|
print(file=self.stream)
|
|
1268
940
|
print(file=self.stream)
|
|
@@ -1304,7 +976,7 @@ class CodeGenerator(object):
|
|
|
1304
976
|
if __debug__ and m.doc:
|
|
1305
977
|
self.imports.add("comtypes", "helpstring")
|
|
1306
978
|
gen = ComMethodGenerator(m, isdual)
|
|
1307
|
-
print(gen.generate(), file=self.stream
|
|
979
|
+
print(gen.generate(), file=self.stream)
|
|
1308
980
|
self.last_item_class = False
|
|
1309
981
|
for typ, _, _, default in m.arguments:
|
|
1310
982
|
if isinstance(typ, typedesc.ComInterface):
|
|
@@ -1322,7 +994,7 @@ class CodeGenerator(object):
|
|
|
1322
994
|
if __debug__ and m.doc:
|
|
1323
995
|
self.imports.add("comtypes", "helpstring")
|
|
1324
996
|
gen = DispMethodGenerator(m)
|
|
1325
|
-
print(gen.generate(), file=self.stream
|
|
997
|
+
print(gen.generate(), file=self.stream)
|
|
1326
998
|
self.last_item_class = False
|
|
1327
999
|
for _, _, _, default in m.arguments:
|
|
1328
1000
|
if default is not None:
|
|
@@ -1334,253 +1006,5 @@ class CodeGenerator(object):
|
|
|
1334
1006
|
if __debug__ and prop.doc:
|
|
1335
1007
|
self.imports.add("comtypes", "helpstring")
|
|
1336
1008
|
gen = DispPropertyGenerator(prop)
|
|
1337
|
-
print(gen.generate(), file=self.stream
|
|
1009
|
+
print(gen.generate(), file=self.stream)
|
|
1338
1010
|
self.last_item_class = False
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
class TypeNamer(object):
|
|
1342
|
-
def __call__(self, t: Any) -> str:
|
|
1343
|
-
# Return a string, containing an expression which can be used
|
|
1344
|
-
# to refer to the type. Assumes the 'from ctypes import *'
|
|
1345
|
-
# namespace is available.
|
|
1346
|
-
if isinstance(t, typedesc.SAFEARRAYType):
|
|
1347
|
-
return "_midlSAFEARRAY(%s)" % self(t.typ)
|
|
1348
|
-
# if isinstance(t, typedesc.CoClass):
|
|
1349
|
-
# return "%s._com_interfaces_[0]" % t.name
|
|
1350
|
-
if isinstance(t, typedesc.Typedef):
|
|
1351
|
-
return t.name
|
|
1352
|
-
if isinstance(t, typedesc.PointerType):
|
|
1353
|
-
_t, pcnt = self._inspect_PointerType(t)
|
|
1354
|
-
return "%s%s%s" % ("POINTER(" * pcnt, self(_t), ")" * pcnt)
|
|
1355
|
-
elif isinstance(t, typedesc.ArrayType):
|
|
1356
|
-
return "%s * %s" % (self(t.typ), int(t.max) + 1)
|
|
1357
|
-
elif isinstance(t, typedesc.FunctionType):
|
|
1358
|
-
args = [self(x) for x in [t.returns] + list(t.iterArgTypes())]
|
|
1359
|
-
if "__stdcall__" in t.attributes:
|
|
1360
|
-
return "WINFUNCTYPE(%s)" % ", ".join(args)
|
|
1361
|
-
else:
|
|
1362
|
-
return "CFUNCTYPE(%s)" % ", ".join(args)
|
|
1363
|
-
elif isinstance(t, typedesc.CvQualifiedType):
|
|
1364
|
-
# const and volatile are ignored
|
|
1365
|
-
return "%s" % self(t.typ)
|
|
1366
|
-
elif isinstance(t, typedesc.FundamentalType):
|
|
1367
|
-
return ctypes_names[t.name]
|
|
1368
|
-
elif isinstance(t, typedesc.Structure):
|
|
1369
|
-
return t.name
|
|
1370
|
-
elif isinstance(t, typedesc.Enumeration):
|
|
1371
|
-
if t.name:
|
|
1372
|
-
return t.name
|
|
1373
|
-
return "c_int" # enums are integers
|
|
1374
|
-
elif isinstance(t, typedesc.EnumValue):
|
|
1375
|
-
if keyword.iskeyword(t.name):
|
|
1376
|
-
return t.name + "_"
|
|
1377
|
-
return t.name
|
|
1378
|
-
elif isinstance(t, typedesc.External):
|
|
1379
|
-
# t.symbol_name - symbol to generate
|
|
1380
|
-
# t.tlib - the ITypeLib pointer to the typelibrary containing the symbols definition
|
|
1381
|
-
modname = name_wrapper_module(t.tlib)
|
|
1382
|
-
return "%s.%s" % (modname, t.symbol_name)
|
|
1383
|
-
return t.name
|
|
1384
|
-
|
|
1385
|
-
def _inspect_PointerType(
|
|
1386
|
-
self, t: typedesc.PointerType, count: int = 0
|
|
1387
|
-
) -> Tuple[Any, int]:
|
|
1388
|
-
if ASSUME_STRINGS:
|
|
1389
|
-
x = get_real_type(t.typ)
|
|
1390
|
-
if isinstance(x, typedesc.FundamentalType):
|
|
1391
|
-
if x.name == "char":
|
|
1392
|
-
return typedesc.Typedef("STRING", x), count
|
|
1393
|
-
elif x.name == "wchar_t":
|
|
1394
|
-
return typedesc.Typedef("WSTRING", x), count
|
|
1395
|
-
if isinstance(t.typ, typedesc.FunctionType):
|
|
1396
|
-
return t.typ, count
|
|
1397
|
-
if isinstance(t.typ, typedesc.FundamentalType):
|
|
1398
|
-
if t.typ.name == "void":
|
|
1399
|
-
return typedesc.Typedef("c_void_p", t.typ), count
|
|
1400
|
-
if isinstance(t.typ, typedesc.PointerType):
|
|
1401
|
-
return self._inspect_PointerType(t.typ, count + 1)
|
|
1402
|
-
return t.typ, count + 1
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
class ImportedNamespaces(object):
|
|
1406
|
-
def __init__(self):
|
|
1407
|
-
self.data = {}
|
|
1408
|
-
|
|
1409
|
-
def add(self, name1, name2=None, symbols=None):
|
|
1410
|
-
"""Adds a namespace will be imported.
|
|
1411
|
-
|
|
1412
|
-
Examples:
|
|
1413
|
-
>>> imports = ImportedNamespaces()
|
|
1414
|
-
>>> imports.add('datetime')
|
|
1415
|
-
>>> imports.add('ctypes', '*')
|
|
1416
|
-
>>> imports.add('decimal', 'Decimal')
|
|
1417
|
-
>>> imports.add('GUID', symbols={'GUID': 'comtypes'})
|
|
1418
|
-
>>> for name in ('COMMETHOD', 'DISPMETHOD', 'IUnknown', 'dispid',
|
|
1419
|
-
... 'CoClass', 'BSTR', 'DISPPROPERTY'):
|
|
1420
|
-
... imports.add('comtypes', name)
|
|
1421
|
-
>>> imports.add('ctypes.wintypes')
|
|
1422
|
-
>>> print(imports.getvalue())
|
|
1423
|
-
from ctypes import *
|
|
1424
|
-
import datetime
|
|
1425
|
-
from decimal import Decimal
|
|
1426
|
-
from comtypes import (
|
|
1427
|
-
BSTR, CoClass, COMMETHOD, dispid, DISPMETHOD, DISPPROPERTY, GUID,
|
|
1428
|
-
IUnknown
|
|
1429
|
-
)
|
|
1430
|
-
import ctypes.wintypes
|
|
1431
|
-
>>> assert imports.get_symbols() == {
|
|
1432
|
-
... 'Decimal', 'GUID', 'COMMETHOD', 'DISPMETHOD', 'IUnknown',
|
|
1433
|
-
... 'dispid', 'CoClass', 'BSTR', 'DISPPROPERTY'
|
|
1434
|
-
... }
|
|
1435
|
-
"""
|
|
1436
|
-
if name2 is None:
|
|
1437
|
-
import_ = name1
|
|
1438
|
-
if not symbols:
|
|
1439
|
-
self.data[import_] = None
|
|
1440
|
-
return
|
|
1441
|
-
from_ = symbols[import_]
|
|
1442
|
-
else:
|
|
1443
|
-
from_, import_ = name1, name2
|
|
1444
|
-
self.data[import_] = from_
|
|
1445
|
-
|
|
1446
|
-
def __contains__(self, item):
|
|
1447
|
-
"""Returns item has already added.
|
|
1448
|
-
|
|
1449
|
-
Examples:
|
|
1450
|
-
>>> imports = ImportedNamespaces()
|
|
1451
|
-
>>> imports.add('datetime')
|
|
1452
|
-
>>> imports.add('ctypes', '*')
|
|
1453
|
-
>>> 'datetime' in imports
|
|
1454
|
-
True
|
|
1455
|
-
>>> ('ctypes', '*') in imports
|
|
1456
|
-
True
|
|
1457
|
-
>>> 'os' in imports
|
|
1458
|
-
False
|
|
1459
|
-
>>> 'ctypes' in imports
|
|
1460
|
-
False
|
|
1461
|
-
>>> ('ctypes', 'c_int') in imports
|
|
1462
|
-
False
|
|
1463
|
-
"""
|
|
1464
|
-
if isinstance(item, tuple):
|
|
1465
|
-
from_, import_ = item
|
|
1466
|
-
else:
|
|
1467
|
-
from_, import_ = None, item
|
|
1468
|
-
if import_ in self.data:
|
|
1469
|
-
return self.data[import_] == from_
|
|
1470
|
-
return False
|
|
1471
|
-
|
|
1472
|
-
def get_symbols(self) -> Set[str]:
|
|
1473
|
-
names = set()
|
|
1474
|
-
for key, val in self.data.items():
|
|
1475
|
-
if val is None or key == "*":
|
|
1476
|
-
continue
|
|
1477
|
-
names.add(key)
|
|
1478
|
-
return names
|
|
1479
|
-
|
|
1480
|
-
def _make_line(self, from_, imports):
|
|
1481
|
-
import_ = ", ".join(imports)
|
|
1482
|
-
code = "from %s import %s" % (from_, import_)
|
|
1483
|
-
if len(code) <= 80:
|
|
1484
|
-
return code
|
|
1485
|
-
wrapper = textwrap.TextWrapper(
|
|
1486
|
-
subsequent_indent=" ", initial_indent=" ", break_long_words=False
|
|
1487
|
-
)
|
|
1488
|
-
import_ = "\n".join(wrapper.wrap(import_))
|
|
1489
|
-
code = "from %s import (\n%s\n)" % (from_, import_)
|
|
1490
|
-
return code
|
|
1491
|
-
|
|
1492
|
-
def getvalue(self):
|
|
1493
|
-
ns = {}
|
|
1494
|
-
lines = []
|
|
1495
|
-
for key, val in self.data.items():
|
|
1496
|
-
if val is None:
|
|
1497
|
-
ns[key] = val
|
|
1498
|
-
elif key == "*":
|
|
1499
|
-
lines.append("from %s import *" % val)
|
|
1500
|
-
else:
|
|
1501
|
-
ns.setdefault(val, set()).add(key)
|
|
1502
|
-
for key, val in ns.items():
|
|
1503
|
-
if val is None:
|
|
1504
|
-
lines.append("import %s" % key)
|
|
1505
|
-
else:
|
|
1506
|
-
names = sorted(val, key=lambda s: s.lower())
|
|
1507
|
-
lines.append(self._make_line(key, names))
|
|
1508
|
-
return "\n".join(lines)
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
class DeclaredNamespaces(object):
|
|
1512
|
-
def __init__(self):
|
|
1513
|
-
self.data = {}
|
|
1514
|
-
|
|
1515
|
-
def add(self, alias, definition, comment=None):
|
|
1516
|
-
"""Adds a namespace will be declared.
|
|
1517
|
-
|
|
1518
|
-
Examples:
|
|
1519
|
-
>>> declarations = DeclaredNamespaces()
|
|
1520
|
-
>>> declarations.add('STRING', 'c_char_p')
|
|
1521
|
-
>>> declarations.add('_lcid', '0', 'change this if required')
|
|
1522
|
-
>>> print(declarations.getvalue())
|
|
1523
|
-
STRING = c_char_p
|
|
1524
|
-
_lcid = 0 # change this if required
|
|
1525
|
-
>>> assert declarations.get_symbols() == {
|
|
1526
|
-
... 'STRING', '_lcid'
|
|
1527
|
-
... }
|
|
1528
|
-
"""
|
|
1529
|
-
self.data[(alias, definition)] = comment
|
|
1530
|
-
|
|
1531
|
-
def get_symbols(self) -> Set[str]:
|
|
1532
|
-
names = set()
|
|
1533
|
-
for alias, _ in self.data.keys():
|
|
1534
|
-
names.add(alias)
|
|
1535
|
-
return names
|
|
1536
|
-
|
|
1537
|
-
def getvalue(self):
|
|
1538
|
-
lines = []
|
|
1539
|
-
for (alias, definition), comment in self.data.items():
|
|
1540
|
-
code = "%s = %s" % (alias, definition)
|
|
1541
|
-
if comment:
|
|
1542
|
-
code = code + " # %s" % comment
|
|
1543
|
-
lines.append(code)
|
|
1544
|
-
return "\n".join(lines)
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
class EnumerationNamespaces(object):
|
|
1548
|
-
def __init__(self):
|
|
1549
|
-
self.data: Dict[str, List[Tuple[str, int]]] = {}
|
|
1550
|
-
|
|
1551
|
-
def add(self, enum_name: str, member_name: str, value: int) -> None:
|
|
1552
|
-
"""Adds a namespace will be enumeration and its member.
|
|
1553
|
-
|
|
1554
|
-
Examples:
|
|
1555
|
-
>>> enums = EnumerationNamespaces()
|
|
1556
|
-
>>> enums.add('Foo', 'ham', 1)
|
|
1557
|
-
>>> enums.add('Foo', 'spam', 2)
|
|
1558
|
-
>>> enums.add('Bar', 'bacon', 3)
|
|
1559
|
-
>>> assert 'Foo' in enums
|
|
1560
|
-
>>> assert 'Baz' not in enums
|
|
1561
|
-
>>> print(enums.getvalue()) # <BLANKLINE> is necessary for doctest
|
|
1562
|
-
class Foo(IntFlag):
|
|
1563
|
-
ham = 1
|
|
1564
|
-
spam = 2
|
|
1565
|
-
<BLANKLINE>
|
|
1566
|
-
<BLANKLINE>
|
|
1567
|
-
class Bar(IntFlag):
|
|
1568
|
-
bacon = 3
|
|
1569
|
-
"""
|
|
1570
|
-
self.data.setdefault(enum_name, []).append((member_name, value))
|
|
1571
|
-
|
|
1572
|
-
def __contains__(self, item: str) -> bool:
|
|
1573
|
-
return item in self.data
|
|
1574
|
-
|
|
1575
|
-
def get_symbols(self) -> Set[str]:
|
|
1576
|
-
return set(self.data)
|
|
1577
|
-
|
|
1578
|
-
def getvalue(self) -> str:
|
|
1579
|
-
blocks = []
|
|
1580
|
-
for enum_name, enum_members in self.data.items():
|
|
1581
|
-
lines = []
|
|
1582
|
-
lines.append(f"class {enum_name}(IntFlag):")
|
|
1583
|
-
for member_name, value in enum_members:
|
|
1584
|
-
lines.append(f" {member_name} = {value}")
|
|
1585
|
-
blocks.append("\n".join(lines))
|
|
1586
|
-
return "\n\n\n".join(blocks)
|