comtypes 1.4.1__zip → 1.4.2__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 (109) hide show
  1. {comtypes-1.4.1 → comtypes-1.4.2}/CHANGES.txt +9 -0
  2. {comtypes-1.4.1/comtypes.egg-info → comtypes-1.4.2}/PKG-INFO +1 -1
  3. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/__init__.py +1 -1
  4. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/client/_generate.py +105 -80
  5. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/hints.pyi +14 -2
  6. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/test/test_client.py +14 -4
  7. comtypes-1.4.2/comtypes/test/test_client_regenerate_modules.py +158 -0
  8. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/tools/codegenerator.py +168 -79
  9. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/tools/typeannotator.py +17 -15
  10. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/tools/typedesc.py +1 -1
  11. {comtypes-1.4.1 → comtypes-1.4.2/comtypes.egg-info}/PKG-INFO +1 -1
  12. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes.egg-info/SOURCES.txt +1 -0
  13. {comtypes-1.4.1 → comtypes-1.4.2}/LICENSE.txt +0 -0
  14. {comtypes-1.4.1 → comtypes-1.4.2}/MANIFEST.in +0 -0
  15. {comtypes-1.4.1 → comtypes-1.4.2}/README.md +0 -0
  16. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/GUID.py +0 -0
  17. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/_comobject.py +0 -0
  18. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/_memberspec.py +0 -0
  19. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/_meta.py +0 -0
  20. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/_npsupport.py +0 -0
  21. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/_safearray.py +0 -0
  22. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/automation.py +0 -0
  23. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/clear_cache.py +0 -0
  24. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/client/__init__.py +0 -0
  25. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/client/_code_cache.py +0 -0
  26. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/client/_constants.py +0 -0
  27. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/client/_events.py +0 -0
  28. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/client/dynamic.py +0 -0
  29. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/client/lazybind.py +0 -0
  30. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/connectionpoints.py +0 -0
  31. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/errorinfo.py +0 -0
  32. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/git.py +0 -0
  33. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/hresult.py +0 -0
  34. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/logutil.py +0 -0
  35. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/messageloop.py +0 -0
  36. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/patcher.py +0 -0
  37. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/persist.py +0 -0
  38. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/safearray.py +0 -0
  39. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/server/__init__.py +0 -0
  40. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/server/automation.py +0 -0
  41. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/server/connectionpoints.py +0 -0
  42. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/server/inprocserver.py +0 -0
  43. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/server/localserver.py +0 -0
  44. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/server/register.py +0 -0
  45. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/server/w_getopt.py +0 -0
  46. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/shelllink.py +0 -0
  47. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/test/TestComServer.idl +0 -0
  48. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/test/TestComServer.py +0 -0
  49. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/test/TestComServer.tlb +0 -0
  50. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/test/TestDispServer.idl +0 -0
  51. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/test/TestDispServer.py +0 -0
  52. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/test/TestDispServer.tlb +0 -0
  53. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/test/__init__.py +0 -0
  54. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/test/find_memleak.py +0 -0
  55. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/test/mylib.idl +0 -0
  56. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/test/mytypelib.idl +0 -0
  57. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/test/runtests.py +0 -0
  58. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/test/setup.py +0 -0
  59. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/test/test_BSTR.py +0 -0
  60. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/test/test_DISPPARAMS.py +0 -0
  61. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/test/test_GUID.py +0 -0
  62. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/test/test_QueryService.py +0 -0
  63. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/test/test_agilent.py +0 -0
  64. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/test/test_avmc.py +0 -0
  65. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/test/test_basic.py +0 -0
  66. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/test/test_casesensitivity.py +0 -0
  67. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/test/test_clear_cache.py +0 -0
  68. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/test/test_client_dynamic.py +0 -0
  69. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/test/test_collections.py +0 -0
  70. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/test/test_comserver.py +0 -0
  71. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/test/test_createwrappers.py +0 -0
  72. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/test/test_dict.py +0 -0
  73. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/test/test_dispinterface.py +0 -0
  74. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/test/test_dyndispatch.py +0 -0
  75. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/test/test_excel.py +0 -0
  76. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/test/test_findgendir.py +0 -0
  77. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/test/test_getactiveobj.py +0 -0
  78. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/test/test_ie.py +0 -0
  79. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/test/test_ienum.py +0 -0
  80. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/test/test_imfattributes.py +0 -0
  81. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/test/test_inout_args.py +0 -0
  82. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/test/test_jscript.js +0 -0
  83. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/test/test_msscript.py +0 -0
  84. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/test/test_npsupport.py +0 -0
  85. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/test/test_outparam.py +0 -0
  86. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/test/test_propputref.py +0 -0
  87. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/test/test_pump_events.py +0 -0
  88. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/test/test_safearray.py +0 -0
  89. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/test/test_sapi.py +0 -0
  90. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/test/test_server.py +0 -0
  91. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/test/test_showevents.py +0 -0
  92. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/test/test_subinterface.py +0 -0
  93. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/test/test_typeinfo.py +0 -0
  94. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/test/test_urlhistory.py +0 -0
  95. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/test/test_variant.py +0 -0
  96. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/test/test_win32com_interop.py +0 -0
  97. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/test/test_wmi.py +0 -0
  98. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/test/test_word.py +0 -0
  99. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/tools/__init__.py +0 -0
  100. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/tools/tlbparser.py +0 -0
  101. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/tools/typedesc_base.py +0 -0
  102. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/typeinfo.py +0 -0
  103. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/util.py +0 -0
  104. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes/viewobject.py +0 -0
  105. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes.egg-info/dependency_links.txt +0 -0
  106. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes.egg-info/entry_points.txt +0 -0
  107. {comtypes-1.4.1 → comtypes-1.4.2}/comtypes.egg-info/top_level.txt +0 -0
  108. {comtypes-1.4.1 → comtypes-1.4.2}/setup.cfg +0 -0
  109. {comtypes-1.4.1 → comtypes-1.4.2}/setup.py +0 -0
