comtypes 1.4.2__zip → 1.4.4__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 (121) hide show
  1. {comtypes-1.4.2 → comtypes-1.4.4}/CHANGES.txt +22 -2
  2. {comtypes-1.4.2/comtypes.egg-info → comtypes-1.4.4}/PKG-INFO +30 -3
  3. {comtypes-1.4.2 → comtypes-1.4.4}/README.md +28 -1
  4. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/__init__.py +6 -8
  5. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/automation.py +26 -2
  6. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/hints.pyi +15 -0
  7. comtypes-1.4.4/comtypes/test/mylib.tlb +0 -0
  8. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_GUID.py +23 -2
  9. comtypes-1.4.4/comtypes/test/test_dispifc_records.py +90 -0
  10. comtypes-1.4.4/comtypes/test/test_findgendir.py +87 -0
  11. comtypes-1.4.4/comtypes/test/urlhist.tlb +0 -0
  12. comtypes-1.4.4/comtypes/tools/codegenerator/__init__.py +5 -0
  13. {comtypes-1.4.2/comtypes/tools → comtypes-1.4.4/comtypes/tools/codegenerator}/codegenerator.py +56 -721
  14. comtypes-1.4.4/comtypes/tools/codegenerator/helpers.py +357 -0
  15. comtypes-1.4.4/comtypes/tools/codegenerator/modulenamer.py +24 -0
  16. comtypes-1.4.4/comtypes/tools/codegenerator/namespaces.py +212 -0
  17. comtypes-1.4.4/comtypes/tools/codegenerator/packing.py +81 -0
  18. {comtypes-1.4.2/comtypes/tools → comtypes-1.4.4/comtypes/tools/codegenerator}/typeannotator.py +18 -3
  19. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/tools/tlbparser.py +19 -49
  20. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/tools/typedesc.py +57 -9
  21. {comtypes-1.4.2 → comtypes-1.4.4/comtypes.egg-info}/PKG-INFO +30 -3
  22. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes.egg-info/SOURCES.txt +13 -3
  23. comtypes-1.4.4/pyproject.toml +3 -0
  24. comtypes-1.4.4/setup.cfg +51 -0
  25. comtypes-1.4.4/setup.py +117 -0
  26. comtypes-1.4.2/comtypes/test/test_findgendir.py +0 -94
  27. comtypes-1.4.2/setup.cfg +0 -4
  28. comtypes-1.4.2/setup.py +0 -172
  29. {comtypes-1.4.2 → comtypes-1.4.4}/LICENSE.txt +0 -0
  30. {comtypes-1.4.2 → comtypes-1.4.4}/MANIFEST.in +0 -0
  31. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/GUID.py +0 -0
  32. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/_comobject.py +0 -0
  33. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/_memberspec.py +0 -0
  34. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/_meta.py +0 -0
  35. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/_npsupport.py +0 -0
  36. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/_safearray.py +0 -0
  37. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/clear_cache.py +0 -0
  38. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/client/__init__.py +0 -0
  39. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/client/_code_cache.py +0 -0
  40. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/client/_constants.py +0 -0
  41. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/client/_events.py +0 -0
  42. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/client/_generate.py +0 -0
  43. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/client/dynamic.py +0 -0
  44. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/client/lazybind.py +0 -0
  45. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/connectionpoints.py +0 -0
  46. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/errorinfo.py +0 -0
  47. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/git.py +0 -0
  48. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/hresult.py +0 -0
  49. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/logutil.py +0 -0
  50. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/messageloop.py +0 -0
  51. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/patcher.py +0 -0
  52. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/persist.py +0 -0
  53. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/safearray.py +0 -0
  54. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/server/__init__.py +0 -0
  55. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/server/automation.py +0 -0
  56. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/server/connectionpoints.py +0 -0
  57. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/server/inprocserver.py +0 -0
  58. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/server/localserver.py +0 -0
  59. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/server/register.py +0 -0
  60. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/server/w_getopt.py +0 -0
  61. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/shelllink.py +0 -0
  62. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/TestComServer.idl +0 -0
  63. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/TestComServer.py +0 -0
  64. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/TestComServer.tlb +0 -0
  65. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/TestDispServer.idl +0 -0
  66. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/TestDispServer.py +0 -0
  67. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/TestDispServer.tlb +0 -0
  68. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/__init__.py +0 -0
  69. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/find_memleak.py +0 -0
  70. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/mylib.idl +0 -0
  71. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/mytypelib.idl +0 -0
  72. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/runtests.py +0 -0
  73. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/setup.py +0 -0
  74. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_BSTR.py +0 -0
  75. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_DISPPARAMS.py +0 -0
  76. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_QueryService.py +0 -0
  77. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_agilent.py +0 -0
  78. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_avmc.py +0 -0
  79. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_basic.py +0 -0
  80. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_casesensitivity.py +0 -0
  81. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_clear_cache.py +0 -0
  82. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_client.py +0 -0
  83. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_client_dynamic.py +0 -0
  84. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_client_regenerate_modules.py +0 -0
  85. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_collections.py +0 -0
  86. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_comserver.py +0 -0
  87. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_createwrappers.py +0 -0
  88. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_dict.py +0 -0
  89. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_dispinterface.py +0 -0
  90. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_dyndispatch.py +0 -0
  91. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_excel.py +0 -0
  92. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_getactiveobj.py +0 -0
  93. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_ie.py +0 -0
  94. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_ienum.py +0 -0
  95. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_imfattributes.py +0 -0
  96. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_inout_args.py +0 -0
  97. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_jscript.js +0 -0
  98. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_msscript.py +0 -0
  99. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_npsupport.py +0 -0
  100. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_outparam.py +0 -0
  101. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_propputref.py +0 -0
  102. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_pump_events.py +0 -0
  103. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_safearray.py +0 -0
  104. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_sapi.py +0 -0
  105. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_server.py +0 -0
  106. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_showevents.py +0 -0
  107. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_subinterface.py +0 -0
  108. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_typeinfo.py +0 -0
  109. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_urlhistory.py +0 -0
  110. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_variant.py +0 -0
  111. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_win32com_interop.py +0 -0
  112. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_wmi.py +0 -0
  113. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/test/test_word.py +0 -0
  114. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/tools/__init__.py +0 -0
  115. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/tools/typedesc_base.py +0 -0
  116. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/typeinfo.py +0 -0
  117. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/util.py +0 -0
  118. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes/viewobject.py +0 -0
  119. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes.egg-info/dependency_links.txt +0 -0
  120. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes.egg-info/entry_points.txt +0 -0
  121. {comtypes-1.4.2 → comtypes-1.4.4}/comtypes.egg-info/top_level.txt +0 -0
