comtypes 1.1.14__zip → 1.2.1__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.
Files changed (106) hide show
  1. {comtypes-1.1.14 → comtypes-1.2.1}/CHANGES.txt +37 -0
  2. comtypes-1.2.1/PKG-INFO +79 -0
  3. comtypes-1.2.1/README.md +59 -0
  4. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/__init__.py +302 -555
  5. comtypes-1.2.1/comtypes/_memberspec.py +520 -0
  6. comtypes-1.2.1/comtypes/_npsupport.py +143 -0
  7. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/automation.py +99 -11
  8. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/client/__init__.py +80 -26
  9. comtypes-1.2.1/comtypes/client/_generate.py +274 -0
  10. comtypes-1.2.1/comtypes/hints.pyi +26 -0
  11. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/persist.py +14 -0
  12. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/safearray.py +22 -21
  13. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/test/__init__.py +0 -7
  14. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/test/test_client.py +35 -0
  15. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/test/test_dict.py +0 -4
  16. comtypes-1.2.1/comtypes/test/test_npsupport.py +343 -0
  17. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/test/test_safearray.py +2 -235
  18. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/test/test_variant.py +6 -59
  19. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/tools/codegenerator.py +454 -337
  20. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/tools/tlbparser.py +56 -75
  21. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/tools/typedesc.py +31 -3
  22. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/tools/typedesc_base.py +28 -1
  23. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/typeinfo.py +291 -121
  24. comtypes-1.2.1/comtypes.egg-info/PKG-INFO +79 -0
  25. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes.egg-info/SOURCES.txt +4 -1
  26. {comtypes-1.1.14 → comtypes-1.2.1}/setup.cfg +0 -1
  27. {comtypes-1.1.14 → comtypes-1.2.1}/setup.py +15 -8
  28. comtypes-1.1.14/PKG-INFO +0 -50
  29. comtypes-1.1.14/README.md +0 -31
  30. comtypes-1.1.14/comtypes/client/_generate.py +0 -257
  31. comtypes-1.1.14/comtypes/npsupport.py +0 -125
  32. comtypes-1.1.14/comtypes.egg-info/PKG-INFO +0 -50
  33. {comtypes-1.1.14 → comtypes-1.2.1}/LICENSE.txt +0 -0
  34. {comtypes-1.1.14 → comtypes-1.2.1}/MANIFEST.in +0 -0
  35. {comtypes-1.1.14 → comtypes-1.2.1}/clear_comtypes_cache.py +0 -0
  36. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/GUID.py +0 -0
  37. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/_comobject.py +0 -0
  38. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/_meta.py +0 -0
  39. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/_safearray.py +0 -0
  40. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/client/_code_cache.py +0 -0
  41. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/client/_constants.py +0 -0
  42. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/client/_events.py +0 -0
  43. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/client/dynamic.py +0 -0
  44. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/client/lazybind.py +0 -0
  45. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/connectionpoints.py +0 -0
  46. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/errorinfo.py +0 -0
  47. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/git.py +0 -0
  48. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/hresult.py +0 -0
  49. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/logutil.py +0 -0
  50. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/messageloop.py +0 -0
  51. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/patcher.py +0 -0
  52. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/server/__init__.py +0 -0
  53. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/server/automation.py +0 -0
  54. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/server/connectionpoints.py +0 -0
  55. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/server/inprocserver.py +0 -0
  56. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/server/localserver.py +0 -0
  57. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/server/register.py +0 -0
  58. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/server/w_getopt.py +0 -0
  59. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/shelllink.py +0 -0
  60. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/test/TestComServer.idl +0 -0
  61. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/test/TestComServer.py +0 -0
  62. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/test/TestComServer.tlb +0 -0
  63. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/test/TestDispServer.idl +0 -0
  64. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/test/TestDispServer.py +0 -0
  65. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/test/TestDispServer.tlb +0 -0
  66. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/test/find_memleak.py +0 -0
  67. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/test/mylib.idl +0 -0
  68. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/test/mytypelib.idl +0 -0
  69. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/test/runtests.py +0 -0
  70. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/test/setup.py +0 -0
  71. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/test/test_BSTR.py +0 -0
  72. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/test/test_DISPPARAMS.py +0 -0
  73. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/test/test_GUID.py +0 -0
  74. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/test/test_QueryService.py +0 -0
  75. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/test/test_agilent.py +0 -0
  76. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/test/test_avmc.py +0 -0
  77. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/test/test_basic.py +0 -0
  78. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/test/test_casesensitivity.py +0 -0
  79. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/test/test_collections.py +0 -0
  80. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/test/test_comserver.py +0 -0
  81. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/test/test_createwrappers.py +0 -0
  82. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/test/test_dispinterface.py +0 -0
  83. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/test/test_dyndispatch.py +0 -0
  84. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/test/test_excel.py +0 -0
  85. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/test/test_findgendir.py +0 -0
  86. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/test/test_getactiveobj.py +0 -0
  87. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/test/test_ie.py +0 -0
  88. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/test/test_jscript.js +0 -0
  89. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/test/test_msscript.py +0 -0
  90. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/test/test_outparam.py +0 -0
  91. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/test/test_propputref.py +0 -0
  92. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/test/test_pump_events.py +0 -0
  93. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/test/test_sapi.py +0 -0
  94. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/test/test_server.py +0 -0
  95. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/test/test_showevents.py +0 -0
  96. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/test/test_subinterface.py +0 -0
  97. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/test/test_typeinfo.py +0 -0
  98. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/test/test_urlhistory.py +0 -0
  99. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/test/test_win32com_interop.py +0 -0
  100. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/test/test_wmi.py +0 -0
  101. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/test/test_word.py +0 -0
  102. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/tools/__init__.py +0 -0
  103. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/util.py +0 -0
  104. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes/viewobject.py +0 -0
  105. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes.egg-info/dependency_links.txt +0 -0
  106. {comtypes-1.1.14 → comtypes-1.2.1}/comtypes.egg-info/top_level.txt +0 -0
@@ -1,24 +1,29 @@
1
1
  # Code generator to generate code for everything contained in COM type
2
2
  # libraries.
3
3
  from __future__ import print_function
4
+ import ctypes
5
+ import keyword
6
+ import logging
4
7
  import os
5
8
  import sys
9
+ import textwrap
6
10
  if sys.version_info >= (3, 0):
7
11
  import io
8
12
  else:
9
13
  import cStringIO as io
10
- import keyword
11
- import ctypes
12
- import textwrap
13
14
 
14
- from comtypes.tools import typedesc
15
15
  import comtypes
16
- import comtypes.client
17
- import comtypes.client._generate
16
+ from comtypes import TYPE_CHECKING, typeinfo
17
+ from comtypes.tools import tlbparser, typedesc
18
+
19
+ if TYPE_CHECKING:
20
+ from typing import (
21
+ Any, Dict, Iterator, List, Optional, Tuple, Union as _UnionT,
22
+ )
23
+
18
24
 
