Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add type hints to server/inprocserver.py and server/localserver.py. #708

Merged
merged 20 commits into from
Dec 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
dbbd282
Improve import section.
junkmd Dec 18, 2024
64f6619
Add type hints to `inprocserver.DllCanUnloadNow`.
junkmd Dec 18, 2024
e5daa71
Add type hints to `inprocserver.DllGetClassObject`.
junkmd Dec 18, 2024
b6e41e3
Add type hints to `inprocserver._setup_logging`.
junkmd Dec 18, 2024
5606346
Add type hints to `inprocserver.inproc_find_class`.
junkmd Dec 18, 2024
ed36294
Add type hints to `inprocserver.ClassFactory.IClassFactory_LockServer`.
junkmd Dec 18, 2024
a296d11
Add type hints to `inprocserver.ClassFactory.IClassFactory_CreateInst…
junkmd Dec 18, 2024
a073df4
Add type hints to `inprocserver.ClassFactory.__init__`.
junkmd Dec 18, 2024
88edb9a
Improve import section.
junkmd Dec 18, 2024
3920324
Add type hints to `localserver.run`.
junkmd Dec 18, 2024
c32983f
Add type hints to class variables and instance variables of `localser…
junkmd Dec 18, 2024
9c0a1b9
Add type hints to `localserver.ClassFactory.__init__`.
junkmd Dec 18, 2024
8515fb4
Add type hints to `localserver.ClassFactory.IUnknown_AddRef`.
junkmd Dec 18, 2024
70e350d
Add type hints to `localserver.ClassFactory.IUnknown_Release`.
junkmd Dec 18, 2024
a876fc2
Add type hints to `localserver.ClassFactory._register_class`.
junkmd Dec 18, 2024
61f49fd
Add type hints to `localserver.ClassFactory._revoke_class`.
junkmd Dec 18, 2024
5a7b918
Add type hints to `localserver.ClassFactory.CreateInstance`.
junkmd Dec 18, 2024
0ee20fb
Add type hints to `localserver.ClassFactory.LockServer`.
junkmd Dec 18, 2024
14f7241
Remove wildcard imports (`from comtypes.hresult import *`).
junkmd Dec 18, 2024
864bebe
Remove wildcard imports (`from ctypes import *`).
junkmd Dec 18, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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