comtypes 1.4.6__zip → 1.4.8__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 (138) hide show
  1. {comtypes-1.4.6 → comtypes-1.4.8}/CHANGES.txt +36 -0
  2. {comtypes-1.4.6/comtypes.egg-info → comtypes-1.4.8}/PKG-INFO +32 -38
  3. {comtypes-1.4.6 → comtypes-1.4.8}/README.md +30 -36
  4. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/__init__.py +1 -1
  5. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/_comobject.py +0 -1
  6. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/_memberspec.py +1 -1
  7. comtypes-1.4.8/comtypes/_meta.py +95 -0
  8. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/_npsupport.py +2 -1
  9. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/_post_coinit/__init__.py +1 -0
  10. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/_post_coinit/bstr.py +13 -6
  11. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/_post_coinit/misc.py +20 -39
  12. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/_post_coinit/unknwn.py +94 -69
  13. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/automation.py +9 -15
  14. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/client/__init__.py +21 -31
  15. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/client/_code_cache.py +1 -0
  16. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/client/_events.py +0 -1
  17. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/client/_generate.py +5 -5
  18. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/client/lazybind.py +0 -5
  19. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/git.py +1 -0
  20. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/hints.pyi +6 -4
  21. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/persist.py +19 -3
  22. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/safearray.py +2 -6
  23. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/server/__init__.py +1 -0
  24. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/server/register.py +1 -0
  25. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/shelllink.py +90 -34
  26. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/test/TestComServer.py +1 -1
  27. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/test/TestDispServer.py +1 -1
  28. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/test/__init__.py +0 -1
  29. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/test/find_memleak.py +0 -1
  30. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/test/test_agilent.py +0 -1
  31. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/test/test_clear_cache.py +1 -0
  32. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/test/test_client.py +9 -0
  33. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/test/test_createwrappers.py +0 -2
  34. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/test/test_dispinterface.py +0 -1
  35. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/test/test_excel.py +0 -1
  36. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/test/test_inout_args.py +1 -1
  37. comtypes-1.4.8/comtypes/test/test_monikers.py +70 -0
  38. comtypes-1.4.8/comtypes/test/test_persist.py +40 -0
  39. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/test/test_server.py +6 -0
  40. comtypes-1.4.8/comtypes/test/test_shelllink.py +129 -0
  41. comtypes-1.4.8/comtypes/test/test_storage.py +127 -0
  42. comtypes-1.4.8/comtypes/test/test_stream.py +131 -0
  43. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/test/test_typeannotator.py +1 -1
  44. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/test/test_urlhistory.py +1 -0
  45. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/test/test_variant.py +0 -2
  46. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/tools/codegenerator/namespaces.py +97 -27
  47. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/tools/codegenerator/typeannotator.py +2 -4
  48. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/tools/tlbparser.py +33 -32
  49. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/tools/typedesc.py +2 -2
  50. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/typeinfo.py +42 -43
  51. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/util.py +1 -0
  52. {comtypes-1.4.6 → comtypes-1.4.8/comtypes.egg-info}/PKG-INFO +32 -38
  53. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes.egg-info/SOURCES.txt +5 -1
  54. comtypes-1.4.8/pyproject.toml +54 -0
  55. {comtypes-1.4.6 → comtypes-1.4.8}/setup.cfg +1 -1
  56. comtypes-1.4.6/comtypes/_meta.py +0 -70
  57. comtypes-1.4.6/comtypes/test/test_istream.py +0 -53
  58. comtypes-1.4.6/pyproject.toml +0 -3
  59. {comtypes-1.4.6 → comtypes-1.4.8}/LICENSE.txt +0 -0
  60. {comtypes-1.4.6 → comtypes-1.4.8}/MANIFEST.in +0 -0
  61. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/GUID.py +0 -0
  62. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/_idl_stuff.py +0 -0
  63. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/_py_instance_method.py +0 -0
  64. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/_safearray.py +0 -0
  65. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/_tlib_version_checker.py +0 -0
  66. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/clear_cache.py +0 -0
  67. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/client/_constants.py +0 -0
  68. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/client/dynamic.py +0 -0
  69. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/connectionpoints.py +0 -0
  70. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/errorinfo.py +0 -0
  71. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/hresult.py +0 -0
  72. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/logutil.py +0 -0
  73. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/messageloop.py +0 -0
  74. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/patcher.py +0 -0
  75. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/server/automation.py +0 -0
  76. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/server/connectionpoints.py +0 -0
  77. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/server/inprocserver.py +0 -0
  78. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/server/localserver.py +0 -0
  79. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/server/w_getopt.py +0 -0
  80. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/stream.py +0 -0
  81. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/test/TestComServer.idl +0 -0
  82. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/test/TestComServer.tlb +0 -0
  83. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/test/TestDispServer.idl +0 -0
  84. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/test/TestDispServer.tlb +0 -0
  85. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/test/mylib.idl +0 -0
  86. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/test/mylib.tlb +0 -0
  87. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/test/mytypelib.idl +0 -0
  88. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/test/runtests.py +0 -0
  89. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/test/setup.py +0 -0
  90. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/test/test_BSTR.py +0 -0
  91. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/test/test_DISPPARAMS.py +0 -0
  92. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/test/test_GUID.py +0 -0
  93. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/test/test_QueryService.py +0 -0
  94. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/test/test_avmc.py +0 -0
  95. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/test/test_basic.py +0 -0
  96. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/test/test_casesensitivity.py +0 -0
  97. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/test/test_client_dynamic.py +0 -0
  98. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/test/test_client_regenerate_modules.py +0 -0
  99. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/test/test_collections.py +0 -0
  100. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/test/test_comserver.py +0 -0
  101. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/test/test_dict.py +0 -0
  102. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/test/test_dispifc_records.py +0 -0
  103. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/test/test_dispifc_safearrays.py +0 -0
  104. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/test/test_dyndispatch.py +0 -0
  105. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/test/test_findgendir.py +0 -0
  106. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/test/test_getactiveobj.py +0 -0
  107. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/test/test_ie.py +0 -0
  108. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/test/test_ienum.py +0 -0
  109. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/test/test_imfattributes.py +0 -0
  110. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/test/test_jscript.js +0 -0
  111. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/test/test_midl_safearray_create.py +0 -0
  112. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/test/test_msscript.py +0 -0
  113. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/test/test_npsupport.py +0 -0
  114. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/test/test_outparam.py +0 -0
  115. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/test/test_propputref.py +0 -0
  116. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/test/test_pump_events.py +0 -0
  117. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/test/test_recordinfo.py +0 -0
  118. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/test/test_safearray.py +0 -0
  119. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/test/test_sapi.py +0 -0
  120. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/test/test_showevents.py +0 -0
  121. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/test/test_subinterface.py +0 -0
  122. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/test/test_typeinfo.py +0 -0
  123. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/test/test_win32com_interop.py +0 -0
  124. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/test/test_wmi.py +0 -0
  125. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/test/test_word.py +0 -0
  126. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/test/urlhist.tlb +0 -0
  127. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/tools/__init__.py +0 -0
  128. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/tools/codegenerator/__init__.py +0 -0
  129. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/tools/codegenerator/codegenerator.py +0 -0
  130. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/tools/codegenerator/helpers.py +0 -0
  131. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/tools/codegenerator/modulenamer.py +0 -0
  132. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/tools/codegenerator/packing.py +0 -0
  133. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/tools/typedesc_base.py +0 -0
  134. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes/viewobject.py +0 -0
  135. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes.egg-info/dependency_links.txt +0 -0
  136. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes.egg-info/entry_points.txt +0 -0
  137. {comtypes-1.4.6 → comtypes-1.4.8}/comtypes.egg-info/top_level.txt +0 -0
  138. {comtypes-1.4.6 → comtypes-1.4.8}/setup.py +0 -0