@@ -208,28 +208,26 @@ def _to_arg_definition(
208
208
  default: _DefValType,
209
209
  ) -> str:
210
210
  if default is not None:
211
- elms = (idlflags, type_name, arg_name, default)
212
- code = " (%r, %s, '%s', %r)" % elms
211
+ code = f" ({idlflags!r}, {type_name}, '{arg_name}', {default!r})"
213
212
  if len(code) > 80:
214
213
  code = (
215
214
  " (\n"
216
- " %r,\n"
217
- " %s,\n"
218
- " '%s',\n"
219
- " %r\n"
215
+ f" {idlflags!r},\n"
216
+ f" {type_name},\n"
217
+ f" '{arg_name}',\n"
218
+ f" {default!r}\n"
220
219
  " )"
221
- ) % elms
220
+ )
222
221
  else:
223
- elms = (idlflags, type_name, arg_name)
224
- code = " (%r, %s, '%s')" % elms
222
+ code = f" ({idlflags!r}, {type_name}, '{arg_name}')"
225
223
  if len(code) > 80:
226
224
  code = (
227
225
  " (\n"
228
- " %r,\n"
229
- " %s,\n"
230
- " '%s',\n"
226
+ f" {idlflags!r},\n"
227
+ f" {type_name},\n"
228
+ f" '{arg_name}',\n"
231
229
  " )"
232
- ) % elms
230
+ )
233
231
  return code
234
232
 
235
233
 
@@ -237,16 +235,15 @@ class ComMethodGenerator(object):
237
235
  def __init__(self, m: typedesc.ComMethod, isdual: bool) -> None:
238
236
  self._m = m
239
237
  self._isdual = isdual
240
- self._stream = io.StringIO()
238
+ self.data: List[str] = []
241
239
  self._to_type_name = TypeNamer()
242
240
 
243
- def generate(self):
244
- # () -> str
241
+ def generate(self) -> str:
245
242
  if not self._m.arguments:
246
243
  self._make_noargs()
247
244
  else:
248
245
  self._make_withargs()
249
- return self._stream.getvalue()
246
+ return "\n".join(self.data)
250
247
 
251
248
  def _get_common_elms(self) -> Tuple[List[_IdlFlagType], str, str]:
