comtypes 1.4.8__zip → 1.4.10__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 (154) hide show
  1. {comtypes-1.4.8 → comtypes-1.4.10}/CHANGES.txt +40 -0
  2. {comtypes-1.4.8/comtypes.egg-info → comtypes-1.4.10}/PKG-INFO +4 -3
  3. {comtypes-1.4.8 → comtypes-1.4.10}/README.md +1 -1
  4. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/GUID.py +38 -16
  5. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/__init__.py +36 -16
  6. comtypes-1.4.10/comtypes/_comobject.py +562 -0
  7. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/_memberspec.py +93 -13
  8. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/_meta.py +1 -0
  9. comtypes-1.4.10/comtypes/_post_coinit/_cominterface_meta_patcher.py +152 -0
  10. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/_post_coinit/bstr.py +12 -5
  11. comtypes-1.4.8/comtypes/_py_instance_method.py → comtypes-1.4.10/comtypes/_post_coinit/instancemethod.py +1 -2
  12. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/_post_coinit/misc.py +60 -25
  13. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/_post_coinit/unknwn.py +26 -176
  14. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/_safearray.py +3 -4
  15. comtypes-1.4.10/comtypes/_vtbl.py +448 -0
  16. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/automation.py +46 -49
  17. comtypes-1.4.10/comtypes/client/__init__.py +42 -0
  18. comtypes-1.4.10/comtypes/client/_activeobj.py +46 -0
  19. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/client/_code_cache.py +10 -5
  20. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/client/_constants.py +1 -1
  21. comtypes-1.4.10/comtypes/client/_create.py +147 -0
  22. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/client/_events.py +58 -13
  23. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/client/_generate.py +7 -11
  24. comtypes-1.4.10/comtypes/client/_managing.py +114 -0
  25. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/client/dynamic.py +2 -3
  26. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/client/lazybind.py +12 -13
  27. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/connectionpoints.py +2 -1
  28. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/errorinfo.py +22 -9
  29. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/git.py +5 -5
  30. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/hints.pyi +7 -15
  31. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/logutil.py +15 -3
  32. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/messageloop.py +1 -1
  33. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/persist.py +3 -5
  34. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/safearray.py +17 -5
  35. comtypes-1.4.10/comtypes/server/__init__.py +104 -0
  36. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/server/automation.py +1 -2
  37. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/server/connectionpoints.py +5 -5
  38. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/server/inprocserver.py +25 -17
  39. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/server/localserver.py +49 -19
  40. comtypes-1.4.10/comtypes/server/register.py +478 -0
  41. comtypes-1.4.10/comtypes/server/w_getopt.py +48 -0
  42. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/shelllink.py +16 -33
  43. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/stream.py +7 -4
  44. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/TestComServer.py +6 -7
  45. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/TestDispServer.py +4 -2
  46. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/__init__.py +10 -12
  47. comtypes-1.4.10/comtypes/test/find_memleak.py +72 -0
  48. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/runtests.py +1 -0
  49. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/setup.py +2 -1
  50. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_BSTR.py +10 -23
  51. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_GUID.py +1 -0
  52. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_QueryService.py +1 -0
  53. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_agilent.py +4 -3
  54. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_avmc.py +1 -1
  55. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_basic.py +12 -6
  56. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_casesensitivity.py +3 -5
  57. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_clear_cache.py +1 -1
  58. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_client.py +2 -2
  59. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_client_dynamic.py +2 -2
  60. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_client_regenerate_modules.py +2 -2
  61. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_collections.py +4 -4
  62. comtypes-1.4.10/comtypes/test/test_comobject.py +146 -0
  63. comtypes-1.4.10/comtypes/test/test_comserver.py +349 -0
  64. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_createwrappers.py +2 -4
  65. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_dispifc_records.py +1 -1
  66. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_dispifc_safearrays.py +1 -1
  67. comtypes-1.4.10/comtypes/test/test_dispinterface.py +153 -0
  68. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_dyndispatch.py +1 -0
  69. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_excel.py +22 -12
  70. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_findgendir.py +1 -2
  71. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_getactiveobj.py +4 -4
  72. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_ie.py +19 -9
  73. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_ienum.py +2 -2
  74. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_imfattributes.py +13 -3
  75. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_inout_args.py +8 -5
  76. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_midl_safearray_create.py +14 -4
  77. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_monikers.py +23 -9
  78. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_msscript.py +2 -1
  79. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_npsupport.py +4 -4
  80. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_outparam.py +37 -14
  81. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_persist.py +2 -4
  82. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_recordinfo.py +1 -1
  83. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_safearray.py +1 -90
  84. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_sapi.py +4 -1
  85. comtypes-1.4.10/comtypes/test/test_server.py +350 -0
  86. comtypes-1.4.10/comtypes/test/test_server_register.py +524 -0
  87. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_shelllink.py +2 -3
  88. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_showevents.py +7 -17
  89. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_storage.py +12 -6
  90. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_stream.py +16 -5
  91. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_subinterface.py +4 -2
  92. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_typeannotator.py +1 -2
  93. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_typeinfo.py +19 -7
  94. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_urlhistory.py +7 -4
  95. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_variant.py +3 -19
  96. comtypes-1.4.10/comtypes/test/test_w_getopt.py +29 -0
  97. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_win32com_interop.py +80 -36
  98. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_wmi.py +0 -3
  99. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_word.py +1 -1
  100. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/tools/codegenerator/codegenerator.py +166 -440
  101. comtypes-1.4.10/comtypes/tools/codegenerator/comments.py +79 -0
  102. comtypes-1.4.10/comtypes/tools/codegenerator/heads.py +192 -0
  103. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/tools/codegenerator/helpers.py +11 -14
  104. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/tools/codegenerator/namespaces.py +13 -5
  105. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/tools/codegenerator/packing.py +4 -4
  106. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/tools/codegenerator/typeannotator.py +19 -9
  107. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/tools/tlbparser.py +22 -23
  108. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/tools/typedesc.py +4 -8
  109. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/tools/typedesc_base.py +2 -2
  110. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/typeinfo.py +159 -63
  111. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/viewobject.py +3 -9
  112. {comtypes-1.4.8 → comtypes-1.4.10/comtypes.egg-info}/PKG-INFO +4 -3
  113. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes.egg-info/SOURCES.txt +11 -3
  114. {comtypes-1.4.8 → comtypes-1.4.10}/pyproject.toml +12 -19
  115. comtypes-1.4.8/comtypes/_comobject.py +0 -833
  116. comtypes-1.4.8/comtypes/_idl_stuff.py +0 -67
  117. comtypes-1.4.8/comtypes/client/__init__.py +0 -323
  118. comtypes-1.4.8/comtypes/server/__init__.py +0 -70
  119. comtypes-1.4.8/comtypes/server/register.py +0 -431
  120. comtypes-1.4.8/comtypes/server/w_getopt.py +0 -75
  121. comtypes-1.4.8/comtypes/test/find_memleak.py +0 -76
  122. comtypes-1.4.8/comtypes/test/test_comserver.py +0 -239
  123. comtypes-1.4.8/comtypes/test/test_dispinterface.py +0 -137
  124. comtypes-1.4.8/comtypes/test/test_propputref.py +0 -40
  125. comtypes-1.4.8/comtypes/test/test_server.py +0 -354
  126. {comtypes-1.4.8 → comtypes-1.4.10}/LICENSE.txt +0 -0
  127. {comtypes-1.4.8 → comtypes-1.4.10}/MANIFEST.in +0 -0
  128. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/_npsupport.py +0 -0
  129. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/_post_coinit/__init__.py +0 -0
  130. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/_tlib_version_checker.py +0 -0
  131. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/clear_cache.py +0 -0
  132. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/hresult.py +0 -0
  133. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/patcher.py +0 -0
  134. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/TestComServer.idl +0 -0
  135. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/TestComServer.tlb +0 -0
  136. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/TestDispServer.idl +0 -0
  137. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/TestDispServer.tlb +0 -0
  138. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/mylib.idl +0 -0
  139. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/mylib.tlb +0 -0
  140. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/mytypelib.idl +0 -0
  141. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_DISPPARAMS.py +0 -0
  142. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_dict.py +0 -0
  143. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_jscript.js +0 -0
  144. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/test_pump_events.py +0 -0
  145. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/test/urlhist.tlb +0 -0
  146. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/tools/__init__.py +0 -0
  147. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/tools/codegenerator/__init__.py +0 -0
  148. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/tools/codegenerator/modulenamer.py +0 -0
  149. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes/util.py +0 -0
  150. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes.egg-info/dependency_links.txt +0 -0
  151. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes.egg-info/entry_points.txt +0 -0
  152. {comtypes-1.4.8 → comtypes-1.4.10}/comtypes.egg-info/top_level.txt +0 -0
  153. {comtypes-1.4.8 → comtypes-1.4.10}/setup.cfg +0 -0
  154. {comtypes-1.4.8 → comtypes-1.4.10}/setup.py +0 -0