@@ -69,12 +69,37 @@ class _cominterface_meta(type):
69
69
  def __new__(cls, name, bases, namespace):
70
70
  methods = namespace.pop("_methods_", None)
71
71
  dispmethods = namespace.pop("_disp_methods_", None)
72
- new_cls = type.__new__(cls, name, bases, namespace)
72
+ self = type.__new__(cls, name, bases, namespace)
73
73
 
74
74
  if methods is not None:
75
- new_cls._methods_ = methods
75
+ self._methods_ = methods
76
76
  if dispmethods is not None:
77
- new_cls._disp_methods_ = dispmethods
77
+ self._disp_methods_ = dispmethods
78
+
79
+ # ` _compointer_meta` is a subclass inherited from `_cominterface_meta`.
80
+ # `_compointer_base` uses `_compointer_meta` as its metaclass.
81
+ # In other words, when the `__new__` method of this metaclass is called,
82
+ # `_compointer_base` type or an subclass of it might be created and assigned
83
+ # to `self`.
84
+ if bases == (c_void_p,):
85
+ # `self` is the `_compointer_base` type.
86
+ # On some versions of Python, `_compointer_base` is not yet available in
87
+ # the accessible namespace at this point in its initialization, and
88
+ # referencing it could raise a `NameError`.
89
+ # This metaclass is intended to be used only as a base class for defining
90
+ # the `_compointer_meta` or as the metaclass for the `IUnknown`, so the
91
+ # situation where the `bases` parameter is `(c_void_p,)` is limited to when
92
+ # the `_compointer_meta` is specified as the metaclass of the
93
+ # `_compointer_base`.
94
+ # Prevent specifying the metaclass type instance in the `bases` parameter
95
+ # when instantiating it, as this would lead to infinite recursion.
96
+ return self
97
+ if issubclass(self, _compointer_base):
98
+ # `self` is a `POINTER(interface)` type.
99
+ # Prevent creating/registering a pointer to a pointer (to a pointer...),
100
+ # which would lead to infinite recursion.
101
+ # Depending on a version or revision of Python, this may be essential.
102
+ return self
78
103
 