19
25
  version = comtypes.__version__
20
26
 
21
- import logging
22
27
  logger = logging.getLogger(__name__)
23
28
 
24
29
  __warn_on_munge__ = __debug__
@@ -158,17 +163,273 @@ def storage(t):
158
163
 
159
164
  ################################################################
160
165
 
161
- class Generator(object):
166
+ def name_wrapper_module(tlib):
167
+ """Determine the name of a typelib wrapper module"""
168
+ libattr = tlib.GetLibAttr()
169
+ modname = "_%s_%s_%s_%s" % \
170
+ (str(libattr.guid)[1:-1].replace("-", "_"),
171
+ libattr.lcid,
172
+ libattr.wMajorVerNum,
173
+ libattr.wMinorVerNum)
174
+ return "comtypes.gen.%s" % modname
175
+
176
+
177
+ def name_friendly_module(tlib):
178
+ """Determine the friendly-name of a typelib module.
179
+ If cannot get friendly-name from typelib, returns `None`.
180
+ """
181
+ try:
182
+ modulename = tlib.GetDocumentation(-1)[0]
183
+ except comtypes.COMError:
184
+ return
185
+ return "comtypes.gen.%s" % modulename
186
+
187
+ ################################################################
188
+
189
+
190
+ def _to_arg_definition(type_name, arg_name, idlflags, default):
191
+ # type: (str, str, List[str], _UnionT[lcid, Any, None]) -> str
192
+ if default is not None:
193
+ elms = (idlflags, type_name, arg_name, default)
194
+ code = " (%r, %s, '%s', %r)" % elms
195
+ if len(code) > 80:
196
+ code = (
197
+ " (\n"
198
+ " %r,\n"
199
+ " %s,\n"
200
+ " '%s',\n"
201
+ " %r\n"
202
+ " )"
203
+ ) % elms
204
+ else:
205
+ elms = (idlflags, type_name, arg_name)
206
+ code = " (%r, %s, '%s')" % elms
207
+ if len(code) > 80:
208
+ code = (
209
+ " (\n"
210
+ " %r,\n"
211
+ " %s,\n"
212
+ " '%s',\n"
213
+ " )"
214
+ ) % elms
215
+ return code
216
+
217
+
218
+ class ComMethodGenerator(object):
219
+ def __init__(self, m, isdual):
220
+ # type: (typedesc.ComMethod, bool) -> None
221
+ self._m = m
222
+ self._isdual = isdual
223
+ self._stream = io.StringIO()
224
+ self._to_type_name = TypeNamer()
225
+
226
+ def generate(self):
227
+ # () -> str
228
+ if not self._m.arguments:
229
+ self._make_noargs()
230
+ else:
231
+ self._make_withargs()
232
+ return self._stream.getvalue()
233
+
234
+ def _get_common_elms(self):
235
+ # type: () -> Tuple[List[_UnionT[str, dispid, helpstring]], str, str]
236
+ idlflags = [] # type: List[_UnionT[str, dispid, helpstring]]
237
+ if self._isdual:
238
+ idlflags.append(dispid(self._m.memid))
239
+ idlflags.extend(self._m.idlflags)
240
+ else: # We don't include the dispid for non-dispatch COM interfaces
241
+ idlflags.extend(self._m.idlflags)
242
+ if __debug__ and self._m.doc:
243
+ idlflags.insert(1, helpstring(self._m.doc))
244
+ type_name = self._to_type_name(self._m.returns)
245
+ return (idlflags, type_name, self._m.name)
246
+
247
+ def _make_noargs(self):
248
+ # type: () -> None
249
+ elms = self._get_common_elms()
250
+ code = " COMMETHOD(%r, %s, '%s')," % elms
251
+ if len(code) > 80:
252
+ code = (
253
+ " COMMETHOD(\n"
254
+ " %r,\n"
255
+ " %s,\n"
256
+ " '%s',\n"
257
+ " ),"
258
+ ) % elms
259
+ print(code, file=self._stream)
260
+
261
+ def _make_withargs(self):
262
+ # type: () -> None
263
+ code = (
264
+ " COMMETHOD(\n"
265
+ " %r,\n"
266
+ " %s,\n"
267
+ " '%s',"
268
+ ) % self._get_common_elms()
269
+ print(code, file=self._stream)
270
+ arglist = [_to_arg_definition(*i) for i in self._iter_args()]
271
+ print(",\n".join(arglist), file=self._stream)
272
+ print(" ),", file=self._stream)
273
+
274
+ def _iter_args(self):
275
+ # type: () -> Iterator[Tuple[str, str, List[str], _UnionT[lcid, Any, None]]]
276
+ for typ, arg_name, _f, _defval in self._m.arguments:
277
+ ###########################################################
278
+ # IDL files that contain 'open arrays' or 'conformant
279
+ # varying arrays' method parameters are strange.
280
+ # These arrays have both a 'size_is()' and
281
+ # 'length_is()' attribute, like this example from
282
+ # dia2.idl (in the DIA SDK):
283
+ #
284
+ # interface IDiaSymbol: IUnknown {
285
+ # ...
286
+ # HRESULT get_dataBytes(
287
+ # [in] DWORD cbData,
288
+ # [out] DWORD *pcbData,
289
+ # [out, size_is(cbData),
290
+ # length_is(*pcbData)] BYTE data[]
291
+ # );
292
+ #
293
+ # The really strange thing is that the decompiled type
294
+ # library then contains this declaration, which declares
295
+ # the interface itself as [out] method parameter:
296
+ #
297
+ # interface IDiaSymbol: IUnknown {
298
+ # ...
299
+ # HRESULT _stdcall get_dataBytes(
300
+ # [in] unsigned long cbData,
301
+ # [out] unsigned long* pcbData,
302
+ # [out] IDiaSymbol data);
303
+ #
304
+ # Of course, comtypes does not accept a COM interface
305
+ # as method parameter; so replace the parameter type
306
+ # with the comtypes spelling of 'unsigned char *', and
307
+ # mark the parameter as [in, out], so the IDL
308
+ # equivalent would be like this:
309
+ #
310
+ # interface IDiaSymbol: IUnknown {
311
+ # ...
312
+ # HRESULT _stdcall get_dataBytes(
313
+ # [in] unsigned long cbData,
314
+ # [out] unsigned long* pcbData,
315
+ # [in, out] BYTE data[]);
316
+ ###########################################################
317
+ idlflags = list(_f) # shallow copy to avoid side effects
318
+ if isinstance(typ, typedesc.ComInterface):
319
+ type_name = "OPENARRAY"
320
+ if 'in' not in idlflags:
321
+ idlflags.append('in')
322
+ else:
323
+ type_name = self._to_type_name(typ)
324
+ if 'lcid' in idlflags:# and 'in' in idlflags:
325
+ default = lcid
326
+ else:
327
+ default = _defval
328
+ yield (type_name, arg_name, idlflags, default)
329
+
330
+
331
+ class DispMethodGenerator(object):
332
+ def __init__(self, m):
333
+ # type: (typedesc.DispMethod) -> None
334
+ self._m = m
335
+ self._stream = io.StringIO()
336
+ self._to_type_name = TypeNamer()
162
337
 