@@ -0,0 +1,79 @@
1
+ import io
2
+
3
+ from comtypes.tools import typedesc
4
+
5
+
6
+ class ComInterfaceBodyImplCommentWriter(object):
7
+ def __init__(self, stream: io.StringIO):
8
+ self.stream = stream
9
+
10
+ def write(self, body: typedesc.ComInterfaceBody) -> None:
11
+ print(
12
+ "################################################################",
13
+ file=self.stream,
14
+ )
15
+ print(f"# code template for {body.itf.name} implementation", file=self.stream)
16
+ print(f"# class {body.itf.name}_Impl(object):", file=self.stream)
17
+
18
+ methods = {}
19
+ for m in body.itf.members:
20
+ if isinstance(m, typedesc.ComMethod):
21
+ # m.arguments is a sequence of tuples:
22
+ # (argtype, argname, idlflags, docstring)
23
+ # Some typelibs have unnamed method parameters!
24
+ inargs = [a[1] or "<unnamed>" for a in m.arguments if "out" not in a[2]]
25
+ outargs = [a[1] or "<unnamed>" for a in m.arguments if "out" in a[2]]
26
+ if "propget" in m.idlflags:
27
+ methods.setdefault(m.name, [0, inargs, outargs, m.doc])[0] |= 1
28
+ elif "propput" in m.idlflags:
29
+ methods.setdefault(m.name, [0, inargs[:-1], inargs[-1:], m.doc])[
30
+ 0
31
+ ] |= 2
32
+ else:
33
+ methods[m.name] = [0, inargs, outargs, m.doc]
34
+
35
+ for name, (typ, inargs, outargs, doc) in methods.items():
36
+ if typ == 0: # method
37
+ print(
38
+ f"# def {name}({', '.join(['self'] + inargs)}):",
39
+ file=self.stream,
40
+ )
41
+ print(f"# {(doc or '-no docstring-')!r}", file=self.stream)
42
+ print(f"# #return {', '.join(outargs)}", file=self.stream)
43
+ elif typ == 1: # propget
44
+ print("# @property", file=self.stream)
45
+ print(
46
+ f"# def {name}({', '.join(['self'] + inargs)}):",
47
+ file=self.stream,
48
+ )
49
+ print(f"# {(doc or '-no docstring-')!r}", file=self.stream)
50
+ print(f"# #return {', '.join(outargs)}", file=self.stream)
51
+ elif typ == 2: # propput
52
+ print(
53
+ f"# def _set({', '.join(['self'] + inargs + outargs)}):",
54
+ file=self.stream,
55
+ )
56
+ print(f"# {(doc or '-no docstring-')!r}", file=self.stream)
57
+ print(
58
+ f"# {name} = property(fset = _set, doc = _set.__doc__)",
59
+ file=self.stream,
60
+ )
61
+ elif typ == 3: # propget + propput
62
+ print(
63
+ f"# def _get({', '.join(['self'] + inargs)}):",
64
+ file=self.stream,
65
+ )
66
+ print(f"# {(doc or '-no docstring-')!r}", file=self.stream)
67
+ print(f"# #return {', '.join(outargs)}", file=self.stream)
68
+ print(
69
+ f"# def _set({', '.join(['self'] + inargs + outargs)}):",
70
+ file=self.stream,
71
+ )
72
+ print(f"# {(doc or '-no docstring-')!r}", file=self.stream)
73
+ print(
74
+ f"# {name} = property(_get, _set, doc = _set.__doc__)",
75
+ file=self.stream,
76
+ )
77
+ else:
78
+ raise RuntimeError("BUG")
79
+ print("#", file=self.stream)
@@ -0,0 +1,192 @@
1
+ import io
2
+ from typing import Optional, Sequence
3
+
4
+ from comtypes.tools import typedesc
5
+ from comtypes.tools.codegenerator import typeannotator
6
+
7
+
8
+ def _to_docstring(orig: str, depth: int = 1) -> str:
9
+ # increasing `depth` by one increases indentation by one
10
+ indent = " " * depth
11
+ # some chars are replaced to avoid causing a `SyntaxError`
12
+ repled = orig.replace("\\", r"\\").replace('"', r"'")
13
+ return f'{indent}"""{repled}"""'
14
+
15
+
16
+ class StructureHeadWriter(object):
17
+ def __init__(self, stream: io.StringIO) -> None:
18
+ self.stream = stream
19
+
20
+ def write(self, head: typedesc.StructureHead, basenames: Sequence[str]) -> None:
21
+ if head.struct.location:
22
+ print(f"# {head.struct.location}", file=self.stream)
23
+ if basenames:
24
+ method_names = [
25
+ m.name for m in head.struct.members if type(m) is typedesc.Method
26
+ ]
27
+ print(
28
+ f"class {head.struct.name}({', '.join(basenames)}):",
29
+ file=self.stream,
30
+ )
31
+ print(
32
+ " _iid_ = GUID('{}') # please look up iid and fill in!",
33
+ file=self.stream,
34
+ )
35
+ if "Enum" in method_names:
36
+ print(" def __iter__(self):", file=self.stream)
37
+ print(" return self.Enum()", file=self.stream)
38
+ elif method_names == "Next Skip Reset Clone".split():
39
+ print(" def __iter__(self):", file=self.stream)
40
+ print(" return self", file=self.stream)
41
+ print(file=self.stream)
42
+ print(" def next(self):", file=self.stream)
43
+ print(" arr, fetched = self.Next(1)", file=self.stream)
44
+ print(" if fetched == 0:", file=self.stream)
45
+ print(" raise StopIteration", file=self.stream)
46
+ print(" return arr[0]", file=self.stream)
47
+
48
+ else:
49
+ methods = [m for m in head.struct.members if type(m) is typedesc.Method]
50
+
51
+ if methods:
52
+ # Hm. We cannot generate code for IUnknown...
53
+ print("assert 0, 'cannot generate code for IUnknown'", file=self.stream)
54
+ print(f"class {head.struct.name}(_com_interface):", file=self.stream)
55
+ print(" pass", file=self.stream)
56
+ elif type(head.struct) is typedesc.Structure:
57
+ print(f"class {head.struct.name}(Structure):", file=self.stream)
58
+ if hasattr(head.struct, "_recordinfo_"):
59
+ print(
60
+ f" _recordinfo_ = {head.struct._recordinfo_!r}",
61
+ file=self.stream,
62
+ )
63
+ else:
64
+ print(" pass", file=self.stream)
65
+ elif type(head.struct) is typedesc.Union:
66
+ print(f"class {head.struct.name}(Union):", file=self.stream)
67
+ print(" pass", file=self.stream)
68
+
69
+
70
+ class LibraryHeadWriter(object):
71
+ def __init__(self, stream: io.StringIO) -> None:
72
+ self.stream = stream
73
+
74
+ def write(self, lib: typedesc.TypeLib) -> None:
75
+ # Hm, in user code we have to write:
76
+ # class MyServer(COMObject, ...):
77
+ # _com_interfaces_ = [MyTypeLib.IInterface]
78
+ # _reg_typelib_ = MyTypeLib.Library._reg_typelib_
79
+ # ^^^^^^^
80
+ # Should the '_reg_typelib_' attribute be at top-level in the
81
+ # generated code, instead as being an attribute of the
82
+ # 'Library' symbol?
83
+ print("class Library(object):", file=self.stream)
84
+ if lib.doc:
85
+ print(_to_docstring(lib.doc), file=self.stream)
86
+
87
+ if lib.name:
88
+ print(f" name = {lib.name!r}", file=self.stream)
89
+
90
+ print(
91
+ f" _reg_typelib_ = ({lib.guid!r}, {lib.major!r}, {lib.minor!r})",
92
+ file=self.stream,
93
+ )
94
+
95
+
96
+ class CoClassHeadWriter(object):
97
+ def __init__(self, stream: io.StringIO, filename: Optional[str]) -> None:
98
+ self.stream = stream
99
+ self.filename = filename
100
+
101
+ def write(self, coclass: typedesc.CoClass) -> None:
102
+ print(f"class {coclass.name}(CoClass):", file=self.stream)
103
+ if coclass.doc:
104
+ print(_to_docstring(coclass.doc), file=self.stream)
105
+ print(f" _reg_clsid_ = GUID({coclass.clsid!r})", file=self.stream)
106
+ print(f" _idlflags_ = {coclass.idlflags}", file=self.stream)
107
+ if self.filename is not None:
108
+ print(" _typelib_path_ = typelib_path", file=self.stream)
109
+ # X print
110
+ # >> self.stream, "POINTER(%s).__ctypes_from_outparam__ = wrap" % coclass.name
111
+
112
+ libid = coclass.tlibattr.guid
113
+ wMajor, wMinor = coclass.tlibattr.wMajorVerNum, coclass.tlibattr.wMinorVerNum
114
+ print(
115
+ f" _reg_typelib_ = ({str(libid)!r}, {wMajor}, {wMinor})",
116
+ file=self.stream,
117
+ )
118
+
119
+
120
+ class ComInterfaceHeadWriter(object):
121
+ def __init__(self, stream: io.StringIO) -> None:
122
+ self.stream = stream
123
+
124
+ def _is_enuminterface(self, itf: typedesc.ComInterface) -> bool:
125
+ # Check if this is an IEnumXXX interface
126
+ if not itf.name.startswith("IEnum"):
127
+ return False
128
+ member_names = [mth.name for mth in itf.members]
129
+ for name in ("Next", "Skip", "Reset", "Clone"):
130
+ if name not in member_names:
131
+ return False
132
+ return True
133
+
134
+ def write(self, head: typedesc.ComInterfaceHead, basename: str) -> None:
135
+ if head.itf.base is None:
136
+ # we don't beed to generate IUnknown
137
+ return
138
+
139
+ print(f"class {head.itf.name}({basename}):", file=self.stream)
140
+ if head.itf.doc:
141
+ print(_to_docstring(head.itf.doc), file=self.stream)
142
+
143
+ print(" _case_insensitive_ = True", file=self.stream)
144
+ print(f" _iid_ = GUID({head.itf.iid!r})", file=self.stream)
145
+ print(f" _idlflags_ = {head.itf.idlflags}", file=self.stream)
146
+
147
+ if self._is_enuminterface(head.itf):
148
+ print(file=self.stream)
149
+ print(" def __iter__(self):", file=self.stream)
150
+ print(" return self", file=self.stream)
151
+ print(file=self.stream)
152
+
153
+ print(" def __next__(self):", file=self.stream)
154
+ print(" item, fetched = self.Next(1)", file=self.stream)
155
+ print(" if fetched:", file=self.stream)
156
+ print(" return item", file=self.stream)
157
+ print(" raise StopIteration", file=self.stream)
158
+ print(file=self.stream)
159
+
160
+ print(" def __getitem__(self, index):", file=self.stream)
161
+ print(" self.Reset()", file=self.stream)
162
+ print(" self.Skip(index)", file=self.stream)
163
+ print(" item, fetched = self.Next(1)", file=self.stream)
164
+ print(" if fetched:", file=self.stream)
165
+ print(" return item", file=self.stream)
166
+ print(" raise IndexError(index)", file=self.stream)
167
+
168
+ annotations = typeannotator.ComInterfaceMembersAnnotator(head.itf).generate()
169
+ if annotations:
170
+ print(file=self.stream)
171
+ print(" if TYPE_CHECKING: # commembers", file=self.stream)
172
+ print(annotations, file=self.stream)
173
+
174
+
175
+ class DispInterfaceHeadWriter(object):
176
+ def __init__(self, stream: io.StringIO) -> None:
177
+ self.stream = stream
178
+
179
+ def write(self, head: typedesc.DispInterfaceHead, basename: str) -> None:
180
+ print(f"class {head.itf.name}({basename}):", file=self.stream)
181
+ if head.itf.doc:
182
+ print(_to_docstring(head.itf.doc), file=self.stream)
183
+ print(" _case_insensitive_ = True", file=self.stream)
184
+ print(f" _iid_ = GUID({head.itf.iid!r})", file=self.stream)
185
+ print(f" _idlflags_ = {head.itf.idlflags}", file=self.stream)
186
+ print(" _methods_ = []", file=self.stream)
187
+
188
+ annotations = typeannotator.DispInterfaceMembersAnnotator(head.itf).generate()
189
+ if annotations:
190
+ print(file=self.stream)
191
+ print(" if TYPE_CHECKING: # dispmembers", file=self.stream)
192
+ print(annotations, file=self.stream)
@@ -1,10 +1,7 @@
1
1
  import keyword