79
104
  # If we sublass a COM interface, for example:
80
105
  #
@@ -85,49 +110,67 @@ class _cominterface_meta(type):
85
110
  # subclass of POINTER(IUnknown) because of the way ctypes
86
111
  # typechecks work.
87
112
  if bases == (object,):
88
- _ptr_bases = (new_cls, _compointer_base)
113
+ # `self` is the `IUnknown` type.
114
+ _ptr_bases = (self, _compointer_base)
89
115
  else:
90
- _ptr_bases = (new_cls, POINTER(bases[0]))
91
-
92
- # The interface 'new_cls' is used as a mixin.
116
+ # `self` is an interface type derived from `IUnknown`.
117
+ _ptr_bases = (self, POINTER(bases[0]))
118
+
119
+ # The interface 'self' is used as a mixin.
120
+ # HACK: Could `type(_compointer_base)` be replaced with `_compointer_meta`?
121
+ # `type(klass)` returns its metaclass.
122
+ # Since this specification, `type(_compointer_base)` will return the
123
+ # `_compointer_meta` type as per the class definition.
124
+ # The reason for this implementation might be a remnant of the differences in
125
+ # how metaclasses work between Python 3.x and Python 2.x.
126
+ # If there are no problems with the versions of Python that `comtypes`
127
+ # supports, this replacement could make the process flow easier to understand.
93
128
  p = type(_compointer_base)(
94
- "POINTER(%s)" % new_cls.__name__,
129
+ f"POINTER({self.__name__})",
95
130
  _ptr_bases,
96
- {"__com_interface__": new_cls, "_needs_com_addref_": None},
131
+ {"__com_interface__": self, "_needs_com_addref_": None},
97
132
  )
98
133
 
99
- from ctypes import _pointer_type_cache
134
+ from ctypes import _pointer_type_cache # type: ignore
100
135
 
101
- _pointer_type_cache[new_cls] = p
136
+ _pointer_type_cache[self] = p
102
137
 
103
- if new_cls._case_insensitive_:
138
+ if self._case_insensitive_:
139
+ self._patch_case_insensitive_to_ptr_type(p)
140
+ self._patch_reference_fix_to_ptrptr_type(POINTER(p)) # type: ignore
104
141
 
105
- @patcher.Patch(p)
106
- class CaseInsensitive(object):
107
- # case insensitive attributes for COM methods and properties
108
- def __getattr__(self, name):
109
- """Implement case insensitive access to methods and properties"""
110
- try:
111
- fixed_name = self.__map_case__[name.lower()]
112
- except KeyError:
113
- raise AttributeError(name)
114
- if fixed_name != name: # prevent unbounded recursion
115
- return getattr(self, fixed_name)
116
- raise AttributeError(name)
117
-
118
- # __setattr__ is pretty heavy-weight, because it is called for
119
- # EVERY attribute assignment. Settings a non-com attribute
120
- # through this function takes 8.6 usec, while without this
121
- # function it takes 0.7 sec - 12 times slower.
122
- #
123
- # How much faster would this be if implemented in C?
124
- def __setattr__(self, name, value):
125
- """Implement case insensitive access to methods and properties"""
126
- object.__setattr__(
127
- self, self.__map_case__.get(name.lower(), name), value
128
- )
129
-
130
- @patcher.Patch(POINTER(p))
142
+ return self
143
+
144
+ @staticmethod
145
+ def _patch_case_insensitive_to_ptr_type(p: Type) -> None:
146
+ @patcher.Patch(p)
147
+ class CaseInsensitive(object):
148
+ # case insensitive attributes for COM methods and properties
149
+ def __getattr__(self, name):
150
+ """Implement case insensitive access to methods and properties"""
151
+ try:
152
+ fixed_name = self.__map_case__[name.lower()]
153
+ except KeyError:
154
+ raise AttributeError(name) # Should we use exception-chaining?
155
+ if fixed_name != name: # prevent unbounded recursion
156
+ return getattr(self, fixed_name)
157
+ raise AttributeError(name)
158
+
159
+ # __setattr__ is pretty heavy-weight, because it is called for
160
+ # EVERY attribute assignment. Settings a non-com attribute
161
+ # through this function takes 8.6 usec, while without this
162
+ # function it takes 0.7 sec - 12 times slower.
163
+ #
164
+ # How much faster would this be if implemented in C?
165
+ def __setattr__(self, name, value):
166
+ """Implement case insensitive access to methods and properties"""
167
+ object.__setattr__(
168
+ self, self.__map_case__.get(name.lower(), name), value
169
+ )
170
+
171
+ @staticmethod
172
+ def _patch_reference_fix_to_ptrptr_type(pp: Type) -> None:
173
+ @patcher.Patch(pp)
131
174
  class ReferenceFix(object):
132
175
  def __setitem__(self, index, value):
133
176
  # We override the __setitem__ method of the
@@ -149,13 +192,11 @@ class _cominterface_meta(type):
149
192
  # CopyComPointer should do if index != 0.
150
193
  if bool(value):
151
194
  value.AddRef()
152
- super(POINTER(p), self).__setitem__(index, value)
195
+ super(pp, self).__setitem__(index, value) # type: ignore
153
196
  return
154
197
  from _ctypes import CopyComPointer
155
198
 
156
- CopyComPointer(value, self)
157
-
158
- return new_cls
199
+ CopyComPointer(value, self) # type: ignore
159
200
 
160
201
  def __setattr__(self, name, value):
161
202
  if name == "_methods_":
@@ -308,16 +349,13 @@ class _cominterface_meta(type):
308
349
 
309
350
  def __get_baseinterface_methodcount(self):
310
351
  "Return the number of com methods in the base interfaces"
311
- try:
312
- result = 0
313
- for itf in self.mro()[1:-1]:
314
- result += len(itf.__dict__["_methods_"])
315
- return result
316
- except KeyError as err:
317
- (name,) = err.args
318
- if name == "_methods_":
319
- raise TypeError("baseinterface '%s' has no _methods_" % itf.__name__)
320
- raise
352
+ result = 0
353
+ for itf in self.mro()[1:-1]:
354
+ if "_methods_" in vars(itf):
355
+ result += len(vars(itf)["_methods_"])
356
+ else:
357
+ raise TypeError(f"baseinterface '{itf.__name__}' has no _methods_")
358
+ return result
321
359
 
322
360
  def _make_methods(self, methods: List[_ComMemberSpec]) -> None:
323
361
  if self._case_insensitive_:
@@ -363,9 +401,11 @@ class _cominterface_meta(type):
363
401
  ################################################################
364
402
 
365
403
 
404
+ # will not work if we change the order of the two base classes!
366
405
  class _compointer_meta(type(c_void_p), _cominterface_meta):
367
- "metaclass for COM interface pointer classes"
368
- # no functionality, but needed to avoid a metaclass conflict
406
+ """metaclass for COM interface pointer classes"""
407
+
408
+ pass # no functionality, but needed to avoid a metaclass conflict
369
409
 
370
410
 
371
411
  class _compointer_base(c_void_p, metaclass=_compointer_meta):
@@ -385,21 +425,6 @@ class _compointer_base(c_void_p, metaclass=_compointer_meta):
385
425
  _debug("Release %s", self)
386
426
  self.Release()
387
427
 
388
- def __cmp__(self, other):
389
- """Compare pointers to COM interfaces."""
390
- # COM identity rule
391
- #
392
- # XXX To compare COM interface pointers, should we
393
- # automatically QueryInterface for IUnknown on both items, and
394
- # compare the pointer values?
395
- if not isinstance(other, _compointer_base):
396
- return 1
397
-
398
- # get the value property of the c_void_p baseclass, this is the pointer value
399
- return cmp(
400
- super(_compointer_base, self).value, super(_compointer_base, other).value
401
- )
402
-
403
428
  def __eq__(self, other):
404
429
  if not isinstance(other, _compointer_base):
405
430
  return False
@@ -4,7 +4,7 @@ import datetime
4
4
  import decimal
5
5
  import sys
6
6
  from ctypes import *
7
- from ctypes import _Pointer
7
+ from ctypes import _Pointer, Array as _CArrayType
8
8
  from _ctypes import CopyComPointer
9
9
  from ctypes.wintypes import DWORD, LONG, UINT, VARIANT_BOOL, WCHAR, WORD
10
10
  from typing import Any, ClassVar, Dict, List, Optional, TYPE_CHECKING, Type
@@ -16,9 +16,11 @@ import comtypes.patcher
16
16
  import comtypes
17
17
 
18
18
  if TYPE_CHECKING:
19
+ from ctypes import _CArgObject
19
20
  from comtypes import hints # type: ignore
20
21
  from comtypes import _safearray
21
22
  else:
23
+ _CArgObject = type(byref(c_int()))
22
24
  try:
23
25
  from comtypes import _safearray
24
26
  except (ImportError, AttributeError):
@@ -50,7 +52,6 @@ INVOKEKIND = tagINVOKEKIND
50
52
  # helpers
51
53
  IID_NULL = GUID()
52
54
  riid_null = byref(IID_NULL)
53
- _byref_type = type(byref(c_int()))
54
55
 
55
56
  # 30. December 1899, midnight. For VT_DATE.
56
57
  _com_null_date = datetime.datetime(1899, 12, 30, 0, 0, 0)
@@ -129,7 +130,7 @@ class tagDEC(Structure):
129
130
  ("Lo64", c_ulonglong),
130
131
  ]
131
132
 
132
- def as_decimal(self):
133
+ def as_decimal(self) -> decimal.Decimal:
133
134
  """Convert a tagDEC struct to Decimal.
134
135
 
135
136
  See http://msdn.microsoft.com/en-us/library/cc234586.aspx for the tagDEC
@@ -137,12 +138,8 @@ class tagDEC(Structure):
137
138
 
138
139
  """
139
140
  digits = (self.Hi32 << 64) + self.Lo64
140
- decimal_str = "{0}{1}e-{2}".format(
141
- "-" if self.sign else "",
142
- digits,
143
- self.scale,
144
- )
145
- return decimal.Decimal(decimal_str)
141
+ sign = "-" if self.sign else ""
142
+ return decimal.Decimal(f"{sign}{digits}e-{self.scale}")
146
143
 
147
144
 
148
145
  DECIMAL = tagDEC
@@ -382,7 +379,7 @@ class tagVARIANT(Structure):
382
379
  elif isinstance(value, c_uint64):
383
380
  self.vt = VT_UI8
384
381
  self._.VT_UI8 = value
385
- elif isinstance(value, _byref_type):
382
+ elif isinstance(value, _CArgObject):
386
383
  ref = value._obj
387
384
  self._.c_void_p = addressof(ref)
388
385
  self.__keepref = value
@@ -609,9 +606,6 @@ v.vt = VT_ERROR
609
606
  v._.VT_I4 = 0x80020004
610
607
  del v
611
608
 
612
- _carg_obj = type(byref(c_int()))
613
- from ctypes import Array as _CArrayType
614
-
615
609
 
616
610
  @comtypes.patcher.Patch(POINTER(VARIANT))
617
611
  class _(object):
@@ -626,7 +620,7 @@ class _(object):
626
620
  if isinstance(arg, POINTER(VARIANT)):
627
621
  return arg
628
622
  # accept byref(VARIANT) instance
629
- if isinstance(arg, _carg_obj) and isinstance(arg._obj, VARIANT):
623
+ if isinstance(arg, _CArgObject) and isinstance(arg._obj, VARIANT):
630
624
  return arg
631
625
  # accept VARIANT instance
632
626
  if isinstance(arg, VARIANT):
@@ -750,7 +744,7 @@ EXCEPINFO = tagEXCEPINFO
750
744
 
751
745
  class tagDISPPARAMS(Structure):
752
746
  if TYPE_CHECKING:
753
- rgvarg: Array[VARIANT]
747
+ rgvarg: _CArrayType[VARIANT]
754
748
  rgdispidNamedArgs: _Pointer[DISPID]
755
749
  cArgs: int
756
750
  cNamedArgs: int
@@ -138,22 +138,17 @@ wrap = GetBestInterface
138
138
  # Should we do this for POINTER(IUnknown) also?