252
249
  idlflags: List[_IdlFlagType] = []
@@ -261,26 +258,30 @@ class ComMethodGenerator(object):
261
258
  return (idlflags, type_name, self._m.name)
262
259
 
263
260
  def _make_noargs(self) -> None:
264
- elms = self._get_common_elms()
265
- code = " COMMETHOD(%r, %s, '%s')," % elms
261
+ flags, type_name, member_name = self._get_common_elms()
262
+ code = f" COMMETHOD({flags!r}, {type_name}, '{member_name}'),"
266
263
  if len(code) > 80:
267
264
  code = (
268
265
  " COMMETHOD(\n"
269
- " %r,\n"
270
- " %s,\n"
271
- " '%s',\n"
266
+ f" {flags!r},\n"
267
+ f" {type_name},\n"
268
+ f" '{member_name}',\n"
272
269
  " ),"
273
- ) % elms
274
- print(code, file=self._stream)
270
+ )
271
+ self.data.append(code)
275
272
 
276
273
  def _make_withargs(self) -> None:
274
+ flags, type_name, member_name = self._get_common_elms()
277
275
  code = (
278
- " COMMETHOD(\n" " %r,\n" " %s,\n" " '%s',"
279
- ) % self._get_common_elms()
280
- print(code, file=self._stream)
276
+ " COMMETHOD(\n"
277
+ f" {flags!r},\n"
278
+ f" {type_name},\n"
279
+ f" '{member_name}',"
280
+ )
281
+ self.data.append(code)
281
282
  arglist = [_to_arg_definition(*i) for i in self._iter_args()]
282
- print(",\n".join(arglist), file=self._stream)
283
- print(" ),", file=self._stream)
283
+ self.data.append(",\n".join(arglist))
284
+ self.data.append(" ),")
284
285
 
285
286
  def _iter_args(self) -> Iterator[Tuple[str, str, List[str], _DefValType]]:
286
287
  for typ, arg_name, _f, _defval in self._m.arguments:
@@ -341,16 +342,15 @@ class ComMethodGenerator(object):
341
342
  class DispMethodGenerator(object):
342
343
  def __init__(self, m: typedesc.DispMethod) -> None:
343
344
  self._m = m
344
- self._stream = io.StringIO()
345
+ self.data: List[str] = []
345
346
  self._to_type_name = TypeNamer()
346
347
 
347
- def generate(self):
348
- # () -> str
348
+ def generate(self) -> str:
349
349
  if not self._m.arguments:
350
350
  self._make_noargs()
351
351
  else:
352
352
  self._make_withargs()
353
- return self._stream.getvalue()
353
+ return "\n".join(self.data)
354
354
 
355
355
  def _get_common_elms(self) -> Tuple[List[_IdlFlagType], str, str]:
356
356
  idlflags: List[_IdlFlagType] = []
@@ -362,26 +362,30 @@ class DispMethodGenerator(object):
362
362
  return (idlflags, type_name, self._m.name)
363
363
 
364
364
  def _make_noargs(self) -> None:
365
- elms = self._get_common_elms()
366
- code = " DISPMETHOD(%r, %s, '%s')," % elms
365
+ flags, type_name, member_name = self._get_common_elms()
366
+ code = f" DISPMETHOD({flags!r}, {type_name}, '{member_name}'),"
367
367
  if len(code) > 80:
368
368
  code = (
369
369
  " DISPMETHOD(\n"
370
- " %r,\n"
371
- " %s,\n"
372
- " '%s',\n"
370
+ f" {flags!r},\n"
371
+ f" {type_name},\n"
372
+ f" '{member_name}',\n"
373
373
  " ),"
374
- ) % elms
375
- print(code, file=self._stream)
374
+ )
375
+ self.data.append(code)
376
376
 
377
377
  def _make_withargs(self) -> None:
378
+ flags, type_name, member_name = self._get_common_elms()
378
379
  code = (
379
- " DISPMETHOD(\n" " %r,\n" " %s,\n" " '%s',"
380
- ) % self._get_common_elms()
381
- print(code, file=self._stream)
380
+ " DISPMETHOD(\n"
381
+ f" {flags!r},\n"
382
+ f" {type_name},\n"
383
+ f" '{member_name}',"
384
+ )
385
+ self.data.append(code)
382
386
  arglist = [_to_arg_definition(*i) for i in self._iter_args()]
