comtypes 1.4.7__zip → 1.4.9__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 (149) hide show
  1. {comtypes-1.4.7 → comtypes-1.4.9}/CHANGES.txt +39 -0
  2. {comtypes-1.4.7/comtypes.egg-info → comtypes-1.4.9}/PKG-INFO +6 -4
  3. {comtypes-1.4.7 → comtypes-1.4.9}/README.md +5 -3
  4. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/GUID.py +6 -5
  5. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/__init__.py +16 -5
  6. comtypes-1.4.9/comtypes/_comobject.py +507 -0
  7. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/_memberspec.py +81 -9
  8. comtypes-1.4.9/comtypes/_meta.py +95 -0
  9. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/_npsupport.py +2 -1
  10. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/_post_coinit/__init__.py +1 -0
  11. comtypes-1.4.9/comtypes/_post_coinit/_cominterface_meta_patcher.py +153 -0
  12. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/_post_coinit/misc.py +21 -40
  13. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/_post_coinit/unknwn.py +88 -209
  14. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/_safearray.py +1 -2
  15. comtypes-1.4.9/comtypes/_vtbl.py +448 -0
  16. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/automation.py +36 -45
  17. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/client/__init__.py +21 -31
  18. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/client/_code_cache.py +5 -4
  19. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/client/_constants.py +1 -1
  20. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/client/_events.py +1 -2
  21. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/client/_generate.py +9 -13
  22. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/client/lazybind.py +2 -7
  23. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/errorinfo.py +3 -3
  24. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/git.py +2 -2
  25. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/hints.pyi +11 -19
  26. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/persist.py +7 -7
  27. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/safearray.py +12 -6
  28. comtypes-1.4.9/comtypes/server/__init__.py +86 -0
  29. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/server/inprocserver.py +22 -17
  30. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/server/localserver.py +28 -16
  31. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/server/register.py +62 -73
  32. comtypes-1.4.9/comtypes/server/w_getopt.py +48 -0
  33. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/shelllink.py +49 -67
  34. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/TestComServer.py +1 -1
  35. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/TestDispServer.py +1 -1
  36. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/__init__.py +9 -12
  37. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/find_memleak.py +0 -1
  38. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_BSTR.py +4 -7
  39. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_agilent.py +0 -1
  40. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_avmc.py +1 -1
  41. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_casesensitivity.py +3 -5
  42. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_clear_cache.py +1 -0
  43. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_collections.py +3 -3
  44. comtypes-1.4.9/comtypes/test/test_comobject.py +146 -0
  45. comtypes-1.4.9/comtypes/test/test_comserver.py +319 -0
  46. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_createwrappers.py +2 -6
  47. comtypes-1.4.9/comtypes/test/test_dispinterface.py +153 -0
  48. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_excel.py +22 -13
  49. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_ie.py +2 -5
  50. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_inout_args.py +8 -5
  51. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_midl_safearray_create.py +9 -1
  52. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_outparam.py +17 -10
  53. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_safearray.py +1 -90
  54. comtypes-1.4.9/comtypes/test/test_server.py +350 -0
  55. comtypes-1.4.9/comtypes/test/test_server_register.py +536 -0
  56. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_shelllink.py +10 -14
  57. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_showevents.py +7 -17
  58. comtypes-1.4.9/comtypes/test/test_stream.py +131 -0
  59. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_typeannotator.py +1 -1
  60. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_urlhistory.py +1 -0
  61. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_variant.py +0 -19
  62. comtypes-1.4.9/comtypes/test/test_w_getopt.py +29 -0
  63. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_win32com_interop.py +80 -36
  64. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_wmi.py +0 -3
  65. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/tools/codegenerator/codegenerator.py +62 -68
  66. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/tools/codegenerator/helpers.py +8 -8
  67. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/tools/codegenerator/namespaces.py +97 -27
  68. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/tools/codegenerator/packing.py +4 -4
  69. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/tools/codegenerator/typeannotator.py +9 -11
  70. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/tools/tlbparser.py +33 -32
  71. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/tools/typedesc.py +3 -8
  72. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/typeinfo.py +32 -47
  73. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/util.py +1 -0
  74. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/viewobject.py +1 -5
  75. {comtypes-1.4.7 → comtypes-1.4.9/comtypes.egg-info}/PKG-INFO +6 -4
  76. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes.egg-info/SOURCES.txt +6 -3
  77. comtypes-1.4.9/pyproject.toml +55 -0
  78. comtypes-1.4.7/comtypes/_comobject.py +0 -834
  79. comtypes-1.4.7/comtypes/_idl_stuff.py +0 -67
  80. comtypes-1.4.7/comtypes/_meta.py +0 -70
  81. comtypes-1.4.7/comtypes/server/__init__.py +0 -69
  82. comtypes-1.4.7/comtypes/server/w_getopt.py +0 -75
  83. comtypes-1.4.7/comtypes/test/test_comserver.py +0 -239
  84. comtypes-1.4.7/comtypes/test/test_dispinterface.py +0 -138
  85. comtypes-1.4.7/comtypes/test/test_propputref.py +0 -40
  86. comtypes-1.4.7/comtypes/test/test_server.py +0 -348
  87. comtypes-1.4.7/comtypes/test/test_stream.py +0 -53
  88. comtypes-1.4.7/pyproject.toml +0 -3
  89. {comtypes-1.4.7 → comtypes-1.4.9}/LICENSE.txt +0 -0
  90. {comtypes-1.4.7 → comtypes-1.4.9}/MANIFEST.in +0 -0
  91. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/_post_coinit/bstr.py +0 -0
  92. /comtypes-1.4.7/comtypes/_py_instance_method.py → /comtypes-1.4.9/comtypes/_post_coinit/instancemethod.py +0 -0
  93. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/_tlib_version_checker.py +0 -0
  94. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/clear_cache.py +0 -0
  95. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/client/dynamic.py +0 -0
  96. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/connectionpoints.py +0 -0
  97. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/hresult.py +0 -0
  98. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/logutil.py +0 -0
  99. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/messageloop.py +0 -0
  100. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/patcher.py +0 -0
  101. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/server/automation.py +0 -0
  102. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/server/connectionpoints.py +0 -0
  103. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/stream.py +0 -0
  104. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/TestComServer.idl +0 -0
  105. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/TestComServer.tlb +0 -0
  106. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/TestDispServer.idl +0 -0
  107. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/TestDispServer.tlb +0 -0
  108. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/mylib.idl +0 -0
  109. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/mylib.tlb +0 -0
  110. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/mytypelib.idl +0 -0
  111. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/runtests.py +0 -0
  112. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/setup.py +0 -0
  113. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_DISPPARAMS.py +0 -0
  114. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_GUID.py +0 -0
  115. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_QueryService.py +0 -0
  116. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_basic.py +0 -0
  117. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_client.py +0 -0
  118. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_client_dynamic.py +0 -0
  119. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_client_regenerate_modules.py +0 -0
  120. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_dict.py +0 -0
  121. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_dispifc_records.py +0 -0
  122. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_dispifc_safearrays.py +0 -0
  123. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_dyndispatch.py +0 -0
  124. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_findgendir.py +0 -0
  125. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_getactiveobj.py +0 -0
  126. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_ienum.py +0 -0
  127. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_imfattributes.py +0 -0
  128. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_jscript.js +0 -0
  129. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_monikers.py +0 -0
  130. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_msscript.py +0 -0
  131. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_npsupport.py +0 -0
  132. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_persist.py +0 -0
  133. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_pump_events.py +0 -0
  134. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_recordinfo.py +0 -0
  135. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_sapi.py +0 -0
  136. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_storage.py +0 -0
  137. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_subinterface.py +0 -0
  138. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_typeinfo.py +0 -0
  139. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/test_word.py +0 -0
  140. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/test/urlhist.tlb +0 -0
  141. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/tools/__init__.py +0 -0
  142. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/tools/codegenerator/__init__.py +0 -0
  143. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/tools/codegenerator/modulenamer.py +0 -0
  144. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes/tools/typedesc_base.py +0 -0
  145. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes.egg-info/dependency_links.txt +0 -0
  146. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes.egg-info/entry_points.txt +0 -0
  147. {comtypes-1.4.7 → comtypes-1.4.9}/comtypes.egg-info/top_level.txt +0 -0
  148. {comtypes-1.4.7 → comtypes-1.4.9}/setup.cfg +0 -0
  149. {comtypes-1.4.7 → comtypes-1.4.9}/setup.py +0 -0