139
139
  ctypes.POINTER(automation.IDispatch).__ctypes_from_outparam__ = wrap_outparam # type: ignore
140
140
 
141
+
141
142
  ################################################################
142
143
  #
143
144
  # Object creation
144
145
  #
145
146
  @overload
146
- def GetActiveObject(progid: _UnionT[str, CoClass, GUID]) -> Any:
147
- ...
148
-
149
-
147
+ def GetActiveObject(progid: _UnionT[str, CoClass, GUID]) -> Any: ...
150
148
  @overload
151
149
  def GetActiveObject(
152
150
  progid: _UnionT[str, CoClass, GUID], interface: Type[_T_IUnknown]
153
- ) -> _T_IUnknown:
154
- ...
155
-
156
-
151
+ ) -> _T_IUnknown: ...
157
152
  def GetActiveObject(
158
153
  progid: _UnionT[str, CoClass, GUID],
159
154
  interface: Optional[Type[IUnknown]] = None,
@@ -193,14 +188,19 @@ def _manage(
193
188
  if TYPE_CHECKING:
194
189
 
195
190
  @overload
196
- def GetClassObject(progid, clsctx=None, pServerInfo=None):
197
- # type: (_UnionT[str, CoClass, GUID], Optional[int], Optional[comtypes.COSERVERINFO]) -> hints.IClassFactory
198
- pass
199
-
191
+ def GetClassObject(
192
+ progid: _UnionT[str, CoClass, GUID],
193
+ clsctx: Optional[int] = None,
194
+ pServerInfo: Optional[comtypes.COSERVERINFO] = None,
195
+ interface: None = None,
196
+ ) -> hints.IClassFactory: ...
200
197
  @overload
201
- def GetClassObject(progid, clsctx=None, pServerInfo=None, interface=None):
202
- # type: (_UnionT[str, CoClass, GUID], Optional[int], Optional[comtypes.COSERVERINFO], Optional[Type[_T_IUnknown]]) -> _T_IUnknown
203
- pass
198
+ def GetClassObject(
199
+ progid: _UnionT[str, CoClass, GUID],
200
+ clsctx: Optional[int] = None,
201
+ pServerInfo: Optional[comtypes.COSERVERINFO] = None,
202
+ interface: Type[_T_IUnknown] = hints.IClassFactory,
203
+ ) -> _T_IUnknown: ...
204
204
 
205
205
 
206
206
  def GetClassObject(progid, clsctx=None, pServerInfo=None, interface=None):
@@ -216,10 +216,7 @@ def GetClassObject(progid, clsctx=None, pServerInfo=None, interface=None):
216
216
 
217
217
 
218
218
  @overload
219
- def CreateObject(progid: _UnionT[str, Type[CoClass], GUID]) -> Any:
220
- ...
221
-
222
-
219
+ def CreateObject(progid: _UnionT[str, Type[CoClass], GUID]) -> Any: ...
223
220
  @overload
224
221
  def CreateObject(
225
222
  progid: _UnionT[str, Type[CoClass], GUID],
@@ -228,10 +225,7 @@ def CreateObject(
228
225
  interface: Optional[Type[_T_IUnknown]] = None,
229
226
  dynamic: bool = ...,
230
227
  pServerInfo: Optional[comtypes.COSERVERINFO] = None,
231
- ) -> _T_IUnknown:
232
- ...
233
-
234
-
228
+ ) -> _T_IUnknown: ...
235
229
  def CreateObject(
236
230
  progid: _UnionT[str, Type[CoClass], GUID], # which object to create
237
231
  clsctx: Optional[int] = None, # how to create the object
@@ -297,15 +291,11 @@ def CreateObject(
297
291
 
298
292
 
299
293
  @overload
300
- def CoGetObject(displayname: str, interface: Type[_T_IUnknown]) -> _T_IUnknown:
301
- ...
302
-
303
-
294
+ def CoGetObject(displayname: str, interface: Type[_T_IUnknown]) -> _T_IUnknown: ...
304
295
  @overload
305
- def CoGetObject(displayname: str, interface: None = None, dynamic: bool = False) -> Any:
306
- ...
307
-
308
-
296
+ def CoGetObject(
297
+ displayname: str, interface: None = None, dynamic: bool = False
298
+ ) -> Any: ...
309
299
  def CoGetObject(
310
300
  displayname: str,
311
301
  interface: Optional[Type[comtypes.IUnknown]] = None,
@@ -4,6 +4,7 @@ The main function is _find_gen_dir(), which on-demand creates the
4
4
  comtypes.gen package and returns a directory where generated code can
5
5
  be written to.
6
6
  """
7
+
7
8
  import ctypes, logging, os, sys, tempfile, types
8
9
  from ctypes import wintypes
9
10
 
@@ -1,4 +1,3 @@
1
- from __future__ import print_function
2
1
  import ctypes
3
2
  import traceback
4
3
  import comtypes
@@ -1,4 +1,3 @@
1
- from __future__ import print_function
2
1
  import ctypes
3
2
  import importlib
4
3
  import inspect
@@ -106,7 +105,8 @@ def GetModule(tlib: _UnionT[Any, typeinfo.ITypeLib]) -> types.ModuleType:
106
105
  frame = sys._getframe(1)
107
106
  _file_: Optional[str] = frame.f_globals.get("__file__", None)
108
107
  pathname, is_abs = _resolve_filename(
109
- tlib_string, _file_ and os.path.dirname(_file_) # type: ignore
108
+ tlib_string,
109
+ _file_ and os.path.dirname(_file_), # type: ignore
110
110
  )
111
111
  logger.debug("GetModule(%s), resolved: %s", pathname, is_abs)
112
112
  tlib = _load_tlib(pathname) # don't register
@@ -251,9 +251,9 @@ _ItfName = str
251
251
  _ItfIid = str
252
252
 
253
253
 
254
- def _get_known_namespaces() -> Tuple[
255
- Mapping[_SymbolName, _ModuleName], Mapping[_ItfName, _ItfIid]
256
- ]:
254
+ def _get_known_namespaces() -> (
255
+ Tuple[Mapping[_SymbolName, _ModuleName], Mapping[_ItfName, _ItfIid]]
256
+ ):
257
257
  """Returns symbols and interfaces that are already statically defined in `ctypes`
258
258
  and `comtypes`.
259
259
  From `ctypes`, all the names are obtained.
@@ -126,11 +126,6 @@ class Dispatch(object):
126
126
  "QueryInterface is forwarded to the real com object."
127
127
  return self._comobj.QueryInterface(*args)
128
128
 
129
- def __cmp__(self, other):
130
- if not isinstance(other, Dispatch):
131
- return 1
132
- return cmp(self._comobj, other._comobj)
133
-
134
129
  def __eq__(self, other):
135
130
  return isinstance(other, Dispatch) and self._comobj == other._comobj
136
131
 
@@ -3,6 +3,7 @@
3
3
  The global interface table provides a way to marshal interface pointers
4
4
  between different threading appartments.
5
5
  """
6
+
6
7
  from ctypes import *
7
8
  from comtypes import (
8
9
  IUnknown,
@@ -10,8 +10,10 @@ from typing import Callable, Iterator, Sequence
10
10
 
11
11
  if sys.version_info >= (3, 8):
12
12
  from typing import Protocol
13
+ from typing import Literal as Literal
13
14
  else:
14
15
  from typing_extensions import Protocol
16
+ from typing_extensions import Literal as Literal
15
17
  if sys.version_info >= (3, 9):
16
18
  from typing import Annotated as Annotated
17
19
  else:
@@ -251,7 +253,7 @@ _T_E = TypeVar("_T_E")
251
253
  def to_dunder_iter(
252
254
  newenum: _UnionT[
253
255
  _Descriptor[_T_Inst, Iterator[_T_E]], Callable[[_T_Inst], Iterator[_T_E]]
254
- ]
256
+ ],
255
257
  ) -> Callable[[_T_Inst], Iterator[_T_E]]: ...
256
258
  @overload
257
259
  def to_dunder_iter(newenum: Any) -> Callable[..., NoReturn]: ...
@@ -264,7 +266,7 @@ def to_dunder_call(
264
266
  _GetSetNamedProperty[_T_Inst, _P_Get, _R_Get, ...],
265
267
  _GetOnlyNamedProperty[_T_Inst, _P_Get, _R_Get],
266
268
  Callable[Concatenate[_T_Inst, _P_Get], _R_Get],
267
- ]
269
+ ],
268
270
  ) -> Callable[Concatenate[_T_Inst, _P_Get], _R_Get]: ...
269
271
  @overload
270
272
  def to_dunder_call(item: Any) -> Callable[..., NoReturn]: ...
@@ -276,7 +278,7 @@ def to_dunder_getitem(
276
278
  _GetSetNamedProperty[_T_Inst, _P_Get, _R_Get, ...],
277
279
  _GetOnlyNamedProperty[_T_Inst, _P_Get, _R_Get],
278
280
  Callable[Concatenate[_T_Inst, _P_Get], _R_Get],
279
- ]
281
+ ],
280
282
  ) -> Callable[Concatenate[_T_Inst, _P_Get], _R_Get]: ...
281
283
  @overload
282
284
  def to_dunder_getitem(item: Any) -> Callable[..., NoReturn]: ...
@@ -287,7 +289,7 @@ def to_dunder_setitem(
287
289
  item: _UnionT[
288
290
  _GetSetNamedProperty[_T_Inst, ..., Any, _P_Set],
289
291
  _SetOnlyNamedProperty[_T_Inst, _P_Set],
290
- ]
292
+ ],
291
293
  ) -> Callable[Concatenate[_T_Inst, _P_Set], Any]: ...
292
294
  @overload
293
295
  def to_dunder_setitem(item: Any) -> Callable[..., NoReturn]: ...
@@ -9,12 +9,20 @@
9
9
  The 'DictPropertyBag' class is a class implementing the IPropertyBag
10
10
  interface, useful in client code.
11
11
  """
12
- from ctypes import *
12
+
13
+ from ctypes import c_int, c_ulong, c_ushort, c_wchar_p
14
+ from ctypes import POINTER, Structure
13
15
  from ctypes.wintypes import WORD, DWORD, BOOL
14
- from comtypes import GUID, IUnknown, COMMETHOD, HRESULT, dispid
16
+ from typing import TYPE_CHECKING
17
+
18
+ from comtypes import GUID, IUnknown, COMMETHOD, HRESULT
15
19
  from comtypes import IPersist
16
20
  from comtypes.automation import VARIANT, tagEXCEPINFO
17
21
 
22
+ if TYPE_CHECKING:
23
+ from comtypes import hints # type: ignore
24
+
25
+
18
26
  # XXX Replace by canonical solution!!!
19
27
  WSTRING = c_wchar_p
20
28
 
@@ -236,9 +244,17 @@ class IPersistFile(IPersist):
236
244
  ),
237
245
  ]
238
246
 
247
+ if TYPE_CHECKING:
248
+
249
+ def IsDirty(self) -> hints.Hresult: ...
250
+ def Load(self, pszFileName: str, dwMode: int) -> hints.Hresult: ...
251
+ def Save(self, pszFileName: str, fRemember: bool) -> hints.Hresult: ...
252
+ def SaveCompleted(self, pszFileName: str) -> hints.Hresult: ...
253
+ def GetCurFile(self) -> str: ...
254
+
239
255
 
240
256
  from comtypes import COMObject
241
- from comtypes.hresult import *
257
+ from comtypes.hresult import E_INVALIDARG, S_OK
242
258
 
243
259
 
244
260
  class DictPropertyBag(COMObject):
@@ -81,9 +81,7 @@ def _make_safearray_type(itemtype):
81
81
  )
82
82
 
83
83
  meta = type(_safearray.tagSAFEARRAY)
84
- sa_type = meta.__new__(
85
- meta, "SAFEARRAY_%s" % itemtype.__name__, (_safearray.tagSAFEARRAY,), {}
86
- )
84
+ sa_type = meta(f"SAFEARRAY_{itemtype.__name__}", (_safearray.tagSAFEARRAY,), {})
87
85
 
88
86
  try:
89
87
  vartype = _ctype_to_vartype[itemtype]
@@ -192,9 +190,7 @@ def _make_safearray_type(itemtype):
192
190
  nitems *= d
193
191
  rgsa[i].cElements = d
194
192
  rgsa[i].lBound = lBound
195
- pa = _safearray.SafeArrayCreateEx(
196
- cls._vartype_, value.ndim, rgsa, extra # cDims # rgsaBound
197
- ) # pvExtra
193
+ pa = _safearray.SafeArrayCreateEx(cls._vartype_, value.ndim, rgsa, extra)
198
194
  if not pa:
199
195
  if cls._vartype_ == VT_RECORD and extra is None:
200
196
  raise TypeError(
@@ -1,5 +1,6 @@
1
1
  import comtypes.client, ctypes
2
2
 
3
+
3
4
  ################################################################
4
5
  # Interfaces
5
6
  class IClassFactory(comtypes.IUnknown):
@@ -35,6 +35,7 @@ Now, debug the object, and when done delete logging info:
35
35
 
36
36
  python mycomobj.py /nodebug
37
37
  """
38
+
38
39
  import sys
39
40
  import os
40
41
  import winreg