383
- print(",\n".join(arglist), file=self._stream)
384
- print(" ),", file=self._stream)
387
+ self.data.append(",\n".join(arglist))
388
+ self.data.append(" ),")
385
389
 
386
390
  def _iter_args(self) -> Iterator[Tuple[str, str, List[str], _DefValType]]:
387
391
  for typ, arg_name, idlflags, default in self._m.arguments:
@@ -394,19 +398,18 @@ class DispPropertyGenerator(object):
394
398
  self._m = m
395
399
  self._to_type_name = TypeNamer()
396
400
 
397
- def generate(self):
398
- # () -> str
399
- elms = self._get_common_elms()
400
- code = " DISPPROPERTY(%r, %s, '%s')," % elms
401
+ def generate(self) -> str:
402
+ flags, type_name, member_name = self._get_common_elms()
403
+ code = f" DISPPROPERTY({flags!r}, {type_name}, '{member_name}'),"
401
404
  if len(code) > 80:
402
405
  code = (
403
406
  " DISPPROPERTY(\n"
404
- " %r,\n"
405
- " %s,\n"
406
- " '%s'\n"
407
+ f" {flags!r},\n"
408
+ f" {type_name},\n"
409
+ f" '{member_name}'\n"
407
410
  " ),"
408
- ) % elms
409
- return code + "\n"
411
+ )
412
+ return code
410
413
 
411
414
  def _get_common_elms(self) -> Tuple[List[_IdlFlagType], str, str]:
412
415
  idlflags: List[_IdlFlagType] = []
@@ -418,14 +421,26 @@ class DispPropertyGenerator(object):
418
421
  return (idlflags, type_name, self._m.name)
419
422
 
420
423
 
424
+ _InterfaceTypeDesc = _UnionT[
425
+ typedesc.ComInterface,
426
+ typedesc.ComInterfaceHead,
427
+ typedesc.ComInterfaceBody,
428
+ typedesc.DispInterface,
429
+ typedesc.DispInterfaceHead,
430
+ typedesc.DispInterfaceBody,
431
+ ]
432
+
433
+
421
434
  class CodeGenerator(object):
422
- def __init__(self, known_symbols=None):
435
+ def __init__(self, known_symbols=None, known_interfaces=None) -> None:
423
436
  self.stream = io.StringIO()
424
437
  self.imports = ImportedNamespaces()
425
438
  self.declarations = DeclaredNamespaces()
426
439
  self.enums = EnumerationNamespaces()
440
+ self.unnamed_enum_members: List[Tuple[str, int]] = []
427
441
  self._to_type_name = TypeNamer()
428
442
  self.known_symbols = known_symbols or {}
443
+ self.known_interfaces = known_interfaces or {}
429
444
 
430
445
  self.done = set() # type descriptions that have been generated
431
446
  self.names = set() # names that have been generated
@@ -436,13 +451,15 @@ class CodeGenerator(object):
436
451
  def generate(self, item):
437
452
  if item in self.done:
438
453
  return
454
+ if self._is_interface_typedesc(item):
455
+ self._define_interface(item)
456
+ return
439
457
  if isinstance(item, typedesc.StructureHead):
440
458
  name = getattr(item.struct, "name", None)
441
459
  else:
442
460
  name = getattr(item, "name", None)
443
461
  if name in self.known_symbols:
444
462
  self.imports.add(name, symbols=self.known_symbols)
445
-
446
463
  self.done.add(item)
447
464
  if isinstance(item, typedesc.Structure):
448
465
  self.done.add(item.get_head())
@@ -572,6 +589,12 @@ class CodeGenerator(object):
572
589
  print(file=output)
573
590
  print(self.declarations.getvalue(), file=output)
574
591
  print(file=output)
592
+ if self.unnamed_enum_members:
593
+ print("# values for unnamed enumeration", file=output)
594
+ for n, v in self.unnamed_enum_members:
595
+ print(f"{n} = {v}", file=output)
596
+ print(file=output)
597
+ print(self.enums.to_constants(), file=output)
575
598
  print(self.stream.getvalue(), file=output)