163
- def __init__(self, ofi, known_symbols=None):
164
- self.output = ofi
338
+ def generate(self):
339
+ # () -> str
340
+ if not self._m.arguments:
341
+ self._make_noargs()
342
+ else:
343
+ self._make_withargs()
344
+ return self._stream.getvalue()
345
+
346
+ def _get_common_elms(self):
347
+ # type: () -> Tuple[List[_UnionT[str, dispid, helpstring]], str, str]
348
+ idlflags = [] # type: List[_UnionT[str, dispid, helpstring]]
349
+ idlflags.append(dispid(self._m.dispid))
350
+ idlflags.extend(self._m.idlflags)
351
+ if __debug__ and self._m.doc:
352
+ idlflags.insert(1, helpstring(self._m.doc))
353
+ type_name = self._to_type_name(self._m.returns)
354
+ return (idlflags, type_name, self._m.name)
355
+
356
+ def _make_noargs(self):
357
+ # type: () -> None
358
+ elms = self._get_common_elms()
359
+ code = " DISPMETHOD(%r, %s, '%s')," % elms
360
+ if len(code) > 80:
361
+ code = (
362
+ " DISPMETHOD(\n"
363
+ " %r,\n"
364
+ " %s,\n"
365
+ " '%s',\n"
366
+ " ),"
367
+ ) % elms
368
+ print(code, file=self._stream)
369
+
370
+ def _make_withargs(self):
371
+ # type: () -> None
372
+ code = (
373
+ " DISPMETHOD(\n"
374
+ " %r,\n"
375
+ " %s,\n"
376
+ " '%s',"
377
+ ) % self._get_common_elms()
378
+ print(code, file=self._stream)
379
+ arglist = [_to_arg_definition(*i) for i in self._iter_args()]
380
+ print(",\n".join(arglist), file=self._stream)
381
+ print(" ),", file=self._stream)
382
+
383
+ def _iter_args(self):
384
+ # type: () -> Iterator[Tuple[str, str, List[str], _UnionT[lcid, Any, None]]]
385
+ for typ, arg_name, idlflags, default in self._m.arguments:
386
+ type_name = self._to_type_name(typ)
387
+ yield (type_name, arg_name, idlflags, default)
388
+
389
+
390
+ class DispPropertyGenerator(object):
391
+ def __init__(self, m):
392
+ # type: (typedesc.DispProperty) -> None
393
+ self._m = m
394
+ self._to_type_name = TypeNamer()
395
+
396
+ def generate(self):
397
+ # () -> str
398
+ elms = self._get_common_elms()
399
+ code = " DISPPROPERTY(%r, %s, '%s')," % elms
400
+ if len(code) > 80:
401
+ code = (
402
+ " DISPPROPERTY(\n"
403
+ " %r,\n"
404
+ " %s,\n"
405
+ " '%s'\n"
406
+ " ),"
407
+ ) % elms
408
+ return code + "\n"
409
+
410
+ def _get_common_elms(self):
411
+ # type: () -> Tuple[List[_UnionT[str, dispid, helpstring]], str, str]
412
+ idlflags = [] # type: List[_UnionT[str, dispid, helpstring]]
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)
419
+
420
+
421
+ class CodeGenerator(object):
422
+
423
+ def __init__(self, known_symbols=None):
165
424
  self.stream = io.StringIO()
166
425
  self.imports = ImportedNamespaces()
167
426
  self.declarations = DeclaredNamespaces()
427
+ self._to_type_name = TypeNamer()
168
428
  self.known_symbols = known_symbols or {}
169
429
 
170
430
  self.done = set() # type descriptions that have been generated
171
431
  self.names = set() # names that have been generated
432
+ self.externals = [] # typelibs imported to generated module
172
433
  self.last_item_class = False
173
434
 
174
435
  def generate(self, item):
@@ -248,8 +509,8 @@ class Generator(object):
248
509
 
249
510
  if filename is not None:
250
511
  # get full path to DLL first (os.stat can't work with relative DLL paths properly)