2
- from typing import Any
3
- from typing import List, Tuple
4
- from typing import Iterator
2
+ from typing import Any, Iterator, List, Tuple
5
3
  from typing import Union as _UnionT
6
4
 
7
- import comtypes
8
5
  from comtypes.tools import typedesc
9
6
  from comtypes.tools.codegenerator.modulenamer import name_wrapper_module
10
7
 
@@ -22,7 +19,7 @@ class dispid(object):
22
19
  self.memid = memid
23
20
 
24
21
  def __repr__(self):
25
- return "dispid(%s)" % self.memid
22
+ return f"dispid({self.memid})"
26
23
 
27
24
 
28
25
  class helpstring(object):
@@ -30,7 +27,7 @@ class helpstring(object):
30
27
  self.text = text
31
28
 
32
29
  def __repr__(self):
33
- return "helpstring(%r)" % self.text
30
+ return f"helpstring({self.text!r})"
34
31
 
35
32
 
36
33
  # XXX Should this be in ctypes itself?
@@ -299,25 +296,25 @@ class TypeNamer(object):
299
296
  # to refer to the type. Assumes the 'from ctypes import *'
300
297
  # namespace is available.
301
298
  if isinstance(t, typedesc.SAFEARRAYType):
302
- return "_midlSAFEARRAY(%s)" % self(t.typ)
299
+ return f"_midlSAFEARRAY({self(t.typ)})"
303
300
  # if isinstance(t, typedesc.CoClass):