576
599
  print(self._make_dunder_all_part(), file=output)
577
600
  print(file=output)
@@ -596,7 +619,7 @@ class CodeGenerator(object):
596
619
  print(self._make_friendly_module_import_part(modname), file=output)
597
620
  print(file=output)
598
621
  print(file=output)
599
- print(self.enums.getvalue(), file=output)
622
+ print(self.enums.to_intflags(), file=output)
600
623
  print(file=output)
601
624
  print(file=output)
602
625
  enum_aliases = self.enum_aliases
@@ -669,21 +692,17 @@ class CodeGenerator(object):
669
692
  if __warn_on_munge__:
670
693
  print("# Fixing keyword as EnumValue for %s" % tp.name)
671
694
  tp_name = self._to_type_name(tp)
672
- print("%s = %d" % (tp_name, value), file=self.stream)
673
695
  if tp.enumeration.name:
674
696
  self.enums.add(tp.enumeration.name, tp_name, value)
697
+ else:
698
+ self.unnamed_enum_members.append((tp_name, value))
675
699
  self.names.add(tp_name)
676
700
 
677
701
  def Enumeration(self, tp: typedesc.Enumeration) -> None:
678
702
  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
703
  for item in tp.values:
684
704
  self.generate(item)
685
705
  if tp.name:
686
- print("%s = c_int # enum" % tp.name, file=self.stream)
687
706
  self.names.add(tp.name)
688
707
 
689
708
  def Typedef(self, tp: typedesc.Typedef) -> None:
@@ -1066,11 +1085,63 @@ class CodeGenerator(object):
1066
1085
 
1067
1086
  self.names.add(coclass.name)
1068
1087
 
1088
+ def _is_interface_typedesc(
1089
+ self, item: Any
1090
+ ) -> "comtypes.hints.TypeGuard[_InterfaceTypeDesc]":
1091
+ return isinstance(
1092
+ item,
1093
+ (
1094
+ typedesc.ComInterface,
1095
+ typedesc.ComInterfaceHead,
1096
+ typedesc.ComInterfaceBody,
1097
+ typedesc.DispInterface,
1098
+ typedesc.DispInterfaceHead,
1099
+ typedesc.DispInterfaceBody,
1100
+ ),
1101
+ )
1102
+
1103
+ def _define_interface(self, item: _InterfaceTypeDesc) -> None:
1104
+ if isinstance(
1105
+ item,
1106
+ (
1107
+ typedesc.ComInterfaceHead,
1108
+ typedesc.ComInterfaceBody,
1109
+ typedesc.DispInterfaceHead,
1110
+ typedesc.DispInterfaceBody,
1111
+ ),
1112
+ ):
1113
+ if self._is_known_interface(item.itf):
1114
+ self.imports.add(item.itf.name, symbols=self.known_symbols)
1115
+ self.done.add(item)
1116
+ return
1117
+ elif isinstance(item, (typedesc.ComInterface, typedesc.DispInterface)):
1118
+ if self._is_known_interface(item):
1119
+ self.imports.add(item.name, symbols=self.known_symbols)
1120
+ self.done.add(item)
1121
+ self.done.add(item.get_head())
1122
+ self.done.add(item.get_body())
1123
+ return
1124
+ else:
1125
+ raise TypeError
1126
+ self.done.add(item) # to avoid infinite recursion.
1127
+ mth = getattr(self, type(item).__name__)
1128
+ mth(item)
1129
+
1069
1130
  def ComInterface(self, itf: typedesc.ComInterface) -> None:
1070
1131
  self.generate(itf.get_head())
1071
1132
  self.generate(itf.get_body())
1072
1133
  self.names.add(itf.name)
1073
1134
 
1135
+ def _is_known_interface(
1136
+ self, item: _UnionT[typedesc.ComInterface, typedesc.DispInterface]
1137
+ ) -> bool:
1138
+ """Returns whether an interface is statically defined in `comtypes`,
1139
+ based on its name and iid.
1140
+ """
1141
+ if item.name in self.known_interfaces:
1142
+ return self.known_interfaces[item.name] == item.iid
1143
+ return False
1144
+
1074
1145
  def _is_enuminterface(self, itf: typedesc.ComInterface) -> bool:
1075
1146
  # Check if this is an IEnumXXX interface
1076
1147
  if not itf.name.startswith("IEnum"):
@@ -1082,14 +1153,11 @@ class CodeGenerator(object):
1082
1153
  return True
1083
1154
 
1084
1155
  def ComInterfaceHead(self, head: typedesc.ComInterfaceHead) -> None:
1085
- if head.itf.name in self.known_symbols:
1086
- return
1087
- base = head.itf.base
1088
1156
  if head.itf.base is None:
1089
1157
  # we don't beed to generate IUnknown
1090
1158
  return
1091
- self.generate(base.get_head())
1092
- self.more.add(base)
1159
+ self.generate(head.itf.base.get_head())
1160
+ self.more.add(head.itf.base)
1093
1161
  basename = self._to_type_name(head.itf.base)
1094
1162
 
1095
1163
  self.imports.add("comtypes", "GUID")
@@ -1130,11 +1198,11 @@ class CodeGenerator(object):
1130
1198
  print(" return item", file=self.stream)
1131
1199
  print(" raise IndexError(index)", file=self.stream)
1132
1200
 
1133
- annotaions = typeannotator.ComInterfaceMembersAnnotator(head.itf).generate()
1134
- if annotaions:
1201
+ annotations = typeannotator.ComInterfaceMembersAnnotator(head.itf).generate()
1202
+ if annotations:
1135
1203
  print(file=self.stream)
1136
1204
  print(" if TYPE_CHECKING: # commembers", file=self.stream)
1137
- print(annotaions, file=self.stream, end="")
1205
+ print(annotations, file=self.stream)
1138
1206
 
1139
1207
  print(file=self.stream)
1140
1208
  print(file=self.stream)
@@ -1258,11 +1326,11 @@ class CodeGenerator(object):
1258
1326
  print(" _idlflags_ = %s" % head.itf.idlflags, file=self.stream)
1259
1327
  print(" _methods_ = []", file=self.stream)
1260
1328
 
1261
- annotaions = typeannotator.DispInterfaceMembersAnnotator(head.itf).generate()
1262
- if annotaions:
1329
+ annotations = typeannotator.DispInterfaceMembersAnnotator(head.itf).generate()
1330
+ if annotations:
1263
1331
  print(file=self.stream)
1264
1332
  print(" if TYPE_CHECKING: # dispmembers", file=self.stream)
1265
- print(annotaions, file=self.stream, end="")
1333
+ print(annotations, file=self.stream)
1266
1334
 
1267
1335
  print(file=self.stream)
1268
1336
  print(file=self.stream)
@@ -1304,7 +1372,7 @@ class CodeGenerator(object):
1304
1372
  if __debug__ and m.doc:
1305
1373
  self.imports.add("comtypes", "helpstring")
1306
1374
  gen = ComMethodGenerator(m, isdual)
1307
- print(gen.generate(), file=self.stream, end="")
1375
+ print(gen.generate(), file=self.stream)
1308
1376
  self.last_item_class = False
1309
1377
  for typ, _, _, default in m.arguments:
1310
1378
  if isinstance(typ, typedesc.ComInterface):
@@ -1322,7 +1390,7 @@ class CodeGenerator(object):
1322
1390
  if __debug__ and m.doc:
1323
1391
  self.imports.add("comtypes", "helpstring")
1324
1392
  gen = DispMethodGenerator(m)
1325
- print(gen.generate(), file=self.stream, end="")
1393
+ print(gen.generate(), file=self.stream)
1326
1394
  self.last_item_class = False
1327
1395
  for _, _, _, default in m.arguments:
1328
1396
  if default is not None:
@@ -1334,7 +1402,7 @@ class CodeGenerator(object):
1334
1402
  if __debug__ and prop.doc:
1335
1403
  self.imports.add("comtypes", "helpstring")
1336
1404
  gen = DispPropertyGenerator(prop)