@@ -1,23 +1,17 @@
1
1
  # https://learn.microsoft.com/en-us/windows/win32/api/unknwn/
2
2
 
3
- from ctypes import byref, c_ulong, c_void_p, HRESULT, POINTER
4
- from _ctypes import COMError
5
-
6
3
  import logging
7
4
  import sys
8
- import types
9
- from typing import ClassVar, TYPE_CHECKING, TypeVar
10
- from typing import Optional
11
- from typing import List, Type
12
-
13
- from comtypes import GUID, patcher, _ole32_nohresult, com_interface_registry
14
- from comtypes._idl_stuff import STDMETHOD
15
- from comtypes._memberspec import ComMemberGenerator, DispMemberGenerator
16
- from comtypes._memberspec import _ComMemberSpec, _DispMemberSpec
17
- from comtypes._py_instance_method import instancemethod
5
+ from ctypes import HRESULT, POINTER, byref, c_ulong, c_void_p
6
+ from typing import TYPE_CHECKING, ClassVar, List, Optional, Type, TypeVar
18
7
 
8
+ from comtypes import GUID, _ole32_nohresult, com_interface_registry
9
+ from comtypes._memberspec import STDMETHOD, ComMemberGenerator, DispMemberGenerator
10
+ from comtypes._post_coinit import _cominterface_meta_patcher as _meta_patch
11
+ from comtypes._post_coinit.instancemethod import instancemethod
19
12
 