251
- loaded_typelib = comtypes.typeinfo.LoadTypeLib(filename)
252
- full_filename = comtypes.tools.tlbparser.get_tlib_filename(
512
+ loaded_typelib = typeinfo.LoadTypeLib(filename)
513
+ full_filename = tlbparser.get_tlib_filename(
253
514
  loaded_typelib)
254
515
 
255
516
  while full_filename and not os.path.exists(full_filename):
@@ -281,88 +542,29 @@ class Generator(object):
281
542
  if tlib_mtime is not None:
282
543
  logger.debug("filename: \"%s\": tlib_mtime: %s", filename, tlib_mtime)
283
544
  self.imports.add('comtypes', '_check_version')
284
-
545
+ output = io.StringIO()
285
546
  if filename is not None:
286
547
  # Hm, what is the CORRECT encoding?
287
- print("# -*- coding: mbcs -*-", file=self.output)
288
- print(file=self.output)
289
- print(self.imports.getvalue(), file=self.output)
290
- print(file=self.output)
291
- print(self.declarations.getvalue(), file=self.output)
292
- print(file=self.output)
293
- print(self.stream.getvalue(), file=self.output)
294
- dunder_all = "__all__ = [%s]" % ", ".join(repr(str(n)) for n in self.names)
548
+ print("# -*- coding: mbcs -*-", file=output)
549
+ print(file=output)
550
+ print(self.imports.getvalue(), file=output)
551
+ print(file=output)
552
+ print(self.declarations.getvalue(), file=output)
553
+ print(file=output)
554
+ print(self.stream.getvalue(), file=output)
555
+ names = ", ".join(repr(str(n)) for n in self.names)
556
+ dunder_all = "__all__ = [%s]" % names
295
557
  if len(dunder_all) > 80:
296
558
  wrapper = textwrap.TextWrapper(subsequent_indent=" ",
297
559
  initial_indent=" ",
298
560
  break_long_words=False)
299
- names = ", ".join(repr(str(n)) for n in self.names)
300
561
  dunder_all = "__all__ = [\n%s\n]" % "\n".join(wrapper.wrap(names))
301
- print(dunder_all, file=self.output)
302
- print(file=self.output)
562
+ print(dunder_all, file=output)
563
+ print(file=output)
303
564
  if tlib_mtime is not None:
304
565
  print("_check_version(%r, %f)" % (version, tlib_mtime),
305
- file=self.output)
306
-
307
- return loops
308
-
309
- def type_name(self, t):
310
- # Return a string, containing an expression which can be used
311
- # to refer to the type. Assumes the 'from ctypes import *'
312
- # namespace is available.
313
- if isinstance(t, typedesc.SAFEARRAYType):
314
- return "_midlSAFEARRAY(%s)" % self.type_name(t.typ)
315
- # if isinstance(t, typedesc.CoClass):
316
- # return "%s._com_interfaces_[0]" % t.name
317
- if isinstance(t, typedesc.Typedef):
318
- return t.name
319
- if isinstance(t, typedesc.PointerType):
320
- if ASSUME_STRINGS:
321
- x = get_real_type(t.typ)
322
- if isinstance(x, typedesc.FundamentalType):
323
- if x.name == "char":
324
- return "STRING"
325
- elif x.name == "wchar_t":
326
- return "WSTRING"
327
-
328
- result = "POINTER(%s)" % self.type_name(t.typ)
329
- # XXX Better to inspect t.typ!
330
- if result.startswith("POINTER(WINFUNCTYPE"):
331
- return result[len("POINTER("):-1]
332
- if result.startswith("POINTER(CFUNCTYPE"):
333
- return result[len("POINTER("):-1]
334
- elif result == "POINTER(None)":
335
- return "c_void_p"
336
- return result
337
- elif isinstance(t, typedesc.ArrayType):
338
- return "%s * %s" % (self.type_name(t.typ), int(t.max)+1)
339
- elif isinstance(t, typedesc.FunctionType):
340
- args = [self.type_name(x) for x in [t.returns] + list(t.iterArgTypes())]
341
- if "__stdcall__" in t.attributes:
342
- return "WINFUNCTYPE(%s)" % ", ".join(args)
343
- else:
344
- return "CFUNCTYPE(%s)" % ", ".join(args)
345
- elif isinstance(t, typedesc.CvQualifiedType):
346
- # const and volatile are ignored
347
- return "%s" % self.type_name(t.typ)
348
- elif isinstance(t, typedesc.FundamentalType):
349
- return ctypes_names[t.name]
350
- elif isinstance(t, typedesc.Structure):
351
- return t.name
352
- elif isinstance(t, typedesc.Enumeration):
353
- if t.name:
354
- return t.name
355
- return "c_int" # enums are integers
356
- elif isinstance(t, typedesc.EnumValue):
357
- if keyword.iskeyword(t.name):
358
- return t.name + "_"
359
- return t.name
360
- elif isinstance(t, typedesc.External):
361
- # t.symbol_name - symbol to generate
362
- # t.tlib - the ITypeLib pointer to the typelibrary containing the symbols definition
363
- modname = comtypes.client._generate._name_module(t.tlib)
364
- return "%s.%s" % (modname, t.symbol_name)
365
- return t.name
566
+ file=output)
567
+ return output.getvalue()
366
568
 
367
569
  def need_VARIANT_imports(self, value):
368
570
  text = repr(value)
@@ -371,10 +573,6 @@ class Generator(object):
371
573
  if "datetime.datetime(" in text:
372
574
  self.imports.add("datetime")
373
575
 
374
- def need_GUID(self):
375
- if "GUID" in self.known_symbols:
376
- self.imports.add("GUID", symbols=self.known_symbols)
377
-
378
576
  def _to_docstring(self, orig, depth=1):
379
577
  # type: (str, int) -> str
380
578
  # increasing `depth` by one increases indentation by one
@@ -383,28 +581,25 @@ class Generator(object):
383
581
  repled = orig.replace("\\", r"\\").replace("\"", r"'")
384
582
  return '%s"""%s"""' % (indent, repled)
385
583
 
386
- _arraytypes = 0
387
584
  def ArrayType(self, tp):
388
- self._arraytypes += 1
585
+ # type: (typedesc.ArrayType) -> None
389
586
  self.generate(get_real_type(tp.typ))
390
587
  self.generate(tp.typ)
391
588
 
392
- _enumvalues = 0
393
589
  def EnumValue(self, tp):
590
+ # type: (typedesc.EnumValue) -> None
394
591
  self.last_item_class = False
395
592
  value = int(tp.value)
396
593
  if keyword.iskeyword(tp.name):
397
594
  # XXX use logging!
398
595
  if __warn_on_munge__:
399
596
  print("# Fixing keyword as EnumValue for %s" % tp.name)
400
- tp_name = self.type_name(tp)
597
+ tp_name = self._to_type_name(tp)
401
598
  print("%s = %d" % (tp_name, value), file=self.stream)
402
599
  self.names.add(tp_name)
403
- self._enumvalues += 1
404
600
 
405
- _enumtypes = 0
406
601
  def Enumeration(self, tp):
407
- self._enumtypes += 1
602
+ # type: (typedesc.Enumeration) -> None
408
603
  self.last_item_class = False
409
604
  if tp.name:
410
605
  print("# values for enumeration '%s'" % tp.name, file=self.stream)
@@ -420,15 +615,14 @@ class Generator(object):
420
615
  print("%s = c_int # enum" % tp.name, file=self.stream)
421
616
  self.names.add(tp.name)
422
617
 
423
- _typedefs = 0
424
618
  def Typedef(self, tp):
425
- self._typedefs += 1
426
- if type(tp.typ) in (typedesc.Structure, typedesc.Union):
619
+ # type: (typedesc.Typedef) -> None
620
+ if isinstance(tp.typ, (typedesc.Structure, typedesc.Union)):
427
621
  self.generate(tp.typ.get_head())
428
622
  self.more.add(tp.typ)
429
623
  else:
430
624
  self.generate(tp.typ)
431
- definition = self.type_name(tp.typ)
625
+ definition = self._to_type_name(tp.typ)
432
626
  if tp.name != definition:
433
627
  if definition in self.known_symbols:
434
628
  self.declarations.add(tp.name, definition)
@@ -438,18 +632,20 @@ class Generator(object):
438
632
  self.names.add(tp.name)
439
633
 
440
634
  def FundamentalType(self, item):
635
+ # type: (typedesc.FundamentalType) -> None
441
636
  pass # we should check if this is known somewhere
442
637
 
443
638
  def StructureHead(self, head):
639
+ # type: (typedesc.StructureHead) -> None
444
640
  for struct in head.struct.bases:
445
641
  self.generate(struct.get_head())
446
642
  self.more.add(struct)
447
643
  if head.struct.location:
448
644
  self.last_item_class = False
449
645
  print("# %s %s" % head.struct.location, file=self.stream)
450
- basenames = [self.type_name(b) for b in head.struct.bases]
646
+ basenames = [self._to_type_name(b) for b in head.struct.bases]
451
647
  if basenames:
452
- self.need_GUID()
648
+ self.imports.add("comtypes", "GUID")
453
649
 
454
650
  if not self.last_item_class:
455
651
  print(file=self.stream)
@@ -519,17 +715,20 @@ class Generator(object):
519
715
  print(file=self.stream)
520
716
  self.names.add(head.struct.name)
521
717
 
522
- _structures = 0
523
718
  def Structure(self, struct):