@@ -216,6 +216,21 @@ class _MethodsAnnotator(abc.ABC, Generic[_T_MTD]):
216
216
  self._define_normal_prop(name, setter=setter)
217
217
 
218
218
 
219
+ def _to_outtype(typ: Any) -> str:
220
+ if isinstance(typ, typedesc.PointerType):
221
+ return _to_outtype(typ.typ)
222
+ elif isinstance(typ, typedesc.DispInterface):
223
+ return f"'{typ.name}'"
224
+ elif isinstance(typ, typedesc.ComInterface):
225
+ return f"'{typ.name}'"
226
+ elif isinstance(typ, typedesc.CoClass):
227
+ impl, _ = typedesc.groupby_impltypeflags(typ.interfaces)
228
+ if impl:
229
+ meta = f"hints.FirstComItfOf['{typ.name}']"
230
+ return f"hints.Annotated[{_to_outtype(impl[0])}, {meta}]"
231
+ return "hints.Incomplete"
232
+
233
+
219
234
  class ComMethodAnnotator(_MethodAnnotator[typedesc.ComMethod]):
220
235
  def _iter_outarg_specs(self) -> Iterator[Tuple[Any, str]]:
221
236
  for typ, name, flags, _ in self.method.arguments:
@@ -240,7 +255,7 @@ class ComMethodAnnotator(_MethodAnnotator[typedesc.ComMethod]):
240
255
  else:
241
256
  inargs.append(f"{argname}: hints.Incomplete = ...")
242
257
  has_optional = True
243
- outargs = ["hints.Incomplete" for _ in self._iter_outarg_specs()]
258
+ outargs = [_to_outtype(ot) for ot, _ in self._iter_outarg_specs()]
244
259
  if not outargs:
245
260
  out = "hints.Hresult"
246
261
  elif len(outargs) == 1:
@@ -283,7 +298,7 @@ class DispMethodAnnotator(_MethodAnnotator[typedesc.DispMethod]):
283
298
  else:
284
299
  inargs.append(f"{argname}: hints.Incomplete = ...")
285
300
  has_optional = True
286
- out = "hints.Incomplete"
301
+ out = _to_outtype(self.method.returns)
287
302
  in_ = ("self, " + ", ".join(inargs)) if inargs else "self"
288
303
  return f"def {name}({in_}) -> {out}: ..."
289
304
 
@@ -314,7 +329,7 @@ class DispInterfaceMembersAnnotator(object):
314
329
  property_lines: List[str] = []
315
330
  for mem in props:
316
331
  property_lines.append("@property # dispprop")
317
- out = "hints.Incomplete"
332
+ out = _to_outtype(mem.typ)
318
333
  property_lines.append(f"def {mem.name}(self) -> {out}: ...")
319
334
  dispprops = "\n".join(f" {p}" for p in property_lines)
320
335
  dispmethods = DispMethodsAnnotator().generate(methods)
@@ -1,20 +1,10 @@
1
- from __future__ import print_function
2
1
  import os
3
2
  import sys
4
- from typing import (
5
- Any,
6
- Callable,
7
- Dict,
8
- List,
9
- Optional,
10
- Type,
11
- TypeVar,
12
- Tuple,
13
- Union as _UnionT,
14
- )
15
- from ctypes import alignment, c_void_p, _Pointer, sizeof, windll
3
+ from typing import Any
4
+ from typing import Dict, List, Optional, Tuple
5
+ from ctypes import alignment, byref, c_void_p, sizeof, windll
16
6
 
17
- from comtypes import automation, _CData, COMError, typeinfo
7
+ from comtypes import automation, BSTR, COMError, typeinfo
18
8
  from comtypes.tools import typedesc
19
9
  from comtypes.client._code_cache import _get_module_filename
20
10
 
@@ -267,10 +257,8 @@ class Parser(object):
267
257
  assert vd.varkind == typeinfo.VAR_CONST
268
258
  typ = self.make_type(vd.elemdescVar.tdesc, tinfo)
269
259
  var_value = vd._.lpvarValue[0].value
270
- v = typedesc.Constant(name, typ, var_value)
260
+ v = typedesc.Constant(name, typ, var_value, var_doc)
271
261
  self._register(name, v)
272
- if var_doc is not None:
273
- v.doc = var_doc
274
262
 
275
263
  # TKIND_INTERFACE = 3
276
264
  def ParseInterface(
@@ -289,15 +277,9 @@ class Parser(object):
289
277
  warnings.warn(message, UserWarning)
290
278
  return None
291
279
 
292
- itf = typedesc.ComInterface(
293
- itf_name,
294
- members=[],
295
- base=None,
296
- iid=str(ta.guid),
297
- idlflags=self.interface_type_flags(ta.wTypeFlags),
298
- )
299
- if itf_doc:
300
- itf.doc = itf_doc
280
+ iid = str(ta.guid)
281
+ idlflags = self.interface_type_flags(ta.wTypeFlags)
282
+ itf = typedesc.ComInterface(itf_name, None, iid, idlflags, itf_doc)
301
283
  self._register(itf_name, itf)
302
284
 
303
285
  if ta.cImplTypes:
@@ -307,7 +289,7 @@ class Parser(object):
307
289
 
308
290
  assert ta.cVars == 0, "vars on an Interface?"
309
291
 
310
- members = []
292
+ members: List[Tuple[int, typedesc.ComMethod]] = []
311
293
  for i in range(ta.cFuncs):
312
294
  fd = tinfo.GetFuncDesc(i)
313
295
  func_name, func_doc = tinfo.GetDocumentation(fd.memid)[:2]
@@ -341,7 +323,7 @@ class Parser(object):
341
323
  # Sort the methods by oVft (VTable offset): Some typeinfo
342
324
  # don't list methods in VTable order.
343
325
  members.sort()
344
- itf.members.extend([m[1] for m in members])
326
+ itf.extend_members([m for _, m in members])
345
327
 
346
328
  return itf
347
329
 
@@ -351,20 +333,13 @@ class Parser(object):
351
333
  ) -> typedesc.DispInterface:
352
334
  itf_name, doc = tinfo.GetDocumentation(-1)[0:2]
353
335
  assert ta.cImplTypes == 1
354
-
355
336
  hr = tinfo.GetRefTypeOfImplType(0)
356
337
  tibase = tinfo.GetRefTypeInfo(hr)
357
338
  base = self.parse_typeinfo(tibase)
358
- members = []
359
- itf = typedesc.DispInterface(
360
- itf_name,
361
- members=members,
362
- base=base,
363
- iid=str(ta.guid),
364
- idlflags=self.interface_type_flags(ta.wTypeFlags),
365
- )
366
- if doc is not None:
367
- itf.doc = str(doc.split("\0")[0])
339
+ iid = str(ta.guid)
340
+ idlflags = self.interface_type_flags(ta.wTypeFlags)
341
+ doc = str(doc.split("\0")[0]) if doc is not None else doc
342
+ itf = typedesc.DispInterface(itf_name, base, iid, idlflags, doc)
368
343
  self._register(itf_name, itf)
369
344
 
370
345
  # This code can only handle pure dispinterfaces. Dual
@@ -379,7 +354,7 @@ class Parser(object):
379
354
  mth = typedesc.DispProperty(
380
355
  vd.memid, var_name, typ, self.var_flags(vd.wVarFlags), var_doc
381
356
  )
382
- itf.members.append(mth)
357
+ itf.add_member(mth)
383
358
 
384
359
  # At least the EXCEL typelib lists the IUnknown and IDispatch
385
360
  # methods even for this kind of interface. I didn't find any
@@ -430,7 +405,7 @@ class Parser(object):
430
405
  else:
431
406
  default = None
432
407
  mth.add_argument(typ, name, self.param_flags(flags), default)
433
- itf.members.append(mth)
408
+ itf.add_member(mth)
434
409
  return itf
435
410
 
436
411
  def inv_kind(self, invkind: int) -> List[str]:
@@ -548,11 +523,9 @@ class Parser(object):
548
523
  # version, control, hidden, and appobject
549
524
  coclass_name, doc = tinfo.GetDocumentation(-1)[0:2]
550
525
  tlibattr = tinfo.GetContainingTypeLib()[0].GetLibAttr()
551
- coclass = typedesc.CoClass(
552
- coclass_name, str(ta.guid), self.coclass_type_flags(ta.wTypeFlags), tlibattr
553
- )
554
- if doc is not None:
555
- coclass.doc = doc
526
+ clsid = str(ta.guid)
527
+ idlflags = self.coclass_type_flags(ta.wTypeFlags)
528
+ coclass = typedesc.CoClass(coclass_name, clsid, idlflags, tlibattr, doc)
556
529
  self._register(coclass_name, coclass)
557
530
 
558
531
  for i in range(ta.cImplTypes):
@@ -763,9 +736,6 @@ class TypeLibParser(Parser):
763
736
  def get_tlib_filename(tlib):
764
737
  # seems if the typelib is not registered, there's no way to
765
738
  # determine the filename.
766
- from ctypes import windll, byref
767
- from comtypes import BSTR
768
-
769
739
  la = tlib.GetLibAttr()
770
740
  name = BSTR()
771
741
  try:
@@ -2,8 +2,9 @@
2
2
  # in typedesc_base
3
3
 
4
4
  import ctypes
5
- from typing import Any, List, Optional, Tuple, Union as _UnionT
5
+ from typing import Any, List, Optional, Sequence, Tuple, Union as _UnionT
6
6
 
7
+ from comtypes import typeinfo
7
8
  from comtypes.typeinfo import ITypeLib, TLIBATTR
8
9
  from comtypes.tools.typedesc_base import *
9
10
 
@@ -29,11 +30,16 @@ class TypeLib(object):
29
30
 
30
31
  class Constant(object):
31
32
  def __init__(
32
- self, name: str, typ: _UnionT[Typedef, FundamentalType], value: Any
33
+ self,
34
+ name: str,
35
+ typ: _UnionT[Typedef, FundamentalType],
36
+ value: Any,
37
+ doc: Optional[str],
33
38
  ) -> None:
34
39
  self.name = name
35
40
  self.typ = typ
36
41
  self.value = value
42
+ self.doc = doc
37
43
 
38
44
 
39
45
  class External(object):
@@ -141,18 +147,22 @@ class DispInterface(object):
141
147
  def __init__(
142
148
  self,
143
149
  name: str,
144
- members: List[_UnionT[DispMethod, DispProperty]],
145
150
  base: Any,
146
151
  iid: str,
147
152
  idlflags: List[str],
153
+ doc: Optional[str],
148
154
  ) -> None:
149
155
  self.name = name
150
- self.members = members
156
+ self.members: List[_UnionT[DispMethod, DispProperty]] = []
151
157
  self.base = base
152
158
  self.iid = iid
153
159
  self.idlflags = idlflags
154
160
  self.itf_head = DispInterfaceHead(self)
155
161
  self.itf_body = DispInterfaceBody(self)
162
+ self.doc = doc
163
+
164
+ def add_member(self, member: _UnionT[DispMethod, DispProperty]) -> None:
165
+ self.members.append(member)
156
166
 
157
167
  def get_body(self) -> DispInterfaceBody:
158
168
  return self.itf_body
@@ -175,18 +185,22 @@ class ComInterface(object):
175
185
  def __init__(
176
186
  self,
177
187
  name: str,
178
- members: List[ComMethod],
179
188
  base: "Optional[ComInterface]",
180
189
  iid: str,
181
190
  idlflags: List[str],
191
+ doc: Optional[str],
182
192
  ) -> None:
183
193
  self.name = name
184
- self.members = members
194
+ self.members: List[ComMethod] = []
185
195
  self.base = base
186
196
  self.iid = iid
187
197
  self.idlflags = idlflags
188
198
  self.itf_head = ComInterfaceHead(self)
189
199
  self.itf_body = ComInterfaceBody(self)
200
+ self.doc = doc
201
+
202
+ def extend_members(self, members: Sequence[ComMethod]) -> None:
203
+ self.members.extend(members)
190
204
 
191
205
  def get_body(self) -> ComInterfaceBody:
192
206
  return self.itf_body
@@ -195,15 +209,49 @@ class ComInterface(object):
195
209
  return self.itf_head
196
210
 
197
211
 
212
+ _ImplTypeFlags = int
213
+ _Interface = _UnionT[ComInterface, DispInterface]
214
+
215
+
198
216
  class CoClass(object):
199
217
  def __init__(
200
- self, name: str, clsid: str, idlflags: List[str], tlibattr: TLIBATTR
218
+ self,
219
+ name: str,
220
+ clsid: str,
221
+ idlflags: List[str],
222
+ tlibattr: TLIBATTR,
223
+ doc: Optional[str],
201
224
  ) -> None:
202
225
  self.name = name
203
226
  self.clsid = clsid
204
227
  self.idlflags = idlflags
205
228
  self.tlibattr = tlibattr
206
- self.interfaces: List[Tuple[Any, int]] = []
229
+ self.interfaces: List[Tuple[_Interface, _ImplTypeFlags]] = []
230
+ self.doc = doc
207
231
 
208
- def add_interface(self, itf: Any, idlflags: int) -> None:
232
+ def add_interface(self, itf: _Interface, idlflags: _ImplTypeFlags) -> None:
209
233
  self.interfaces.append((itf, idlflags))
234
+
235
+
236
+ _ImplementedInterfaces = Sequence[_Interface]
237
+ _SourceInterfaces = Sequence[_Interface]
238
+
239
+
240
+ def groupby_impltypeflags(
241
+ seq: Sequence[Tuple[_Interface, _ImplTypeFlags]]
242
+ ) -> Tuple[_ImplementedInterfaces, _SourceInterfaces]:
243
+ implemented = []
244
+ sources = []
245
+ for itf, impltypeflags in seq:
246
+ if impltypeflags & typeinfo.IMPLTYPEFLAG_FSOURCE:
247
+ # source interface
248
+ where = sources
249
+ else:
250
+ # sink interface
251
+ where = implemented
252
+ if impltypeflags & typeinfo.IMPLTYPEFLAG_FDEFAULT:
253
+ # The default interface should be the first item on the list
254
+ where.insert(0, itf)
255
+ else:
256
+ where.append(itf)
257
+ return implemented, sources
@@ -1,12 +1,11 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: comtypes
3
- Version: 1.4.2
3
+ Version: 1.4.4
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
7
7
  Author: Thomas Heller
