From 9d716c7db570596dff4699ebfcaafaad2a01cf53 Mon Sep 17 00:00:00 2001 From: Jun Komoda <45822440+junkmd@users.noreply.github.com> Date: Thu, 19 Dec 2024 07:29:43 +0900 Subject: [PATCH] Add type hints to `server/inprocserver.py` and `server/localserver.py`. (#708) * Improve import section. * Add type hints to `inprocserver.DllCanUnloadNow`. * Add type hints to `inprocserver.DllGetClassObject`. * Add type hints to `inprocserver._setup_logging`. * Add type hints to `inprocserver.inproc_find_class`. * Add type hints to `inprocserver.ClassFactory.IClassFactory_LockServer`. * Add type hints to `inprocserver.ClassFactory.IClassFactory_CreateInstance`. * Add type hints to `inprocserver.ClassFactory.__init__`. * Improve import section. * Add type hints to `localserver.run`. * Add type hints to class variables and instance variables of `localserver.ClassFactory`. * Add type hints to `localserver.ClassFactory.__init__`. * Add type hints to `localserver.ClassFactory.IUnknown_AddRef`. * Add type hints to `localserver.ClassFactory.IUnknown_Release`. * Add type hints to `localserver.ClassFactory._register_class`. * Add type hints to `localserver.ClassFactory._revoke_class`. * Add type hints to `localserver.ClassFactory.CreateInstance`. * Add type hints to `localserver.ClassFactory.LockServer`. * Remove wildcard imports (`from comtypes.hresult import *`). * Remove wildcard imports (`from ctypes import *`). --- comtypes/server/inprocserver.py | 37 +++++++++++++++------------ comtypes/server/localserver.py | 44 +++++++++++++++++++++------------ 2 files changed, 49 insertions(+), 32 deletions(-) diff --git a/comtypes/server/inprocserver.py b/comtypes/server/inprocserver.py index 57935c30..33f7e8c2 100644 --- a/comtypes/server/inprocserver.py +++ b/comtypes/server/inprocserver.py @@ -1,12 +1,11 @@ import ctypes -from comtypes import COMObject, GUID -from comtypes.server import IClassFactory -from comtypes.hresult import * - -import sys import logging +import sys import winreg +from typing import Any, Literal, Optional, Type +from comtypes import GUID, COMObject, IUnknown, hresult +from comtypes.server import IClassFactory logger = logging.getLogger(__name__) _debug = logger.debug @@ -18,29 +17,35 @@ class ClassFactory(COMObject): _com_interfaces_ = [IClassFactory] - def __init__(self, cls): + def __init__(self, cls: Type[COMObject]) -> None: super(ClassFactory, self).__init__() self._cls = cls - def IClassFactory_CreateInstance(self, this, punkOuter, riid, ppv): + def IClassFactory_CreateInstance( + self, + this: Any, + punkOuter: Optional[Type["ctypes._Pointer[IUnknown]"]], + riid: "ctypes._Pointer[GUID]", + ppv: ctypes.c_void_p, + ) -> int: _debug("ClassFactory.CreateInstance(%s)", riid[0]) result = self._cls().IUnknown_QueryInterface(None, riid, ppv) _debug("CreateInstance() -> %s", result) return result - def IClassFactory_LockServer(self, this, fLock): + def IClassFactory_LockServer(self, this: Any, fLock: bool) -> Literal[0]: if fLock: COMObject.__server__.Lock() else: COMObject.__server__.Unlock() - return S_OK + return hresult.S_OK # will be set by py2exe boot script 'from outside' _clsid_to_class = {} -def inproc_find_class(clsid): +def inproc_find_class(clsid: GUID) -> Type[COMObject]: if _clsid_to_class: return _clsid_to_class[clsid] @@ -70,7 +75,7 @@ def inproc_find_class(clsid): _logging_configured = False -def _setup_logging(clsid): +def _setup_logging(clsid: GUID) -> None: """Read from the registry, and configure the logging module. Currently, the handler (NTDebugHandler) is hardcoded. @@ -109,7 +114,7 @@ def _setup_logging(clsid): logging.getLogger(name).setLevel(level) -def DllGetClassObject(rclsid, riid, ppv): +def DllGetClassObject(rclsid: int, riid: int, ppv: int) -> int: COMObject.__run_inprocserver__() iid = GUID.from_address(riid) @@ -127,7 +132,7 @@ def DllGetClassObject(rclsid, riid, ppv): cls = inproc_find_class(clsid) if not cls: - return CLASS_E_CLASSNOTAVAILABLE + return hresult.CLASS_E_CLASSNOTAVAILABLE result = ClassFactory(cls).IUnknown_QueryInterface( None, ctypes.pointer(iid), ctypes.c_void_p(ppv) @@ -136,12 +141,12 @@ def DllGetClassObject(rclsid, riid, ppv): return result except Exception: _critical("DllGetClassObject", exc_info=True) - return E_FAIL + return hresult.E_FAIL -def DllCanUnloadNow(): +def DllCanUnloadNow() -> Literal[1]: # S_FALSE COMObject.__run_inprocserver__() result = COMObject.__server__.DllCanUnloadNow() # To avoid a memory leak when PyInitialize()/PyUninitialize() are # called several times, we refuse to unload the dll. - return S_FALSE + return hresult.S_FALSE diff --git a/comtypes/server/localserver.py b/comtypes/server/localserver.py index 1f50d21a..62907792 100644 --- a/comtypes/server/localserver.py +++ b/comtypes/server/localserver.py @@ -1,10 +1,16 @@ +import logging +import queue import sys -from ctypes import * +from ctypes import byref, c_ulong, c_void_p, oledll +from typing import TYPE_CHECKING, Any, Literal, Optional, Sequence, Type + import comtypes -from comtypes.hresult import * +from comtypes import hresult from comtypes.server import IClassFactory -import logging -import queue + +if TYPE_CHECKING: + from ctypes import _Pointer + logger = logging.getLogger(__name__) _debug = logger.debug @@ -16,31 +22,31 @@ REGCLS_SURROGATE = 8 # must be used when a surrogate process -def run(classes): +def run(classes: Sequence[Type[comtypes.COMObject]]) -> None: classobjects = [ClassFactory(cls) for cls in classes] comtypes.COMObject.__run_localserver__(classobjects) class ClassFactory(comtypes.COMObject): _com_interfaces_ = [IClassFactory] - _locks = 0 - _queue = None - regcls = REGCLS_MULTIPLEUSE + _locks: int = 0 + _queue: Optional[queue.Queue] = None + regcls: int = REGCLS_MULTIPLEUSE - def __init__(self, cls, *args, **kw): + def __init__(self, cls: Type[comtypes.COMObject], *args, **kw) -> None: super(ClassFactory, self).__init__() self._cls = cls self._register_class() self._args = args self._kw = kw - def IUnknown_AddRef(self, this): + def IUnknown_AddRef(self, this: Any) -> int: return 2 - def IUnknown_Release(self, this): + def IUnknown_Release(self, this: Any) -> int: return 1 - def _register_class(self): + def _register_class(self) -> None: regcls = getattr(self._cls, "_regcls_", self.regcls) cookie = c_ulong() ptr = self._com_pointers_[comtypes.IUnknown._iid_] @@ -55,19 +61,25 @@ def _register_class(self): ) self.cookie = cookie - def _revoke_class(self): + def _revoke_class(self) -> None: oledll.ole32.CoRevokeClassObject(self.cookie) - def CreateInstance(self, this, punkOuter, riid, ppv): + def CreateInstance( + self, + this: Any, + punkOuter: Optional[Type["_Pointer[comtypes.IUnknown]"]], + riid: "_Pointer[comtypes.GUID]", + ppv: c_void_p, + ) -> int: _debug("ClassFactory.CreateInstance(%s)", riid[0]) obj = self._cls(*self._args, **self._kw) result = obj.IUnknown_QueryInterface(None, riid, ppv) _debug("CreateInstance() -> %s", result) return result - def LockServer(self, this, fLock): + def LockServer(self, this: Any, fLock: bool) -> Literal[0]: if fLock: comtypes.COMObject.__server__.Lock() else: comtypes.COMObject.__server__.Unlock() - return S_OK + return hresult.S_OK