524
- self._structures += 1
719
+ # type: (typedesc.Structure) -> None
525
720
  self.generate(struct.get_head())
526
721
  self.generate(struct.get_body())
527
722
 
528
- Union = Structure
723
+ def Union(self, union):
724
+ # type: (typedesc.Union) -> None
725
+ self.generate(union.get_head())
726
+ self.generate(union.get_body())
529
727
 
530
728
  def StructureBody(self, body):
531
- fields = []
532
- methods = []
729
+ # type: (typedesc.StructureBody) -> None
730
+ fields = [] # type: List[typedesc.Field]
731
+ methods = [] # type: List[typedesc.Method]
533
732
  for m in body.struct.members:
534
733
  if type(m) is typedesc.Field:
535
734
  fields.append(m)
@@ -563,11 +762,6 @@ class Generator(object):
563
762
  if body.struct.bases:
564
763
  assert len(body.struct.bases) == 1
565
764
  self.generate(body.struct.bases[0].get_body())
566
- # field definition normally span several lines.
567
- # Before we generate them, we need to 'import' everything they need.
568
- # So, call type_name for each field once,
569
- for f in fields:
570
- self.type_name(f.typ)
571
765
 
572
766
  if not self.last_item_class:
573
767
  print(file=self.stream)
@@ -590,9 +784,9 @@ class Generator(object):
590
784
  else:
591
785
  fieldname = f.name
592
786
  if f.bits is None:
593
- print(" ('%s', %s)," % (fieldname, self.type_name(f.typ)), file=self.stream)
787
+ print(" ('%s', %s)," % (fieldname, self._to_type_name(f.typ)), file=self.stream)
594
788
  else:
595
- print(" ('%s', %s, %s)," % (fieldname, self.type_name(f.typ), f.bits), file=self.stream)
789
+ print(" ('%s', %s, %s)," % (fieldname, self._to_type_name(f.typ), f.bits), file=self.stream)
596
790
  print("]", file=self.stream)
597
791
 
598
792
  if body.struct.size is None:
@@ -611,13 +805,6 @@ class Generator(object):
611
805
 
612
806
  if methods:
613
807
  self.imports.add("comtypes", "COMMETHOD")
614
- # method definitions normally span several lines.
615
- # Before we generate them, we need to 'import' everything they need.
616
- # So, call type_name for each field once,
617
- for m in methods:
618
- self.type_name(m.returns)
619
- for a in m.iterArgTypes():
620
- self.type_name(a)
621
808
 
622
809
  if not self.last_item_class:
623
810
  print(file=self.stream)
@@ -636,11 +823,11 @@ class Generator(object):
636
823
  " [], \n"
637
824
  " %s,\n"
638
825
  " '%s',\n"
639
- ) % (self.type_name(m.returns), m.name),
826
+ ) % (self._to_type_name(m.returns), m.name),
640
827
  file=self.stream
641
828
  )
642
829
  for a in m.iterArgTypes():
643
- print(" ([], %s),\n" % self.type_name(a), file=self.stream)
830
+ print(" ([], %s),\n" % self._to_type_name(a), file=self.stream)
644
831
  print(" ),", file=self.stream)
645
832
  print("]", file=self.stream)
646
833
 
@@ -648,8 +835,7 @@ class Generator(object):
648
835
  # top-level typedesc generators
649
836
  #
650
837
  def TypeLib(self, lib):
651
- # lib.name, lib.gui, lib.major, lib.minor, lib.doc
652
-
838
+ # type: (typedesc.TypeLib) -> None
653
839
  # Hm, in user code we have to write:
654
840
  # class MyServer(COMObject, ...):
655
841
  # _com_interfaces_ = [MyTypeLib.IInterface]
@@ -676,25 +862,27 @@ class Generator(object):
676
862
  print(file=self.stream)
677
863
 
678
864
  def External(self, ext):
679
- modname = comtypes.client._generate._name_module(ext.tlib)
865
+ # type: (typedesc.External) -> None
866
+ modname = name_wrapper_module(ext.tlib)
680
867
  if modname not in self.imports:
681
- comtypes.client.GetModule(ext.tlib)
868
+ self.externals.append(ext.tlib)
682
869
  self.imports.add(modname)
683
870
 
684
871
  def Constant(self, tp):
872
+ # type: (typedesc.Constant) -> None
685
873
  self.last_item_class = False
686
874
  print("%s = %r # Constant %s" % (tp.name,
687
875
  tp.value,
688
- self.type_name(tp.typ)), file=self.stream)
876
+ self._to_type_name(tp.typ)), file=self.stream)
689
877
  self.names.add(tp.name)
690
878
 
691
879
  def SAFEARRAYType(self, sa):
880
+ # type: (typedesc.SAFEARRAYType) -> None
692
881
  self.generate(sa.typ)
693
882
  self.imports.add("comtypes.automation", "_midlSAFEARRAY")
694
883
 
695
- _pointertypes = 0
696
884
  def PointerType(self, tp):
697
- self._pointertypes += 1
885
+ # type: (typedesc.PointerType) -> None
698
886
  if type(tp.typ) is typedesc.ComInterface:
699
887
  # this defines the class
700
888
  self.generate(tp.typ.get_head())
@@ -719,7 +907,8 @@ class Generator(object):
719
907
  self.declarations.add("WSTRING", "c_wchar_p")
720
908
 
721
909
  def CoClass(self, coclass):
722
- self.need_GUID()
910
+ # type: (typedesc.CoClass) -> None
911
+ self.imports.add("comtypes", "GUID")
723
912
  self.imports.add("comtypes", "CoClass")
724
913
  if not self.last_item_class:
725
914
  print(file=self.stream)
@@ -757,9 +946,9 @@ class Generator(object):
757
946
  where = implemented
758
947
  if item[1] & 1: # IMPLTYPEFLAG_FDEAULT
759
948
  # The default interface should be the first item on the list
760
- where.insert(0, self.type_name(item[0]))
949
+ where.insert(0, self._to_type_name(item[0]))
761
950
  else:
762
- where.append(self.type_name(item[0]))
951
+ where.append(self._to_type_name(item[0]))
763
952
 
764
953
  if implemented:
765
954
  self.last_item_class = False
@@ -771,11 +960,13 @@ class Generator(object):
771
960
  self.names.add(coclass.name)
772
961
 
773
962
  def ComInterface(self, itf):
963
+ # type: (typedesc.ComInterface) -> None
774
964
  self.generate(itf.get_head())
775
965
  self.generate(itf.get_body())
776
966
  self.names.add(itf.name)
777
967
 
778
968
  def _is_enuminterface(self, itf):
969
+ # type: (typedesc.ComInterface) -> bool
779
970
  # Check if this is an IEnumXXX interface
780
971
  if not itf.name.startswith("IEnum"):
781
972
  return False
@@ -786,6 +977,7 @@ class Generator(object):
786
977
  return True
787
978
 
