Skip to content

Commit

Permalink
change type hints from comment annotations to inline annotations in `…
Browse files Browse the repository at this point in the history
…comtypes/__init__.py`, `comtypes/automation.py` and `comtypes/typeinfo.py` (#454)

* update `comtypes/__init__.py`

* update `comtypes/automation.py`

* update `comtypes/typeinfo.py`

* fix `Array[T]` to quoted literal strings
  • Loading branch information
junkmd authored Jan 6, 2023
1 parent 7321eaf commit 7b38a7a
Show file tree
Hide file tree
Showing 3 changed files with 157 additions and 171 deletions.
43 changes: 19 additions & 24 deletions comtypes/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -260,11 +260,10 @@ class _cominterface_meta(type):
methods from COMMETHOD lists.
"""

if TYPE_CHECKING:
_case_insensitive_: bool
_iid_: GUID
_methods_: List[_ComMemberSpec]
_disp_methods_: List[_DispMemberSpec]
_case_insensitive_: bool
_iid_: GUID
_methods_: List[_ComMemberSpec]
_disp_methods_: List[_DispMemberSpec]

# This flag is set to True by the atexit handler which calls
# CoUninitialize.
Expand Down Expand Up @@ -489,8 +488,7 @@ def _make_case_insensitive(self):
d.update(getattr(self, "__map_case__", {}))
self.__map_case__ = d

def _make_dispmethods(self, methods):
# type: (List[_DispMemberSpec]) -> None
def _make_dispmethods(self, methods: List[_DispMemberSpec]) -> None:
if self._case_insensitive_:
self._make_case_insensitive()
# create dispinterface methods and properties on the interface 'self'
Expand Down Expand Up @@ -525,8 +523,7 @@ def __get_baseinterface_methodcount(self):
raise TypeError("baseinterface '%s' has no _methods_" % itf.__name__)
raise

def _make_methods(self, methods):
# type: (List[_ComMemberSpec]) -> None
def _make_methods(self, methods: List[_ComMemberSpec]) -> None:
if self._case_insensitive_:
self._make_case_insensitive()
# register com interface. we insist on an _iid_ in THIS class!
Expand Down Expand Up @@ -808,22 +805,22 @@ class IUnknown(_IUnknown_Base, metaclass=_cominterface_meta):
with STDMETHOD or COMMETHOD calls.
"""

_case_insensitive_ = False # type: ClassVar[bool]
_iid_ = GUID("{00000000-0000-0000-C000-000000000046}") # type: ClassVar[GUID]

_methods_ = [
_case_insensitive_: ClassVar[bool] = False
_iid_: ClassVar[GUID] = GUID("{00000000-0000-0000-C000-000000000046}")
_methods_: ClassVar[List[_ComMemberSpec]] = [
STDMETHOD(HRESULT, "QueryInterface", [POINTER(GUID), POINTER(c_void_p)]),
STDMETHOD(c_ulong, "AddRef"),
STDMETHOD(c_ulong, "Release"),
] # type: ClassVar[List[_ComMemberSpec]]
]

# NOTE: Why not `QueryInterface(T) -> _Pointer[T]`?
# Any static type checkers is not able to provide members of `T` from `_Pointer[T]`,
# regardless of the pointer is able to access members of contents in runtime.
# And if `isinstance(p, POINTER(T))` is `True`, then `isinstance(p, T)` is also `True`.
# So returning `T` is not a lie, and good way to know what members the class has.
def QueryInterface(self, interface, iid=None):
# type: (Type[_T_IUnknown], Optional[GUID]) -> _T_IUnknown
def QueryInterface(
self, interface: Type[_T_IUnknown], iid: Optional[GUID] = None
) -> _T_IUnknown:
"""QueryInterface(interface) -> instance"""
p = POINTER(interface)()
if iid is None:
Expand All @@ -836,13 +833,11 @@ def QueryInterface(self, interface, iid=None):

# these are only so that they get a docstring.
# XXX There should be other ways to install a docstring.
def AddRef(self):
# type: () -> int
def AddRef(self) -> int:
"""Increase the internal refcount by one and return it."""
return self.__com_AddRef()

def Release(self):
# type: () -> int
def Release(self) -> int:
"""Decrease the internal refcount by one and return it."""
return self.__com_Release()

Expand All @@ -867,12 +862,12 @@ def GetClassID(self) -> GUID:

class IServiceProvider(IUnknown):
_iid_ = GUID("{6D5140C1-7436-11CE-8034-00AA006009FA}")
if TYPE_CHECKING:
_QueryService: Callable[[Any, Any, Any], int]
_QueryService: Callable[[Any, Any, Any], int]
# Overridden QueryService to make it nicer to use (passing it an
# interface and it returns a pointer to that interface)
def QueryService(self, serviceIID, interface):
# type: (GUID, Type[_T_IUnknown]) -> _T_IUnknown
def QueryService(
self, serviceIID: GUID, interface: Type[_T_IUnknown]
) -> _T_IUnknown:
p = POINTER(interface)()
self._QueryService(byref(serviceIID), byref(interface._iid_), byref(p))
return p # type: ignore
Expand Down
54 changes: 23 additions & 31 deletions comtypes/automation.py
Original file line number Diff line number Diff line change
Expand Up @@ -749,32 +749,28 @@ def __del__(self):
DISPID_COLLECT = -8


if TYPE_CHECKING:
RawGetIDsOfNamesFunc = Callable[
[_byref_type, Array[c_wchar_p], int, int, Array[DISPID]],
int,
]
RawInvokeFunc = Callable[
[
int,
_byref_type,
int,
int, # dispIdMember, riid, lcid, wFlags
_UnionT[_byref_type, DISPPARAMS], # *pDispParams
_UnionT[_byref_type, VARIANT], # pVarResult
_UnionT[_byref_type, EXCEPINFO, None], # pExcepInfo
_UnionT[_byref_type, c_uint], # puArgErr
],
int,
]
RawGetIDsOfNamesFunc = Callable[
[_byref_type, "Array[c_wchar_p]", int, int, "Array[DISPID]"], int
]
# fmt: off
RawInvokeFunc = Callable[
[
int, _byref_type, int, int, # dispIdMember, riid, lcid, wFlags
_UnionT[_byref_type, DISPPARAMS], # *pDispParams
_UnionT[_byref_type, VARIANT], # pVarResult
_UnionT[_byref_type, EXCEPINFO, None], # pExcepInfo
_UnionT[_byref_type, c_uint], # puArgErr
],
int,
]
# fmt: on


class IDispatch(IUnknown):
if TYPE_CHECKING:
_disp_methods_: ClassVar[List[comtypes._DispMemberSpec]]
_GetTypeInfo: Callable[[int, int], IUnknown]
__com_GetIDsOfNames: RawGetIDsOfNamesFunc
__com_Invoke: RawInvokeFunc
_disp_methods_: ClassVar[List[comtypes._DispMemberSpec]]
_GetTypeInfo: Callable[[int, int], IUnknown]
__com_GetIDsOfNames: RawGetIDsOfNamesFunc
__com_Invoke: RawInvokeFunc

_iid_ = GUID("{00020400-0000-0000-C000-000000000046}")
_methods_ = [
Expand Down Expand Up @@ -811,16 +807,14 @@ class IDispatch(IUnknown):
),
]

def GetTypeInfo(self, index, lcid=0):
# type: (int, int) -> hints.ITypeInfo
def GetTypeInfo(self, index: int, lcid: int = 0) -> "hints.ITypeInfo":
"""Return type information. Index 0 specifies typeinfo for IDispatch"""
import comtypes.typeinfo

result = self._GetTypeInfo(index, lcid)
return result.QueryInterface(comtypes.typeinfo.ITypeInfo)

def GetIDsOfNames(self, *names, **kw):
# type: (str, Any) -> List[int]
def GetIDsOfNames(self, *names: str, **kw: Any) -> List[int]:
"""Map string names to integer ids."""
lcid = kw.pop("lcid", 0)
assert not kw
Expand All @@ -829,8 +823,7 @@ def GetIDsOfNames(self, *names, **kw):
self.__com_GetIDsOfNames(riid_null, arr, len(names), lcid, ids)
return ids[:]

def _invoke(self, memid, invkind, lcid, *args):
# type: (int, int, int, Any) -> Any
def _invoke(self, memid: int, invkind: int, lcid: int, *args: Any) -> Any:
var = VARIANT()
argerr = c_uint()
dp = DISPPARAMS()
Expand All @@ -850,8 +843,7 @@ def _invoke(self, memid, invkind, lcid, *args):
self.__com_Invoke(memid, riid_null, lcid, invkind, dp, var, None, argerr)
return var._get_value(dynamic=True)

def Invoke(self, dispid, *args, **kw):
# type: (int, Any, Any) -> Any
def Invoke(self, dispid: int, *args: Any, **kw: Any) -> Any:
"""Invoke a method or property."""

# Memory management in Dispatch::Invoke calls:
Expand Down
Loading

0 comments on commit 7b38a7a

Please sign in to comment.