Skip to content

Commit

Permalink
Add type hints to server/inprocserver.py and `server/localserver.py…
Browse files Browse the repository at this point in the history
…`. (#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 *`).
  • Loading branch information
junkmd authored Dec 18, 2024
1 parent 1439e3b commit 9d716c7
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 32 deletions.
37 changes: 21 additions & 16 deletions comtypes/server/inprocserver.py
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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]

Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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)
Expand All @@ -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)
Expand All @@ -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
44 changes: 28 additions & 16 deletions comtypes/server/localserver.py
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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_]
Expand All @@ -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

0 comments on commit 9d716c7

Please sign in to comment.