788
979
  def ComInterfaceHead(self, head):
980
+ # type: (typedesc.ComInterfaceHead) -> None
789
981
  if head.itf.name in self.known_symbols:
790
982
  return
791
983
  base = head.itf.base
@@ -794,9 +986,9 @@ class Generator(object):
794
986
  return
795
987
  self.generate(base.get_head())
796
988
  self.more.add(base)
797
- basename = self.type_name(head.itf.base)
989
+ basename = self._to_type_name(head.itf.base)
798
990
 
799
- self.need_GUID()
991
+ self.imports.add("comtypes", "GUID")
800
992
 
801
993
  if not self.last_item_class:
802
994
  print(file=self.stream)
@@ -838,6 +1030,7 @@ class Generator(object):
838
1030
  print(file=self.stream)
839
1031
 
840
1032
  def ComInterfaceBody(self, body):
1033
+ # type: (typedesc.ComInterfaceBody) -> None
841
1034
  # The base class must be fully generated, including the
842
1035
  # _methods_ list.
843
1036
  self.generate(body.itf.base)
@@ -908,15 +1101,17 @@ class Generator(object):
908
1101
  print("#", file=self.stream)
909
1102
 
910
1103
  def DispInterface(self, itf):
1104
+ # type: (typedesc.DispInterface) -> None
911
1105
  self.generate(itf.get_head())
912
1106
  self.generate(itf.get_body())
913
1107
  self.names.add(itf.name)
914
1108
 
915
1109
  def DispInterfaceHead(self, head):
1110
+ # type: (typedesc.DispInterfaceHead) -> None
916
1111
  self.generate(head.itf.base)
917
- basename = self.type_name(head.itf.base)
1112
+ basename = self._to_type_name(head.itf.base)
918
1113
 
919
- self.need_GUID()
1114
+ self.imports.add("comtypes", "GUID")
920
1115
  if not self.last_item_class:
921
1116
  print(file=self.stream)
922
1117
  print(file=self.stream)
@@ -924,10 +1119,10 @@ class Generator(object):
924
1119
  self.last_item_class = True
925
1120
 
926
1121
  print("class %s(%s):" % (head.itf.name, basename), file=self.stream)
927
- print(" _case_insensitive_ = True", file=self.stream)
928
1122
  doc = getattr(head.itf, "doc", None)
929
1123
  if doc:
930
- print(" %r" % doc, file=self.stream)
1124
+ print(self._to_docstring(doc), file=self.stream)
1125
+ print(" _case_insensitive_ = True", file=self.stream)
931
1126
  print(" _iid_ = GUID(%r)" % head.itf.iid, file=self.stream)
932
1127
  print(" _idlflags_ = %s" % head.itf.idlflags, file=self.stream)
933
1128
  print(" _methods_ = []", file=self.stream)
@@ -935,6 +1130,7 @@ class Generator(object):
935
1130
  print(file=self.stream)
936
1131
 
937
1132
  def DispInterfaceBody(self, body):
1133
+ # type: (typedesc.DispInterfaceBody) -> None
938
1134
  # make sure we can generate the body
939
1135
  for m in body.itf.members:
940
1136
  if isinstance(m, typedesc.DispMethod):
@@ -965,206 +1161,108 @@ class Generator(object):
965
1161
  # non-toplevel method generators
966
1162
  #
967
1163
  def make_ComMethod(self, m, isdual):
1164
+ # type: (typedesc.ComMethod, bool) -> None
968
1165
  self.imports.add("comtypes", "COMMETHOD")
969
- # typ, name, idlflags, default
970
1166
  if isdual:
971
1167
  self.imports.add("comtypes", "dispid")
972
- idlflags = [dispid(m.memid)] + m.idlflags
973
- else:
974
- # We don't include the dispid for non-dispatch COM interfaces
975
- idlflags = m.idlflags
976
1168
  if __debug__ and m.doc:
977
1169
  self.imports.add("comtypes", "helpstring")
978
- idlflags.insert(1, helpstring(m.doc))
979
-
1170
+ gen = ComMethodGenerator(m, isdual)
1171
+ print(gen.generate(), file=self.stream, end="")
980
1172
  self.last_item_class = False
981
- if not m.arguments:
982
- code = " COMMETHOD(%r, %s, '%s')," % (idlflags, self.type_name(m.returns), m.name)
983
- if len(code) > 80:
984
- code = (
985
- " COMMETHOD(\n"
986
- " %r,\n"
987
- " %s,\n"
988
- " '%s',\n"
989
- " ),"
990
- ) % (idlflags, self.type_name(m.returns), m.name)
991
-
992
- print(code, file=self.stream)
993
- else:
994
- code = (
995
- " COMMETHOD(\n"
996
- " %r,\n"
997
- " %s,\n"
998
- " '%s',"
999
- ) % (idlflags, self.type_name(m.returns), m.name)
1000
- print(code, file=self.stream)
1001
- arglist = []
1002
- for typ, name, idlflags, default in m.arguments:
1003
- type_name = self.type_name(typ)
1004
- ###########################################################
1005
- # IDL files that contain 'open arrays' or 'conformant
1006
- # varying arrays' method parameters are strange.
1007
- # These arrays have both a 'size_is()' and
1008
- # 'length_is()' attribute, like this example from
1009
- # dia2.idl (in the DIA SDK):
1010
- #
1011
- # interface IDiaSymbol: IUnknown {
1012
- # ...
1013
- # HRESULT get_dataBytes(
1014
- # [in] DWORD cbData,
1015
- # [out] DWORD *pcbData,
1016
- # [out, size_is(cbData),
1017
- # length_is(*pcbData)] BYTE data[]
1018
- # );
1019
- #
1020
- # The really strange thing is that the decompiled type
1021
- # library then contains this declaration, which declares
1022
- # the interface itself as [out] method parameter:
1023
- #
1024
- # interface IDiaSymbol: IUnknown {
1025
- # ...
1026
- # HRESULT _stdcall get_dataBytes(
1027
- # [in] unsigned long cbData,
1028
- # [out] unsigned long* pcbData,
1029
- # [out] IDiaSymbol data);
1030
- #
1031
- # Of course, comtypes does not accept a COM interface
1032
- # as method parameter; so replace the parameter type
1033
- # with the comtypes spelling of 'unsigned char *', and
1034
- # mark the parameter as [in, out], so the IDL
1035
- # equivalent would be like this:
1036
- #
1037
- # interface IDiaSymbol: IUnknown {
1038
- # ...
1039
- # HRESULT _stdcall get_dataBytes(
1040
- # [in] unsigned long cbData,
1041
- # [out] unsigned long* pcbData,
1042
- # [in, out] BYTE data[]);
1043
- ###########################################################
1044
- if isinstance(typ, typedesc.ComInterface):
1045
- self.declarations.add("OPENARRAY", "POINTER(c_ubyte)",
1046
- "hack, see comtypes/tools/codegenerator.py")
1047
- type_name = "OPENARRAY"
1048
- if 'in' not in idlflags:
1049
- idlflags.append('in')
1050
- if 'lcid' in idlflags:# and 'in' in idlflags:
1051
- default = lcid
1052
- if default is not None:
1053
- self.need_VARIANT_imports(default)
1054
-
1055
- code = " (%r, %s, '%s', %r)" % (idlflags, type_name, name, default)
1056
-
1057
- if len(code) > 80:
1058
- code = (
1059
- " (\n"
1060
- " %r,\n"
1061
- " %s,\n"
1062
- " '%s',\n"
1063
- " %r\n"
1064
- " )"
1065
- ) % (idlflags, type_name, name, default)
1066
- else:
1067
- code = " (%r, %s, '%s')" % (idlflags, type_name, name)
1068
- if len(code) > 80:
1069
- code = (
1070
- " (\n"
1071
- " %r,\n"
1072
- " %s,\n"
1073
- " '%s',\n"
1074
- " )"
1075
- ) % (idlflags, type_name, name)
1076
-
1077
- arglist.append(code)
1078
-
1079
- print(",\n".join(arglist), file=self.stream)
1080
- print(" ),", file=self.stream)
1173
+ for typ, _, _, default in m.arguments:
1174
+ if isinstance(typ, typedesc.ComInterface):
1175
+ self.declarations.add("OPENARRAY", "POINTER(c_ubyte)",
1176
+ "hack, see comtypes/tools/codegenerator.py")
1177
+ if default is not None:
1178
+ self.need_VARIANT_imports(default)
1081
1179
 
1082
1180
  def make_DispMethod(self, m):
1181
+ # type: (typedesc.DispMethod) -> None
1083
1182
  self.imports.add("comtypes", "DISPMETHOD")
1084
1183
  self.imports.add("comtypes", "dispid")
1085
- idlflags = [dispid(m.dispid)] + m.idlflags
1086
1184
  if __debug__ and m.doc:
1087
1185
  self.imports.add("comtypes", "helpstring")
1088
- idlflags.insert(1, helpstring(m.doc))
1089
-
1186
+ gen = DispMethodGenerator(m)
1187
+ print(gen.generate(), file=self.stream, end="")
1090
1188
  self.last_item_class = False
1091
-
1092
- # typ, name, idlflags, default
1093
- if not m.arguments:
1094
- code = " DISPMETHOD(%r, %s, '%s')," % (idlflags, self.type_name(m.returns), m.name)
1095
- if len(code) > 80:
1096
- code = (
1097
- " DISPMETHOD(\n"
1098
- " %r,\n"
1099
- " %s,\n"
1100
- " '%s'\n"
1101
- " ),"
1102
- ) % (idlflags, self.type_name(m.returns), m.name)
1103
-
1104
- print(code, file=self.stream)
1105
- else:
1106
- code = (
1107
- " DISPMETHOD(\n"
1108
- " %r,\n"
1109
- " %s,\n"
1110
- " '%s',"
1111
- ) % (idlflags, self.type_name(m.returns), m.name)
1112
-
1113
- print(code, file=self.stream)
1114
-
1115
- arglist = []
1116
- for typ, name, idlflags, default in m.arguments:
1189
+ for _, _, _, default in m.arguments:
1190
+ if default is not None:
1117
1191
  self.need_VARIANT_imports(default)
1118
- if default is not None:
1119
- code = " (%r, %s, '%s', %r)" % (idlflags, self.type_name(typ), name, default)
1120
- if len(code) > 80:
1121
- code = (
1122
- " (\n"
1123
- " %r,\n"
1124
- " %s,\n"
1125
- " '%s',\n"
1126
- " %r\n"
1127
- " )"
1128
- ) % (idlflags, self.type_name(typ), name, default)
1129
-
1130
-
1131
- else:
1132
- code = " (%r, %s, '%s')" % (idlflags, self.type_name(typ), name)
1133
-
1134
- if len(code) > 80:
1135
- code = (
1136
- " (\n"
1137
- " %r,\n"
1138
- " %s,\n"
1139
- " '%s'\n"
1140
- " )"
1141
- ) % (idlflags, self.type_name(typ), name)
1142
-
1143
- arglist.append(code)
1144
-
1145
- print(",\n".join(arglist), file=self.stream)
1146
- print(" ),", file=self.stream)
1147
1192
 
1148
1193
  def make_DispProperty(self, prop):
1194
+ # type: (typedesc.DispProperty) -> None
1149
1195
  self.imports.add("comtypes", "DISPPROPERTY")
1150
1196
  self.imports.add("comtypes", "dispid")
1151
- idlflags = [dispid(prop.dispid)] + prop.idlflags
1152
1197
  if __debug__ and prop.doc:
1153
1198
  self.imports.add("comtypes", "helpstring")
1154
- idlflags.insert(1, helpstring(prop.doc))
1155
-
1199
+ gen = DispPropertyGenerator(prop)
1200
+ print(gen.generate(), file=self.stream, end="")
1156
1201
  self.last_item_class = False
1157
- code = " DISPPROPERTY(%r, %s, '%s')," % (idlflags, self.type_name(prop.typ), prop.name)
1158
- if len(code) > 80:
1159
- code = (
1160
- " DISPPROPERTY(\n"
1161
- " %r,\n"
1162
- " %s,\n"
1163
- " '%s'\n"
1164
- " ),"
1165
- ) % (idlflags, self.type_name(prop.typ), prop.name)
1166
1202
 