8
8
  Author-email: theller@python.net
9
- License: MIT License
10
9
  Classifier: Development Status :: 5 - Production/Stable
11
10
  Classifier: Intended Audience :: Developers
12
11
  Classifier: License :: OSI Approved :: MIT License
@@ -14,6 +13,7 @@ Classifier: Operating System :: Microsoft :: Windows
14
13
  Classifier: Programming Language :: Python
15
14
  Classifier: Programming Language :: Python :: 3
16
15
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
16
+ Requires-Python: >=3.7
17
17
  Description-Content-Type: text/markdown
18
18
  License-File: LICENSE.txt
19
19
 
@@ -31,7 +31,6 @@ License-File: LICENSE.txt
31
31
  `comtypes` allows to define, call, and implement custom and dispatch-based COM interfaces in pure `Python`.
32
32
 
33
33
  This package works on Windows only.
34
- - [`comtypes==1.1.7`](https://pypi.org/project/comtypes/1.1.7/) is the last version supporting Windows CE.
35
34
 
36
35
  Available on `Python` 3.7-3.12.
37
36
  - [`comtypes==1.2.1`](https://pypi.org/project/comtypes/1.2.1/) is the last version supporting `Python` 2.7 and 3.3-3.6.
@@ -75,6 +74,34 @@ This project and the maintainers of thousands of other packages are working with
75
74
 
76
75
  [Learn more](https://tidelift.com/subscription/pkg/pypi-comtypes?utm_source=pypi-comtypes&utm_medium=referral&utm_campaign=github).
77
76
 
77
+ ## Frequently Asked Questions
78
+
79
+ ### Q: Why does this package not support platforms other than Windows?
80
+ **A:** [The Microsoft Component Object Model (COM)](https://learn.microsoft.com/en-us/windows/win32/com/com-technical-overview) is a technology that is unique to Windows and is not supported on other platforms.
81
+
82
+ [The phrase _"COM is a platform-independent"_ in the MS documentation](https://learn.microsoft.com/en-us/windows/win32/com/component-object-model--com--portal) means that COM maintains compatibility across different versions of Windows, and does NOT imply that it is supported on Linux or Mac.
83
+
84
+ As long as COM is not supported outside of Windows, this project does not plan to port to other platforms.
85
+
86
+ ### Q: Why does `cannot import name 'COMError' from '_ctypes'` error occur when using this package on platforms other than Windows?
87
+ **A:** The [`_ctypes`](https://github.com/python/cpython/blob/main/Modules/_ctypes/_ctypes.c) is part of the internal implementation of the [`ctypes`](https://github.com/python/cpython/blob/main/Lib/ctypes/) standard library that exists for Python on all platforms.
88
+ However, `COMError` and COM-related features are implemented only in Python for Windows.
89
+
90
+ In cross-platform software development, care must be taken to ensure that codebase dependent on `comtypes` does not execute in environments other than Windows.
91
+
92
+ ### Q: Despite a script that depends on `comtypes` having run successfully before, a error (`ImportError`, `NameError`, or `SyntaxError`) is raised now, and the same error occurs again and again.
93
+
94
+ **A:** Executing `py -m comtypes.clear_cache` and then running the script again might resolve the problem.
95
+
96
+ When `comtypes.client.GetModule` is called (either directly or indirectly), `comtypes` generates Python module files.
97
+ If Python is forced to terminate or crashes in the middle of file generation, the codebase written to the file becomes partial.
98
+ When Python tries to import this unexecutable partial codebase module, an error occurs.
99
+
100
+ Executing `py -m comtypes.clear_cache` identifies the directories where the "cache module files" are stored and deletes them.
101
+ After deleting these partial modules and running the script again, `comtypes.client.GetModule` is called and executable modules are generated anew.
102
+
103
+ However, if the script implementation does not use `comtypes.client.GetModule` or processes generated files, it may not be a solution.
104
+
78
105
  ## Documentation:
79
106
 
80
107
  The documentation is currently hosted on pythonhosted at:
@@ -2,6 +2,8 @@ CHANGES.txt
2
2
  LICENSE.txt
3
3
  MANIFEST.in
4
4
  README.md
5
+ pyproject.toml
6
+ setup.cfg
5
7
  setup.py
6
8
  comtypes/GUID.py
7
9
  comtypes/__init__.py
@@ -54,6 +56,7 @@ comtypes/test/TestDispServer.tlb
54
56
  comtypes/test/__init__.py
55
57
  comtypes/test/find_memleak.py
56
58
  comtypes/test/mylib.idl
59
+ comtypes/test/mylib.tlb
57
60
  comtypes/test/mytypelib.idl
58
61
  comtypes/test/runtests.py
59
62
  comtypes/test/setup.py
@@ -73,6 +76,7 @@ comtypes/test/test_collections.py
73
76
  comtypes/test/test_comserver.py
74
77
  comtypes/test/test_createwrappers.py
75
78
  comtypes/test/test_dict.py
79
+ comtypes/test/test_dispifc_records.py
76
80
  comtypes/test/test_dispinterface.py
77
81
  comtypes/test/test_dyndispatch.py
78
82
  comtypes/test/test_excel.py
@@ -99,9 +103,15 @@ comtypes/test/test_variant.py
99
103
  comtypes/test/test_win32com_interop.py
100
104
  comtypes/test/test_wmi.py
101
105
  comtypes/test/test_word.py
106
+ comtypes/test/urlhist.tlb
102
107
  comtypes/tools/__init__.py
103
- comtypes/tools/codegenerator.py
104
108
  comtypes/tools/tlbparser.py
105
- comtypes/tools/typeannotator.py
106
109
  comtypes/tools/typedesc.py
107
- comtypes/tools/typedesc_base.py
110
+ comtypes/tools/typedesc_base.py
111
+ comtypes/tools/codegenerator/__init__.py
112
+ comtypes/tools/codegenerator/codegenerator.py
113
+ comtypes/tools/codegenerator/helpers.py
114
+ comtypes/tools/codegenerator/modulenamer.py
115
+ comtypes/tools/codegenerator/namespaces.py
116
+ comtypes/tools/codegenerator/packing.py
117
+ comtypes/tools/codegenerator/typeannotator.py
@@ -0,0 +1,3 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.2"]
3
+ build-backend = "setuptools.build_meta"
@@ -0,0 +1,51 @@
1
+ [metadata]
2
+ name = comtypes
3
+ description = Pure Python COM package
4
+ author = Thomas Heller
5
+ author_email = theller@python.net
6
+ url = https://github.com/enthought/comtypes
7
+ download_url = https://github.com/enthought/comtypes/releases
8
+ version = attr:comtypes.__version__
9
+ long_description = file:README.md
10
+ long_description_content_type = text/markdown
11
+ classifiers =
12
+ Development Status :: 5 - Production/Stable
13
+ Intended Audience :: Developers
14
+ License :: OSI Approved :: MIT License
15
+ Operating System :: Microsoft :: Windows
16
+ Programming Language :: Python
17
+ Programming Language :: Python :: 3
18
+ Topic :: Software Development :: Libraries :: Python Modules
19
+
20
+ [options]
21
+ python_requires = >=3.7
22
+ packages =
23
+ comtypes
24
+ comtypes.client
25
+ comtypes.server
26
+ comtypes.tools
27
+ comtypes.tools.codegenerator
28
+ comtypes.test
29
+
30
+ [options.package_data]
31
+ comtypes.test =
32
+ TestComServer.idl
33
+ TestComServer.tlb
34
+ TestDispServer.idl
35
+ TestDispServer.tlb
36
+ mytypelib.idl
37
+ mylib.idl
38
+ mylib.tlb
39
+ urlhist.tlb
40
+ test_jscript.js
41
+ comtypes =
42
+ hints.pyi
43
+
44
+ [options.entry_points]
45
+ console_scripts =
46
+ clear_comtypes_cache = comtypes.clear_cache:main
47
+
48
+ [egg_info]
49
+ tag_build =
50
+ tag_date = 0
51
+
@@ -0,0 +1,117 @@
1
+ """comtypes package install script"""
2
+
3
+ import sys
4
+ import os
5
+ import subprocess
6
+
7
+ from setuptools import Command, setup
8
+ from setuptools.command.install import install
9
+
10
+
11
+ class test(Command):
12
+ # Original version of this class posted
13
+ # by Berthold Hoellmann to distutils-sig@python.org
14
+ description = "run tests"
15
+
16
+ user_options = [
17
+ ('tests=', 't', "comma-separated list of packages that contain test modules"),
18
+ (
19
+ 'use-resources=',
20
+ 'u',
21
+ "resources to use - resource names are defined by tests",
22
+ ),
23
+ (
24
+ 'refcounts',
25
+ 'r',
26
+ "repeat tests to search for refcount leaks (requires "
27
+ "'sys.gettotalrefcount')",
28
+ ),
29
+ ]
30
+
31
+ boolean_options = ["refcounts"]
32
+
33
+ def initialize_options(self):
34
+ self.use_resources = ""
35
+ self.refcounts = False
36
+ self.tests = "comtypes.test"
37
+ self.failure = False
38
+
39
+ def finalize_options(self):
40
+ if self.refcounts and not hasattr(sys, "gettotalrefcount"):
41
+ raise Exception("refcount option requires Python debug build")
42
+ self.tests = self.tests.split(",")
43
+ self.use_resources = self.use_resources.split(",")
44
+
45
+ def run(self):
46
+ build = self.reinitialize_command('build')
47
+ build.run()
48
+ if build.build_lib is not None:
49
+ sys.path.insert(0, build.build_lib)
50
+
51
+ # Register our ATL COM tester dll
52
+ import comtypes.test
53
+
54
+ script_path = os.path.dirname(__file__)
55
+ source_dir = os.path.abspath(os.path.join(script_path, "source"))
56
+ comtypes.test.register_server(source_dir)
57
+
58
+ comtypes.test.use_resources.extend(self.use_resources)
59
+ for name in self.tests:
60
+ package = __import__(name, globals(), locals(), ['*'])
61
+ sys.stdout.write(
62
+ "Testing package %s %s\n" % (name, (sys.version, sys.platform, os.name))
63
+ )
64
+ package_failure = comtypes.test.run_tests(
65
+ package, "test_*.py", self.verbose, self.refcounts
66
+ )
67
+ self.failure = self.failure or package_failure
68
+
69
+
70
+ class post_install(install):
71
+ # both this static variable and method initialize_options() help to avoid
72
+ # weird setuptools error with "pip install comtypes", details are here:
73
+ # https://github.com/enthought/comtypes/issues/155
74
+ # the working solution was found here:
75
+ # https://github.com/pypa/setuptools/blob/3b90be7bb6323eb44d0f28864509c1d47aa098de/setuptools/command/install.py
76
+ user_options = install.user_options + [
77
+ ('old-and-unmanageable', None, "Try not to use this!"),
78
+ (
79
+ 'single-version-externally-managed',
80
+ None,
81
+ "used by system package builders to create 'flat' eggs",
82
+ ),
83
+ ]
84
+
85
+ def initialize_options(self):
86
+ install.initialize_options(self)
87
+ self.old_and_unmanageable = None
88
+ self.single_version_externally_managed = None
89
+
90
+ def run(self):
91
+ install.run(self)
92
+ # Custom script we run at the end of installing
93
+ if not self.dry_run and not self.root:
94
+ print("Executing post install script...")
95
+ print(f'"{sys.executable}" -m comtypes.clear_cache -y')
96
+ try:
97
+ subprocess.check_call([
98
+ sys.executable,
99
+ "-m",
100
+ "comtypes.clear_cache",
101
+ '-y',
102
+ ])
103
+ except subprocess.CalledProcessError:
104
+ print("Failed to run post install script!")
105
+
106
+
107
+ if __name__ == '__main__':
108
+ dist = setup(
109
+ cmdclass={
110
+ 'test': test,
111
+ 'install': post_install,
112
+ },
113
+ )
114
+ # Exit with a failure code if only running the tests and they failed
115
+ if dist.commands == ['test']:
116
+ command = dist.command_obj['test']
117
+ sys.exit(command.failure)