20
- _all_slice = slice(None, None, None)
13
+ if TYPE_CHECKING:
14
+ from comtypes._memberspec import _ComMemberSpec, _DispMemberSpec
21
15
 
22
16
  logger = logging.getLogger(__name__)
23
17
 
@@ -58,8 +52,8 @@ class _cominterface_meta(type):
58
52
 
59
53
  _case_insensitive_: bool
60
54
  _iid_: GUID
61
- _methods_: List[_ComMemberSpec]
62
- _disp_methods_: List[_DispMemberSpec]
55
+ _methods_: List["_ComMemberSpec"]
56
+ _disp_methods_: List["_DispMemberSpec"]
63
57
 
64
58
  # This flag is set to True by the atexit handler which calls
65
59
  # CoUninitialize.
@@ -69,12 +63,37 @@ class _cominterface_meta(type):
69
63
  def __new__(cls, name, bases, namespace):
70
64
  methods = namespace.pop("_methods_", None)
71
65
  dispmethods = namespace.pop("_disp_methods_", None)
72
- new_cls = type.__new__(cls, name, bases, namespace)
66
+ self = type.__new__(cls, name, bases, namespace)
73
67
 
74
68
  if methods is not None:
75
- new_cls._methods_ = methods
69
+ self._methods_ = methods
76
70
  if dispmethods is not None:
77
- new_cls._disp_methods_ = dispmethods
71
+ self._disp_methods_ = dispmethods
72
+
73
+ # ` _compointer_meta` is a subclass inherited from `_cominterface_meta`.
74
+ # `_compointer_base` uses `_compointer_meta` as its metaclass.
75
+ # In other words, when the `__new__` method of this metaclass is called,
76
+ # `_compointer_base` type or an subclass of it might be created and assigned
77
+ # to `self`.
78
+ if bases == (c_void_p,):
79
+ # `self` is the `_compointer_base` type.
80
+ # On some versions of Python, `_compointer_base` is not yet available in
81
+ # the accessible namespace at this point in its initialization, and
82
+ # referencing it could raise a `NameError`.
83
+ # This metaclass is intended to be used only as a base class for defining
84
+ # the `_compointer_meta` or as the metaclass for the `IUnknown`, so the
85
+ # situation where the `bases` parameter is `(c_void_p,)` is limited to when
86
+ # the `_compointer_meta` is specified as the metaclass of the
87
+ # `_compointer_base`.
88
+ # Prevent specifying the metaclass type instance in the `bases` parameter
89
+ # when instantiating it, as this would lead to infinite recursion.
90
+ return self
91
+ if issubclass(self, _compointer_base):
92
+ # `self` is a `POINTER(interface)` type.
93
+ # Prevent creating/registering a pointer to a pointer (to a pointer...),
94
+ # which would lead to infinite recursion.
95
+ # Depending on a version or revision of Python, this may be essential.
96
+ return self
78
97
 
79
98
  # If we sublass a COM interface, for example:
80
99
  #
@@ -85,77 +104,36 @@ class _cominterface_meta(type):
85
104
  # subclass of POINTER(IUnknown) because of the way ctypes
86
105
  # typechecks work.
87
106
  if bases == (object,):
88
- _ptr_bases = (new_cls, _compointer_base)
107
+ # `self` is the `IUnknown` type.
108
+ _ptr_bases = (self, _compointer_base)
89
109
  else:
90
- _ptr_bases = (new_cls, POINTER(bases[0]))
91
-
92
- # The interface 'new_cls' is used as a mixin.
110
+ # `self` is an interface type derived from `IUnknown`.
111
+ _ptr_bases = (self, POINTER(bases[0]))
112
+
113
+ # The interface 'self' is used as a mixin.
114
+ # HACK: Could `type(_compointer_base)` be replaced with `_compointer_meta`?
115
+ # `type(klass)` returns its metaclass.
116
+ # Since this specification, `type(_compointer_base)` will return the
117
+ # `_compointer_meta` type as per the class definition.
118
+ # The reason for this implementation might be a remnant of the differences in
119
+ # how metaclasses work between Python 3.x and Python 2.x.
120
+ # If there are no problems with the versions of Python that `comtypes`
121
+ # supports, this replacement could make the process flow easier to understand.
93
122
  p = type(_compointer_base)(
94
- "POINTER(%s)" % new_cls.__name__,
123
+ f"POINTER({self.__name__})",
95
124
  _ptr_bases,
96
- {"__com_interface__": new_cls, "_needs_com_addref_": None},
125
+ {"__com_interface__": self, "_needs_com_addref_": None},
97
126
  )
98
127
 
99
- from ctypes import _pointer_type_cache
100
-
101
- _pointer_type_cache[new_cls] = p
102
-
103
- if new_cls._case_insensitive_:
104
-
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))
131
- class ReferenceFix(object):
132
- def __setitem__(self, index, value):
133
- # We override the __setitem__ method of the
134
- # POINTER(POINTER(interface)) type, so that the COM
135
- # reference count is managed correctly.
136
- #
137
- # This is so that we can implement COM methods that have to
138
- # return COM pointers more easily and consistent. Instead of
139
- # using CopyComPointer in the method implementation, we can
140
- # simply do:
141
- #
142
- # def GetTypeInfo(self, this, ..., pptinfo):
143
- # if not pptinfo: return E_POINTER
144
- # pptinfo[0] = a_com_interface_pointer
145
- # return S_OK
146
- if index != 0:
147
- # CopyComPointer, which is in _ctypes, does only
148
- # handle an index of 0. This code does what
149
- # CopyComPointer should do if index != 0.
150
- if bool(value):
151
- value.AddRef()
152
- super(POINTER(p), self).__setitem__(index, value)
153
- return
154
- from _ctypes import CopyComPointer
155
-
156
- CopyComPointer(value, self)
157
-
158
- return new_cls
128
+ from ctypes import _pointer_type_cache # type: ignore
129
+
130
+ _pointer_type_cache[self] = p
131
+
132
+ if self._case_insensitive_:
133
+ _meta_patch.case_insensitive(p)
134
+ _meta_patch.reference_fix(POINTER(p)) # type: ignore
135
+
136
+ return self
159
137
 
160
138
  def __setattr__(self, name, value):
161
139
  if name == "_methods_":
@@ -184,94 +162,11 @@ class _cominterface_meta(type):
184
162
 
185
163
  # XXX These special methods should be generated by the code generator.
186
164
  if has_name("Count"):
187
-
188
- @patcher.Patch(self)
189
- class _(object):
190
- def __len__(self):
191
- "Return the the 'self.Count' property."
192
- return self.Count
193
-
165
+ _meta_patch.sized(self)
194
166
  if has_name("Item"):
195
-
196
- @patcher.Patch(self)
197
- class _(object):
198
- # 'Item' is the 'default' value. Make it available by
199
- # calling the instance (Not sure this makes sense, but
200
- # win32com does this also).
201
- def __call__(self, *args, **kw):
202
- "Return 'self.Item(*args, **kw)'"
203
- return self.Item(*args, **kw)
204
-
205
- # does this make sense? It seems that all standard typelibs I've
206
- # seen so far that support .Item also support ._NewEnum
207
- @patcher.no_replace
208
- def __getitem__(self, index):
209
- "Return 'self.Item(index)'"
210
- # Handle tuples and all-slice
211
- if isinstance(index, tuple):
212
- args = index
213
- elif index == _all_slice:
214
- args = ()
215
- else:
216
- args = (index,)
217
-
218
- try:
219
- result = self.Item(*args)
220
- except COMError as err:
221
- (hresult, text, details) = err.args
222
- if hresult == -2147352565: # DISP_E_BADINDEX
223
- raise IndexError("invalid index")
224
- else:
225
- raise
226
-
227
- # Note that result may be NULL COM pointer. There is no way
228
- # to interpret this properly, so it is returned as-is.
229
-
230
- # Hm, should we call __ctypes_from_outparam__ on the
231
- # result?
232
- return result
233
-
234
- @patcher.no_replace
235
- def __setitem__(self, index, value):
236
- "Attempt 'self.Item[index] = value'"
237
- try:
238
- self.Item[index] = value
239
- except COMError as err:
240
- (hresult, text, details) = err.args
241
- if hresult == -2147352565: # DISP_E_BADINDEX
242
- raise IndexError("invalid index")
243
- else:
244
- raise
245
- except TypeError:
246
- msg = "%r object does not support item assignment"
247
- raise TypeError(msg % type(self))
248
-
167
+ _meta_patch.callable_and_subscriptable(self)
249
168
  if has_name("_NewEnum"):
250
-
251
- @patcher.Patch(self)
252
- class _(object):
253
- def __iter__(self):
254
- "Return an iterator over the _NewEnum collection."
255
- # This method returns a pointer to _some_ _NewEnum interface.
256
- # It relies on the fact that the code generator creates next()
257
- # methods for them automatically.
258
- #
259
- # Better would maybe to return an object that
260
- # implements the Python iterator protocol, and
261
- # forwards the calls to the COM interface.
262
- enum = self._NewEnum
263
- if isinstance(enum, types.MethodType):
264
- # _NewEnum should be a propget property, with dispid -4.
265
- #
266
- # Sometimes, however, it is a method.
267
- enum = enum()
268
- if hasattr(enum, "Next"):
269
- return enum
270
- # _NewEnum returns an IUnknown pointer, QueryInterface() it to
271
- # IEnumVARIANT
272
- from comtypes.automation import IEnumVARIANT
273
-
274
- return enum.QueryInterface(IEnumVARIANT)
169
+ _meta_patch.iterator(self)
275
170
 
276
171
  def _make_case_insensitive(self):
277
172
  # The __map_case__ dictionary maps lower case names to the
@@ -284,7 +179,7 @@ class _cominterface_meta(type):
284
179
  d.update(getattr(self, "__map_case__", {}))
285
180
  self.__map_case__ = d
286
181
 
287
- def _make_dispmethods(self, methods: List[_DispMemberSpec]) -> None:
182
+ def _make_dispmethods(self, methods: List["_DispMemberSpec"]) -> None:
288
183
  if self._case_insensitive_:
289
184
  self._make_case_insensitive()
290
185
  # create dispinterface methods and properties on the interface 'self'
@@ -308,18 +203,15 @@ class _cominterface_meta(type):
308
203
 
309
204
  def __get_baseinterface_methodcount(self):
310
205
  "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
321
-
322
- def _make_methods(self, methods: List[_ComMemberSpec]) -> None:
206
+ result = 0
207
+ for itf in self.mro()[1:-1]:
208
+ if "_methods_" in vars(itf):
209
+ result += len(vars(itf)["_methods_"])
210
+ else:
211
+ raise TypeError(f"baseinterface '{itf.__name__}' has no _methods_")
212
+ return result
213
+
214
+ def _make_methods(self, methods: List["_ComMemberSpec"]) -> None:
323
215
  if self._case_insensitive_:
324
216
  self._make_case_insensitive()
325
217
  # register com interface. we insist on an _iid_ in THIS class!
@@ -337,12 +229,12 @@ class _cominterface_meta(type):
337
229
  member_gen.add(m)
338
230
  for name, func, raw_func, is_prop in member_gen.methods():
339
231
  raw_mth = instancemethod(raw_func, None, self)
340
- setattr(self, "_%s__com_%s" % (self.__name__, name), raw_mth)
232
+ setattr(self, f"_{self.__name__}__com_{name}", raw_mth)
341
233
  mth = instancemethod(func, None, self)
342
234
  if not is_prop:
343
235
  # We install the method in the class, except when it's a property.
344
236
  # And we make sure we don't overwrite a property that's already present.
345
- mthname = name if not hasattr(self, name) else ("_%s" % name)
237
+ mthname = name if not hasattr(self, name) else f"_{name}"
346
238
  setattr(self, mthname, mth)
347
239
  # For a method, this is the real name.
348
240
  # For a property, this is the name WITHOUT the _set_ or _get_ prefix.
@@ -353,7 +245,7 @@ class _cominterface_meta(type):
353
245
  # create public properties / attribute accessors
354
246
  for name, accessor in member_gen.properties():
355
247
  # Again, we should not overwrite class attributes that are already present.
356
- propname = name if not hasattr(self, name) else ("_%s" % name)
248
+ propname = name if not hasattr(self, name) else f"_{name}"
357
249
  setattr(self, propname, accessor)
358
250
  # COM is case insensitive
359
251
  if self._case_insensitive_:
@@ -363,9 +255,11 @@ class _cominterface_meta(type):
363
255
  ################################################################
364
256
 
365
257
 
258
+ # will not work if we change the order of the two base classes!
366
259
  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
260
+ """metaclass for COM interface pointer classes"""
261
+
262
+ pass # no functionality, but needed to avoid a metaclass conflict
369
263
 
370
264
 
371
265
  class _compointer_base(c_void_p, metaclass=_compointer_meta):
@@ -383,22 +277,7 @@ class _compointer_base(c_void_p, metaclass=_compointer_meta):
383
277
  #
384
278
  if not type(self)._com_shutting_down:
385
279
  _debug("Release %s", self)
386
- self.Release()
387
-
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
- )
280
+ self.Release() # type: ignore
402
281
 
403
282
  def __eq__(self, other):
404
283
  if not isinstance(other, _compointer_base):
@@ -421,7 +300,7 @@ class _compointer_base(c_void_p, metaclass=_compointer_meta):
421
300
 
422
301
  def __repr__(self):
423
302
  ptr = super(_compointer_base, self).value
424
- return "<%s ptr=0x%x at %x>" % (self.__class__.__name__, ptr or 0, id(self))
303
+ return f"<{self.__class__.__name__} ptr=0x{ptr or 0:x} at {id(self):x}>"
425
304
 
426
305
  # This fixes the problem when there are multiple python interface types
427
306
  # wrapping the same COM interface. This could happen because some interfaces
@@ -457,8 +336,8 @@ class _compointer_base(c_void_p, metaclass=_compointer_meta):
457
336
  # a kind of QueryInterface
458
337
  return table[cls._iid_]
459
338
  except KeyError:
460
- raise TypeError("Interface %s not supported" % cls._iid_)
461
- return value.QueryInterface(cls.__com_interface__)
339
+ raise TypeError(f"Interface {cls._iid_} not supported")
340
+ return value.QueryInterface(cls.__com_interface__) # type: ignore
462
341
 
463
342
 
464
343
  ################################################################
@@ -499,7 +378,7 @@ class IUnknown(_IUnknown_Base, metaclass=_cominterface_meta):
499
378
 
500
379
  _case_insensitive_: ClassVar[bool] = False
501
380
  _iid_: ClassVar[GUID] = GUID("{00000000-0000-0000-C000-000000000046}")
502
- _methods_: ClassVar[List[_ComMemberSpec]] = [
381
+ _methods_: ClassVar[List["_ComMemberSpec"]] = [
503
382
  STDMETHOD(HRESULT, "QueryInterface", [POINTER(GUID), POINTER(c_void_p)]),
504
383
  STDMETHOD(c_ulong, "AddRef"),
505
384
  STDMETHOD(c_ulong, "Release"),
@@ -1,7 +1,7 @@
1
1
  """SAFEARRAY api functions, data types, and constants."""
2
2
 
3
3
  from ctypes import c_uint, c_ushort, c_void_p, POINTER, Structure, WinDLL
4
- from ctypes.wintypes import DWORD, LONG, UINT
4
+ from ctypes.wintypes import DWORD, LONG, UINT, USHORT
5
5
 
6
6
  from comtypes import HRESULT, GUID
7
7
 
@@ -19,7 +19,6 @@ from comtypes import HRESULT, GUID
19
19
 
20
20
  VARTYPE = c_ushort
21
21
  PVOID = c_void_p
22
- USHORT = c_ushort
23
22
 
24
23
  _oleaut32 = WinDLL("oleaut32")
25
24