304
301
  # return "%s._com_interfaces_[0]" % t.name
305
302
  if isinstance(t, typedesc.Typedef):
306
303
  return t.name
307
304
  if isinstance(t, typedesc.PointerType):
308
305
  _t, pcnt = self._inspect_PointerType(t)
309
- return "%s%s%s" % ("POINTER(" * pcnt, self(_t), ")" * pcnt)
306
+ return f"{'POINTER(' * pcnt}{self(_t)}{')' * pcnt}"
310
307
  elif isinstance(t, typedesc.ArrayType):
311
- return "%s * %s" % (self(t.typ), int(t.max) + 1)
308
+ return f"{self(t.typ)} * {int(t.max) + 1}"
312
309
  elif isinstance(t, typedesc.FunctionType):
313
310
  args = [self(x) for x in [t.returns] + list(t.iterArgTypes())]
314
311
  if "__stdcall__" in t.attributes:
315
- return "WINFUNCTYPE(%s)" % ", ".join(args)
312
+ return f"WINFUNCTYPE({', '.join(args)})"
316
313
  else:
317
- return "CFUNCTYPE(%s)" % ", ".join(args)
314
+ return f"CFUNCTYPE({', '.join(args)})"
318
315
  elif isinstance(t, typedesc.CvQualifiedType):
319
316
  # const and volatile are ignored
320
- return "%s" % self(t.typ)
317
+ return f"{self(t.typ)}"
321
318
  elif isinstance(t, typedesc.FundamentalType):
322
319
  return ctypes_names[t.name]
323
320
  elif isinstance(t, typedesc.Structure):
@@ -328,13 +325,13 @@ class TypeNamer(object):
328
325
  return "c_int" # enums are integers
329
326
  elif isinstance(t, typedesc.EnumValue):
330
327
  if keyword.iskeyword(t.name):
331
- return t.name + "_"
328
+ return f"{t.name}_"
332
329
  return t.name
333
330
  elif isinstance(t, typedesc.External):
334
331
  # t.symbol_name - symbol to generate
335
332
  # t.tlib - the ITypeLib pointer to the typelibrary containing the symbols definition
336
333
  modname = name_wrapper_module(t.tlib)
337
- return "%s.%s" % (modname, t.symbol_name)
334
+ return f"{modname}.{t.symbol_name}"
338
335
  return t.name
339
336
 
340
337
  def _inspect_PointerType(
@@ -1,10 +1,18 @@
1
- from collections import Counter
2
1
  import textwrap
3
- from typing import overload
4
- from typing import Optional, Union as _UnionT
5
- from typing import Dict, List, Set, Tuple
6
- from typing import Iterator, Mapping, Sequence
7
2
  import warnings
3
+ from collections import Counter
4
+ from typing import (
5
+ Dict,
6
+ Iterator,
7
+ List,
8
+ Mapping,
9
+ Optional,
10
+ Sequence,
11
+ Set,
12
+ Tuple,
13
+ overload,
14
+ )
15
+ from typing import Union as _UnionT
8
16
 
9
17
 
10
18
  class ImportedNamespaces(object):
@@ -25,20 +25,20 @@ def _calc_packing(struct, fields, pack, isStruct):
25
25
  size += a - size % a
26
26
  if isStruct:
27
27
  if size != f.offset:
28
- raise PackingError("field %s offset (%s/%s)" % (f.name, size, f.offset))
28
+ raise PackingError(f"field {f.name} offset ({size}/{f.offset})")
29
29
  size += s
30
30
  else:
31
31
  size = max(size, s)
32
32
  total_align = max(total_align, a)
33
33
  if total_align != struct.align:
34
- raise PackingError("total alignment (%s/%s)" % (total_align, struct.align))
34
+ raise PackingError(f"total alignment ({total_align}/{struct.align})")
35
35
  a = total_align
36
36
  if pack is not None:
37
37
  a = min(pack, a)
38
38
  if size % a:
39
39
  size += a - size % a
40
40
  if size != struct.size:
41
- raise PackingError("total size (%s/%s)" % (size, struct.size))
41
+ raise PackingError(f"total size ({size}/{struct.size})")
42
42
 
43
43
 
44
44
  def calc_packing(struct, fields):
@@ -55,7 +55,7 @@ def calc_packing(struct, fields):
55
55
 
56
56
  return int(pack / 8)
57
57
 
58
- raise PackingError("PACKING FAILED: %s" % details)
58
+ raise PackingError(f"PACKING FAILED: {details}")
59
59
 
60
60
 
61
61
  class PackingError(Exception):
@@ -1,19 +1,29 @@
1
1
  import abc
2
2
  import keyword
3
- from typing import Any, Generic, TypeVar, TYPE_CHECKING
4
- from typing import Dict, List, Optional, Sequence, Tuple
5
- from typing import Iterable, Iterator
3
+ from typing import (
4
+ Any,
5
+ Dict,
6
+ Generic,
7
+ Iterable,
8
+ Iterator,
9
+ List,
10
+ Optional,
11
+ Protocol,
12
+ Sequence,
13
+ Tuple,
14
+ TypeVar,
15
+ )
6
16
 
7
17
  from comtypes.tools import typedesc
8
18
 
9
- if TYPE_CHECKING:
10
- from comtypes import hints
11
19
 
20
+ class _MethodTypeDesc(Protocol):
21
+ arguments: List[Tuple[Any, str, List[str], Optional[Any]]]
22
+ idlflags: List[str]
23
+ name: str
12
24
 
13
- if TYPE_CHECKING:
14
- _T_MTD = TypeVar("_T_MTD", bound=hints._MethodTypeDesc)
15
- else:
16
- _T_MTD = TypeVar("_T_MTD")
25
+
26
+ _T_MTD = TypeVar("_T_MTD", bound=_MethodTypeDesc)
17
27
 
18
28
 
19
29
  class _MethodAnnotator(abc.ABC, Generic[_T_MTD]):
@@ -1,13 +1,11 @@
1
1
  import os
2
2
  import sys
3
- from typing import Any
4
- from typing import Dict, List, Optional, Tuple
5
- from ctypes import alignment, byref, c_void_p, sizeof, windll
3
+ from ctypes import alignment, c_void_p, sizeof, windll
4
+ from typing import Any, Dict, List, Optional, Tuple
6
5
 
7
- from comtypes import automation, BSTR, COMError, typeinfo
8
- from comtypes.tools import typedesc
6
+ from comtypes import BSTR, COMError, automation, typeinfo
9
7
  from comtypes.client._code_cache import _get_module_filename
10
-
8
+ from comtypes.tools import typedesc
11
9
 
12
10
  # Is the process 64-bit?
13
11
  is_64bits = sys.maxsize > 2**32
@@ -237,7 +235,7 @@ class Parser(object):
237
235
  elif fd.callconv == typeinfo.CC_STDCALL:
238
236
  attributes = "__stdcall__"
239
237
  else:
240
- raise ValueError("calling convention %d" % fd.callconv)
238
+ raise ValueError(f"calling convention {fd.callconv:d}")
241
239
 
242
240
  func = typedesc.Function(func_name, returns, attributes, extern=1)
243
241
  if func_doc is not None:
@@ -741,28 +739,29 @@ def get_tlib_filename(tlib: typeinfo.ITypeLib) -> Optional[str]:
741
739
  # seems if the typelib is not registered, there's no way to
742
740
  # determine the filename.
743
741
  la = tlib.GetLibAttr()
744
- name = BSTR()
745
- if 0 == windll.oleaut32.QueryPathOfRegTypeLib(
746
- byref(la.guid), la.wMajorVerNum, la.wMinorVerNum, 0, byref(name)
747
- ):
748
- full_filename = name.value.split("\0")[0]
749
- if not os.path.isabs(full_filename):
750
- # workaround Windows 7 bug in QueryPathOfRegTypeLib returning relative path
751
- try:
752
- dll = windll.LoadLibrary(full_filename)
753
- full_filename = _get_module_filename(dll._handle)
754
- del dll
755
- except OSError:
756
- return None
757
- return full_filename
758
- return None
742
+ try:
743
+ full_filename = typeinfo.QueryPathOfRegTypeLib(
744
+ str(la.guid), la.wMajorVerNum, la.wMinorVerNum
745
+ )
746
+ except OSError:
747
+ return None
748
+
749
+ if not os.path.isabs(full_filename):
750
+ # workaround Windows 7 bug in QueryPathOfRegTypeLib returning relative path
751
+ try:
752
+ dll = windll.LoadLibrary(full_filename)
753
+ full_filename = _get_module_filename(dll._handle)
754
+ del dll
755
+ except OSError:
756
+ return None
757
+ return full_filename
759
758
 
760
759
 
761
760
  def _py2exe_hint():
762
761
  # If the tlbparser is frozen, we need to include these
762
+ import comtypes.automation
763
763
  import comtypes.persist
764
764
  import comtypes.typeinfo
765
- import comtypes.automation
766
765
 
767
766
 
768
767
  # -eof-
@@ -2,11 +2,12 @@
2
2
  # in typedesc_base
3
3
 
4
4
  import ctypes
5
- from typing import Any, List, Optional, Sequence, Tuple, Union as _UnionT
5
+ from typing import Any, List, Optional, Sequence, Tuple
6
+ from typing import Union as _UnionT
6
7
 
7
8
  from comtypes import typeinfo
8
- from comtypes.typeinfo import ITypeLib, TLIBATTR
9
9
  from comtypes.tools.typedesc_base import *
10
+ from comtypes.typeinfo import TLIBATTR, ITypeLib
10
11
 
11
12
 
12
13
  class TypeLib(object):
@@ -20,12 +21,7 @@ class TypeLib(object):
20
21
  self.doc = doc
21
22
 
22
23
  def __repr__(self):
23
- return "<TypeLib(%s: %s, %s, %s)>" % (
24
- self.name,
25
- self.guid,
26
- self.major,
27
- self.minor,
28
- )
24
+ return f"<TypeLib({self.name}: {self.guid}, {self.major}, {self.minor})>"
29
25
 
30
26
 
31
27
  class Constant(object):
@@ -1,6 +1,6 @@
1
1
  # typedesc.py - classes representing C type descriptions
2
- from typing import Any, SupportsInt
3
- from typing import List, Optional, Tuple, Union as _UnionT
2
+ from typing import Any, List, Optional, SupportsInt, Tuple
3
+ from typing import Union as _UnionT
4
4
 
5
5
  import comtypes
6
6