1337
- print(gen.generate(), file=self.stream, end="")
1405
+ print(gen.generate(), file=self.stream)
1338
1406
  self.last_item_class = False
1339
1407
 
1340
1408
 
@@ -1552,13 +1620,14 @@ class EnumerationNamespaces(object):
1552
1620
  """Adds a namespace will be enumeration and its member.
1553
1621
 
1554
1622
  Examples:
1623
+ <BLANKLINE> is necessary for doctest
1555
1624
  >>> enums = EnumerationNamespaces()
1556
1625
  >>> enums.add('Foo', 'ham', 1)
1557
1626
  >>> enums.add('Foo', 'spam', 2)
1558
1627
  >>> enums.add('Bar', 'bacon', 3)
1559
1628
  >>> assert 'Foo' in enums
1560
1629
  >>> assert 'Baz' not in enums
1561
- >>> print(enums.getvalue()) # <BLANKLINE> is necessary for doctest
1630
+ >>> print(enums.to_intflags())
1562
1631
  class Foo(IntFlag):
1563
1632
  ham = 1
1564
1633
  spam = 2
@@ -1566,6 +1635,15 @@ class EnumerationNamespaces(object):
1566
1635
  <BLANKLINE>
1567
1636
  class Bar(IntFlag):
1568
1637
  bacon = 3
1638
+ >>> print(enums.to_constants())
1639
+ # values for enumeration 'Foo'
1640
+ ham = 1
1641
+ spam = 2
1642
+ Foo = c_int # enum
1643
+ <BLANKLINE>
1644
+ # values for enumeration 'Bar'
1645
+ bacon = 3
1646
+ Bar = c_int # enum
1569
1647
  """
1570
1648
  self.data.setdefault(enum_name, []).append((member_name, value))
1571
1649
 
@@ -1575,7 +1653,18 @@ class EnumerationNamespaces(object):
1575
1653
  def get_symbols(self) -> Set[str]:
1576
1654
  return set(self.data)
1577
1655
 
1578
- def getvalue(self) -> str:
1656
+ def to_constants(self) -> str:
1657
+ blocks = []
1658
+ for enum_name, enum_members in self.data.items():
1659
+ lines = []
1660
+ lines.append(f"# values for enumeration '{enum_name}'")
1661
+ for n, v in enum_members:
1662
+ lines.append(f"{n} = {v}")
1663
+ lines.append(f"{enum_name} = c_int # enum")
1664
+ blocks.append("\n".join(lines))
1665
+ return "\n\n".join(blocks)
1666
+
1667
+ def to_intflags(self) -> str:
1579
1668
  blocks = []
1580
1669
  for enum_name, enum_members in self.data.items():
1581
1670
  lines = []
@@ -1,5 +1,4 @@
1
1
  import abc
2
- import io
3
2
  import keyword