1167
- print(code, file=self.stream)
1203
+
1204
+ class TypeNamer(object):
1205
+ def __call__(self, t):
1206
+ # type: (Any) -> str
1207
+ # Return a string, containing an expression which can be used
1208
+ # to refer to the type. Assumes the 'from ctypes import *'
1209
+ # namespace is available.
1210
+ if isinstance(t, typedesc.SAFEARRAYType):
1211
+ return "_midlSAFEARRAY(%s)" % self(t.typ)
1212
+ # if isinstance(t, typedesc.CoClass):
1213
+ # return "%s._com_interfaces_[0]" % t.name
1214
+ if isinstance(t, typedesc.Typedef):
1215
+ return t.name
1216
+ if isinstance(t, typedesc.PointerType):
1217
+ _t, pcnt = self._inspect_PointerType(t)
1218
+ return "%s%s%s" % ("POINTER("*pcnt, self(_t), ")"*pcnt)
1219
+ elif isinstance(t, typedesc.ArrayType):
1220
+ return "%s * %s" % (self(t.typ), int(t.max)+1)
1221
+ elif isinstance(t, typedesc.FunctionType):
1222
+ args = [self(x) for x in [t.returns] + list(t.iterArgTypes())]
1223
+ if "__stdcall__" in t.attributes:
1224
+ return "WINFUNCTYPE(%s)" % ", ".join(args)
1225
+ else:
1226
+ return "CFUNCTYPE(%s)" % ", ".join(args)
1227
+ elif isinstance(t, typedesc.CvQualifiedType):
1228
+ # const and volatile are ignored
1229
+ return "%s" % self(t.typ)
1230
+ elif isinstance(t, typedesc.FundamentalType):
1231
+ return ctypes_names[t.name]
1232
+ elif isinstance(t, typedesc.Structure):
1233
+ return t.name
1234
+ elif isinstance(t, typedesc.Enumeration):
1235
+ if t.name:
1236
+ return t.name
1237
+ return "c_int" # enums are integers
1238
+ elif isinstance(t, typedesc.EnumValue):
1239
+ if keyword.iskeyword(t.name):
1240
+ return t.name + "_"
1241
+ return t.name
1242
+ elif isinstance(t, typedesc.External):
1243
+ # t.symbol_name - symbol to generate
1244
+ # t.tlib - the ITypeLib pointer to the typelibrary containing the symbols definition
1245
+ modname = name_wrapper_module(t.tlib)
1246
+ return "%s.%s" % (modname, t.symbol_name)
1247
+ return t.name
1248
+
1249
+ def _inspect_PointerType(self, t, count=0):
1250
+ # type: (typedesc.PointerType, int) -> Tuple[Any, int]
1251
+ if ASSUME_STRINGS:
1252
+ x = get_real_type(t.typ)
1253
+ if isinstance(x, typedesc.FundamentalType):
1254
+ if x.name == "char":
1255
+ return typedesc.Typedef("STRING", x), count
1256
+ elif x.name == "wchar_t":
1257
+ return typedesc.Typedef("WSTRING", x), count
1258
+ if isinstance(t.typ, typedesc.FunctionType):
1259
+ return t.typ, count
1260
+ if isinstance(t.typ, typedesc.FundamentalType):
1261
+ if t.typ.name == "void":
1262
+ return typedesc.Typedef("c_void_p", t.typ), count
1263
+ if isinstance(t.typ, typedesc.PointerType):
1264
+ return self._inspect_PointerType(t.typ, count + 1)
1265
+ return t.typ, count + 1
1168
1266
 
1169
1267
 
1170
1268
  class ImportedNamespaces(object):
@@ -1184,16 +1282,33 @@ class ImportedNamespaces(object):
1184
1282
  >>> imports.add('ctypes', '*')
1185
1283
  >>> imports.add('decimal', 'Decimal')
1186
1284
  >>> imports.add('GUID', symbols={'GUID': 'comtypes'})
1187
- >>> for name in ('COMMETHOD', 'IUnknown', 'dispid', 'CoClass',
1188
- ... 'BSTR', 'DISPPROPERTY'):
1285
+ >>> for name in ('COMMETHOD', 'DISPMETHOD', 'IUnknown', 'dispid',
1286
+ ... 'CoClass', 'BSTR', 'DISPPROPERTY'):
1189
1287
  ... imports.add('comtypes', name)
1190
1288
  >>> imports.add('ctypes.wintypes')
1191
1289
  >>> print(imports.getvalue())
1192
1290
  from ctypes import *
1193
1291
  import datetime
1194
1292
  from decimal import Decimal
1195
- from comtypes import BSTR, CoClass, COMMETHOD, dispid, DISPPROPERTY, \\
1196
- GUID, IUnknown
1293
+ from comtypes import (
1294
+ BSTR, CoClass, COMMETHOD, dispid, DISPMETHOD, DISPPROPERTY, GUID,
1295
+ IUnknown
1296
+ )
1297
+ import ctypes.wintypes
1298
+ >>> print(imports.getvalue(for_stub=True))
1299
+ from ctypes import *
1300
+ import datetime
1301
+ from decimal import Decimal as Decimal
1302
+ from comtypes import (
1303
+ BSTR as BSTR,
1304
+ CoClass as CoClass,
1305
+ COMMETHOD as COMMETHOD,
1306
+ dispid as dispid,
1307
+ DISPMETHOD as DISPMETHOD,
1308
+ DISPPROPERTY as DISPPROPERTY,
1309
+ GUID as GUID,
1310
+ IUnknown as IUnknown,
1311
+ )
1197
1312
  import ctypes.wintypes
1198
1313
  """
1199
1314
  if name2 is None:
@@ -1232,32 +1347,40 @@ class ImportedNamespaces(object):
1232
1347
  return self.data[import_] == from_
1233
1348
  return False
1234
1349
 
1235
- def _make_line(self, import_, from_=None):
1236
- if from_ is None:
1237
- return "import %s" % import_
1350
+ def _make_line(self, from_, imports, for_stub):
1351
+ if for_stub:
1352
+ import_ = ", ".join("%s as %s" % (n, n) for n in imports)
1353
+ else:
1354
+ import_ = ", ".join(imports)
1238
1355
  code = "from %s import %s" % (from_, import_)
1239
- if len(code) > 80:
1356
+ if len(code) <= 80:
1357
+ return code
1358
+ if for_stub:
1359
+ import_ = "\n".join(" %s as %s," % (n, n) for n in imports)
1360
+ else:
1240
1361
  wrapper = textwrap.TextWrapper(subsequent_indent=" ",
1362
+ initial_indent=" ",
1241
1363
  break_long_words=False)
1242
- code = " \\\n".join(wrapper.wrap(code))
1364
+ import_ = "\n".join(wrapper.wrap(import_))
1365
+ code = "from %s import (\n%s\n)" % (from_, import_)
1243
1366
  return code
1244
1367
 
1245
- def getvalue(self):
1368
+ def getvalue(self, for_stub=False):
1246
1369
  ns = {}
1247
1370
  lines = []
1248
1371
  for key, val in self.data.items():
1249
1372
  if val is None:
1250
1373
  ns[key] = val
1251
1374
  elif key == "*":
1252
- lines.append(self._make_line("*", val))
1375
+ lines.append("from %s import *" % val)
1253
1376
  else:
1254
1377
  ns.setdefault(val, set()).add(key)
1255
1378
  for key, val in ns.items():
1256
1379
  if val is None:
1257
- lines.append(self._make_line(key))
1380
+ lines.append("import %s" % key)
1258
1381
  else:
1259
- names = ", ".join(sorted(val, key=lambda s: s.lower()))
1260
- lines.append(self._make_line(names, key))
1382
+ names = sorted(val, key=lambda s: s.lower())
1383
+ lines.append(self._make_line(key, names, for_stub=for_stub))
1261
1384
  return "\n".join(lines)
1262
1385
 
1263
1386
 
@@ -1290,9 +1413,3 @@ class DeclaredNamespaces(object):
1290
1413
  code = code + " # %s" % comment
1291
1414
  lines.append(code)
1292
1415
  return "\n".join(lines)
1293
-
1294
-
1295
- # shortcut for development
1296
- if __name__ == "__main__":
1297
- from . import tlbparser
1298
- tlbparser.main()