4
3
  from typing import (
5
4
  Any,
@@ -55,7 +54,7 @@ _CatMths = Tuple[ # categorized methods
55
54
 
56
55
  class _MethodsAnnotator(abc.ABC, Generic[_T_MTD]):
57
56
  def __init__(self) -> None:
58
- self.stream = io.StringIO()
57
+ self.data: List[str] = []
59
58
 
60
59
  @abc.abstractmethod
61
60
  def to_method_annotator(self, method: _T_MTD) -> _MethodAnnotator[_T_MTD]:
@@ -100,7 +99,7 @@ class _MethodsAnnotator(abc.ABC, Generic[_T_MTD]):
100
99
  else:
101
100
  self._define_member(f"pass # what does `{name}` behave?")
102
101
  self._patch_dunder(name)
103
- return self.stream.getvalue()
102
+ return "\n".join(f" {d}" for d in self.data)
104
103
 
105
104
  def _patch_dunder(self, name: str) -> None:
106
105
  if name == "Count":
@@ -141,7 +140,7 @@ class _MethodsAnnotator(abc.ABC, Generic[_T_MTD]):
141
140
  self._define_member(content)
142
141
 
143
142
  def _define_member(self, content: str) -> None:
144
- print(f" {content}", file=self.stream)
143
+ self.data.append(content)
145
144
 
146
145
  def _gen_method(self, name: str, mth: _T_MTD) -> None:
147
146
  self._define_member(self.to_method_annotator(mth).getvalue(name))
@@ -237,13 +236,13 @@ class ComMethodAnnotator(_MethodAnnotator[typedesc.ComMethod]):
237
236
  # should be a special callback.
238
237
  inargs.append("**kwargs: Any")
239
238
  break
240
- inargs.append(f"{argname}: Any")
239
+ inargs.append(f"{argname}: hints.Incomplete")
241
240
  else:
242
- inargs.append(f"{argname}: Any = ...")
241
+ inargs.append(f"{argname}: hints.Incomplete = ...")
243
242
  has_optional = True
244
- outargs = ["Any" for _ in self._iter_outarg_specs()]
243
+ outargs = ["hints.Incomplete" for _ in self._iter_outarg_specs()]
245
244
  if not outargs:
246
- out = "Any"
245
+ out = "hints.Hresult"
247
246
  elif len(outargs) == 1:
248
247
  out = outargs[0]
249
248
  else:
@@ -280,11 +279,11 @@ class DispMethodAnnotator(_MethodAnnotator[typedesc.DispMethod]):
280
279
  # should be a special callback.
281
280
  inargs.append("**kwargs: Any")
282
281
  break
283
- inargs.append(f"{argname}: Any")
282
+ inargs.append(f"{argname}: hints.Incomplete")
284
283
  else:
285
- inargs.append(f"{argname}: Any = ...")
284
+ inargs.append(f"{argname}: hints.Incomplete = ...")
286
285
  has_optional = True
287
- out = "Any"
286
+ out = "hints.Incomplete"
288
287
  in_ = ("self, " + ", ".join(inargs)) if inargs else "self"
289
288
  return f"def {name}({in_}) -> {out}: ..."
290
289
 
@@ -297,7 +296,6 @@ class DispMethodsAnnotator(_MethodsAnnotator[typedesc.DispMethod]):
297
296
  class DispInterfaceMembersAnnotator(object):
298
297
  def __init__(self, itf: typedesc.DispInterface):
299
298
  self.itf = itf
300
- self.stream = io.StringIO()
301
299
 
302
300
  def _categorize_members(
303
301
  self,
@@ -313,7 +311,11 @@ class DispInterfaceMembersAnnotator(object):
313
311
 
314
312
  def generate(self) -> str:
315
313
  props, methods = self._categorize_members()
314
+ property_lines: List[str] = []
316
315
  for mem in props:
317
- print(" @property # dispprop", file=self.stream)
318
- print(f" def {mem.name}(self) -> Any: ...", file=self.stream)
319
- return self.stream.getvalue() + DispMethodsAnnotator().generate(methods)
316
+ property_lines.append("@property # dispprop")
317
+ out = "hints.Incomplete"
318
+ property_lines.append(f"def {mem.name}(self) -> {out}: ...")
319
+ dispprops = "\n".join(f" {p}" for p in property_lines)
320
+ dispmethods = DispMethodsAnnotator().generate(methods)
321
+ return "\n".join(d for d in (dispprops, dispmethods) if d)
@@ -176,7 +176,7 @@ class ComInterface(object):
176
176
  self,
177
177
  name: str,
178
178
  members: List[ComMethod],
179
- base: Any,
179
+ base: "Optional[ComInterface]",
180
180
  iid: str,
181
181
  idlflags: List[str],
182
182
  ) -> None:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: comtypes
3
- Version: 1.4.1
3
+ Version: 1.4.2
4
4
  Summary: Pure Python COM package
5
5
  Home-page: https://github.com/enthought/comtypes
6
6
  Download-URL: https://github.com/enthought/comtypes/releases
@@ -68,6 +68,7 @@ comtypes/test/test_casesensitivity.py
68
68
  comtypes/test/test_clear_cache.py
69
69
  comtypes/test/test_client.py
70
70
  comtypes/test/test_client_dynamic.py
71
+ comtypes/test/test_client_regenerate_modules.py
71
72
  comtypes/test/test_collections.py
72
73
  comtypes/test/test_comserver.py
73
74
  comtypes/test/test_createwrappers.py
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes