From 275984b841768127ab26600038d0e481f0807e64 Mon Sep 17 00:00:00 2001 From: donbarbos Date: Thu, 19 Mar 2026 22:55:51 +0400 Subject: [PATCH 01/12] [pywin32] Improve win32com * Add `Final` * Add default values * Use `bool | Literal[0, 1]` for boolean params (instead of `int`) * Annotate known parts (Source: https://github.com/mhammond/pywin32/tree/b311/com/win32com) --- stubs/pywin32/win32com/client/__init__.pyi | 46 ++-- stubs/pywin32/win32com/client/build.pyi | 84 +++++--- stubs/pywin32/win32com/client/dynamic.pyi | 37 ++-- stubs/pywin32/win32com/client/gencache.pyi | 5 +- stubs/pywin32/win32com/olectl.pyi | 102 ++++----- stubs/pywin32/win32com/server/connect.pyi | 19 +- stubs/pywin32/win32com/server/exception.pyi | 30 ++- stubs/pywin32/win32com/server/policy.pyi | 11 +- stubs/pywin32/win32com/server/util.pyi | 31 ++- stubs/pywin32/win32com/storagecon.pyi | 228 ++++++++++---------- stubs/pywin32/win32com/universal.pyi | 26 ++- stubs/pywin32/win32com/util.pyi | 2 +- 12 files changed, 344 insertions(+), 277 deletions(-) diff --git a/stubs/pywin32/win32com/client/__init__.pyi b/stubs/pywin32/win32com/client/__init__.pyi index 987a842edbec..1afbe6dda5f6 100644 --- a/stubs/pywin32/win32com/client/__init__.pyi +++ b/stubs/pywin32/win32com/client/__init__.pyi @@ -9,32 +9,25 @@ from win32com.client import dynamic _Stringifiable: TypeAlias = object -def GetObject(Pathname: str | None = ..., Class: Incomplete | None = ..., clsctx: Incomplete | None = ...) -> CDispatch: ... -def GetActiveObject(Class, clsctx=...): ... -def Moniker(Pathname, clsctx=...): ... +def GetObject(Pathname: str | None = None, Class=None, clsctx=None) -> CDispatch: ... +def GetActiveObject(Class: str, clsctx=...): ... +def Moniker(Pathname: str, clsctx=...): ... def Dispatch( dispatch: str | dynamic.PyIDispatchType | dynamic._GoodDispatchTypes | dynamic.PyIUnknownType, - userName: str | None = ..., - resultCLSID: _Stringifiable | None = ..., - typeinfo: _win32typing.PyITypeInfo | None = ..., + userName: str | None = None, + resultCLSID: _Stringifiable | None = None, + typeinfo: _win32typing.PyITypeInfo | None = None, clsctx: int = ..., ) -> dynamic.CDispatch: ... -def DispatchEx( - clsid, - machine: Incomplete | None = ..., - userName: Incomplete | None = ..., - resultCLSID: Incomplete | None = ..., - typeinfo: Incomplete | None = ..., - clsctx: Incomplete | None = ..., -): ... +def DispatchEx(clsid, machine=None, userName=None, resultCLSID=None, typeinfo=None, clsctx=None): ... class CDispatch(dynamic.CDispatch): - def __dir__(self): ... + def __dir__(self) -> list[str]: ... -def CastTo(ob, target, typelib: Incomplete | None = ...): ... +def CastTo(ob, target, typelib=None): ... class Constants: - __dicts__: Incomplete + __dicts__: list[Incomplete] def __getattr__(self, a: str): ... constants: Final[Constants] @@ -45,22 +38,22 @@ class EventsProxy: def __getattr__(self, attr: str): ... def __setattr__(self, attr: str, val) -> None: ... -def DispatchWithEvents(clsid, user_event_class): ... +def DispatchWithEvents(clsid, user_event_class) -> EventsProxy: ... def WithEvents(disp, user_event_class): ... def getevents(clsid): ... def Record(name, object) -> com_record: ... def register_record_class(cls) -> None: ... class DispatchBaseClass: - def __init__(self, oobj: Incomplete | None = ...) -> None: ... - def __dir__(self): ... - def __eq__(self, other): ... - def __ne__(self, other): ... + def __init__(self, oobj=None) -> None: ... + def __dir__(self) -> list[str]: ... + def __eq__(self, other) -> bool: ... + def __ne__(self, other) -> bool: ... def __getattr__(self, attr: str): ... def __setattr__(self, attr: str, value) -> None: ... class CoClassBaseClass: - def __init__(self, oobj: Incomplete | None = ...) -> None: ... + def __init__(self, oobj=None) -> None: ... def __getattr__(self, attr: str): ... def __setattr__(self, attr: str, value) -> None: ... def __call__(self, *args, **kwargs): ... @@ -73,4 +66,9 @@ class CoClassBaseClass: class VARIANT: varianttype: Incomplete def __init__(self, vt, value) -> None: ... - value: Incomplete + @property + def value(self): ... + @value.setter + def value(self, newval) -> None: ... + @value.deleter + def value(self) -> None: ... diff --git a/stubs/pywin32/win32com/client/build.pyi b/stubs/pywin32/win32com/client/build.pyi index cbbcd2e9a1f8..5eba28add3f4 100644 --- a/stubs/pywin32/win32com/client/build.pyi +++ b/stubs/pywin32/win32com/client/build.pyi @@ -1,36 +1,70 @@ from _typeshed import Incomplete +from collections.abc import Iterable +from typing import ClassVar, Final, Literal + +class NotSupportedException(Exception): ... + +DropIndirection: Final = "DropIndirection" +NoTranslateTypes: Final[list[int]] +NoTranslateMap: Final[set[int]] + +class MapEntry: + dispid: Incomplete + desc: Incomplete | None + names: Incomplete + doc: Incomplete + resultCLSID: Incomplete + resultDocumentation: Incomplete | None + wasProperty: Incomplete + hidden: bool | Literal[0, 1] + def __init__( + self, desc_or_id, names=None, doc=None, resultCLSID=..., resultDoc=None, hidden: bool | Literal[0, 1] = 0 + ) -> None: ... + def GetResultCLSID(self) -> Incomplete | None: ... + def GetResultCLSIDStr(self) -> str: ... + def GetResultName(self) -> Incomplete | None: ... class OleItem: - typename: str + typename: ClassVar[str] doc: Incomplete - python_name: Incomplete - bWritten: int - bIsDispatch: int - bIsSink: int - clsid: Incomplete - co_class: Incomplete - def __init__(self, doc: Incomplete | None = ...) -> None: ... + python_name: Incomplete | None + bWritten: bool | Literal[0, 1] + bIsDispatch: bool | Literal[0, 1] + bIsSink: bool | Literal[0, 1] + clsid: Incomplete | None + co_class: Incomplete | None + def __init__(self, doc=None) -> None: ... class DispatchItem(OleItem): - typename: str - propMap: Incomplete - propMapGet: Incomplete - propMapPut: Incomplete - mapFuncs: Incomplete - defaultDispatchName: Incomplete - hidden: int - def __init__( - self, typeinfo: Incomplete | None = ..., attr: Incomplete | None = ..., doc: Incomplete | None = ..., bForUser: int = ... - ) -> None: ... + typename: ClassVar[str] + propMap: dict[Incomplete, Incomplete] + propMapGet: dict[Incomplete, Incomplete] + propMapPut: dict[Incomplete, Incomplete] + mapFuncs: dict[Incomplete, Incomplete] + defaultDispatchName: Incomplete | None + hidden: bool | Literal[0, 1] + def __init__(self, typeinfo=None, attr=None, doc=None, bForUser: bool | Literal[0, 1] = 1) -> None: ... clsid: Incomplete - bIsDispatch: Incomplete - def Build(self, typeinfo, attr, bForUser: int = ...) -> None: ... - def CountInOutOptArgs(self, argTuple): ... - def MakeFuncMethod(self, entry, name, bMakeClass: int = ...): ... - def MakeDispatchFuncMethod(self, entry, name, bMakeClass: int = ...): ... - def MakeVarArgsFuncMethod(self, entry, name, bMakeClass: int = ...): ... + bIsDispatch: bool | Literal[0, 1] + def Build(self, typeinfo, attr, bForUser: bool | Literal[0, 1] = 1) -> None: ... + def CountInOutOptArgs(self, argTuple: Iterable[Incomplete]) -> tuple[int, int, int]: ... + def MakeFuncMethod(self, entry, name: str, bMakeClass: bool | Literal[0, 1] = 1) -> list[str]: ... + def MakeDispatchFuncMethod(self, entry, name: str, bMakeClass: bool | Literal[0, 1] = 1) -> list[str]: ... + def MakeVarArgsFuncMethod(self, entry, name: str, bMakeClass: bool | Literal[0, 1] = 1) -> list[str]: ... + +class VTableItem(DispatchItem): + vtableFuncs: list[tuple[Incomplete, Incomplete, Incomplete]] + def Build(self, typeinfo, attr, bForUser: bool | Literal[0, 1] = 1) -> None: ... class LazyDispatchItem(DispatchItem): - typename: str + typename: ClassVar[str] clsid: Incomplete def __init__(self, attr, doc) -> None: ... + +typeSubstMap: Final[dict[int, int]] +valid_identifier_chars: Final[str] + +def demunge_leading_underscores(className: str) -> str: ... +def MakePublicAttributeName(className: str, is_global: bool = False) -> str: ... +def MakeDefaultArgRepr(defArgVal) -> str | None: ... +def BuildCallList(fdesc, names, defNamedOptArg, defNamedNotOptArg, defUnnamedArg, defOutArg, is_comment: bool = False) -> str: ... diff --git a/stubs/pywin32/win32com/client/dynamic.pyi b/stubs/pywin32/win32com/client/dynamic.pyi index 17b3cb620fff..e0a8de476563 100644 --- a/stubs/pywin32/win32com/client/dynamic.pyi +++ b/stubs/pywin32/win32com/client/dynamic.pyi @@ -1,5 +1,5 @@ from _typeshed import Incomplete -from typing import Any, Protocol, TypeVar, overload +from typing import Any, Final, Literal, Protocol, TypeVar, overload, type_check_only from typing_extensions import TypeAlias import _win32typing @@ -9,23 +9,24 @@ from win32com.client import build _T_co = TypeVar("_T_co", covariant=True) _T = TypeVar("_T") +@type_check_only class _DispatchCreateClass(Protocol[_T_co]): @staticmethod def __call__( IDispatch: str | PyIDispatchType | _GoodDispatchTypes | PyIUnknownType, olerepr: build.DispatchItem | build.LazyDispatchItem, - userName: str | None = ..., - lazydata: Incomplete | None = ..., + userName: str | None = None, + lazydata=None, ) -> _T_co: ... debugging: int debugging_attr: int -LCID: int -ERRORS_BAD_CONTEXT: Incomplete -ALL_INVOKE_TYPES: Incomplete +LCID: Final = 0x0 +ERRORS_BAD_CONTEXT: Final[list[int]] +ALL_INVOKE_TYPES: Final[list[int]] -def debug_print(*args) -> None: ... -def debug_attr_print(*args) -> None: ... +def debug_print(*args: object) -> None: ... +def debug_attr_print(*args: object) -> None: ... PyIDispatchType = _win32typing.PyIDispatch PyIUnknownType = _win32typing.PyIUnknown @@ -37,32 +38,32 @@ def Dispatch( IDispatch: str | PyIDispatchType | _GoodDispatchTypes | PyIUnknownType, userName: str | None, createClass: _DispatchCreateClass[_T], - typeinfo: _win32typing.PyITypeInfo | None = ..., + typeinfo: _win32typing.PyITypeInfo | None = None, clsctx: int = ..., ) -> _T: ... @overload def Dispatch( IDispatch: str | PyIDispatchType | _GoodDispatchTypes | PyIUnknownType, - userName: str | None = ..., + userName: str | None = None, createClass: None = None, - typeinfo: _win32typing.PyITypeInfo | None = ..., + typeinfo: _win32typing.PyITypeInfo | None = None, clsctx: int = ..., ) -> CDispatch: ... -def MakeOleRepr(IDispatch, typeinfo, typecomp): ... -def DumbDispatch(IDispatch, userName: Incomplete | None = ..., createClass: Incomplete | None = ..., clsctx=...): ... +def MakeOleRepr(IDispatch, typeinfo, typecomp) -> build.DispatchItem | build.LazyDispatchItem: ... +def DumbDispatch(IDispatch, userName=None, createClass=None, clsctx=...): ... class CDispatch: - def __init__(self, IDispatch, olerepr, userName: Incomplete | None = ..., lazydata: Incomplete | None = ...) -> None: ... + def __init__(self, IDispatch, olerepr, userName=None, lazydata=None) -> None: ... def __call__(self, *args): ... def __bool__(self) -> bool: ... - def __dir__(self): ... - def __eq__(self, other): ... - def __ne__(self, other): ... + def __dir__(self) -> list[str]: ... + def __eq__(self, other) -> bool: ... + def __ne__(self, other) -> bool: ... def __int__(self) -> int: ... def __len__(self) -> int: ... def __getitem__(self, index): ... def __setitem__(self, index, *args) -> None: ... - def __LazyMap__(self, attr): ... + def __LazyMap__(self, attr) -> Literal[0, 1] | None: ... def __AttrToID__(self, attr): ... ob: Incomplete # CDispatch objects are dynamically generated and too complex to type diff --git a/stubs/pywin32/win32com/client/gencache.pyi b/stubs/pywin32/win32com/client/gencache.pyi index 825af08d8701..d25ec58c0f59 100644 --- a/stubs/pywin32/win32com/client/gencache.pyi +++ b/stubs/pywin32/win32com/client/gencache.pyi @@ -1,5 +1,8 @@ +from typing import Literal + from win32com.client import dynamic def EnsureDispatch( - prog_id: str | dynamic.PyIDispatchType | dynamic._GoodDispatchTypes | dynamic.PyIUnknownType, bForDemand: int = ... + prog_id: str | dynamic.PyIDispatchType | dynamic._GoodDispatchTypes | dynamic.PyIUnknownType, + bForDemand: bool | Literal[0, 1] = 1, ) -> dynamic.CDispatch: ... diff --git a/stubs/pywin32/win32com/olectl.pyi b/stubs/pywin32/win32com/olectl.pyi index 33c11076d847..bfd6283a5497 100644 --- a/stubs/pywin32/win32com/olectl.pyi +++ b/stubs/pywin32/win32com/olectl.pyi @@ -1,54 +1,56 @@ -FACILITY_CONTROL: int +from typing import Final + +FACILITY_CONTROL: Final = 0xA def MAKE_SCODE(sev: int, fac: int, code: int) -> int: ... def STD_CTL_SCODE(n: int) -> int: ... -CTL_E_ILLEGALFUNCTIONCALL: int -CTL_E_OVERFLOW: int -CTL_E_OUTOFMEMORY: int -CTL_E_DIVISIONBYZERO: int -CTL_E_OUTOFSTRINGSPACE: int -CTL_E_OUTOFSTACKSPACE: int -CTL_E_BADFILENAMEORNUMBER: int -CTL_E_FILENOTFOUND: int -CTL_E_BADFILEMODE: int -CTL_E_FILEALREADYOPEN: int -CTL_E_DEVICEIOERROR: int -CTL_E_FILEALREADYEXISTS: int -CTL_E_BADRECORDLENGTH: int -CTL_E_DISKFULL: int -CTL_E_BADRECORDNUMBER: int -CTL_E_BADFILENAME: int -CTL_E_TOOMANYFILES: int -CTL_E_DEVICEUNAVAILABLE: int -CTL_E_PERMISSIONDENIED: int -CTL_E_DISKNOTREADY: int -CTL_E_PATHFILEACCESSERROR: int -CTL_E_PATHNOTFOUND: int -CTL_E_INVALIDPATTERNSTRING: int -CTL_E_INVALIDUSEOFNULL: int -CTL_E_INVALIDFILEFORMAT: int -CTL_E_INVALIDPROPERTYVALUE: int -CTL_E_INVALIDPROPERTYARRAYINDEX: int -CTL_E_SETNOTSUPPORTEDATRUNTIME: int -CTL_E_SETNOTSUPPORTED: int -CTL_E_NEEDPROPERTYARRAYINDEX: int -CTL_E_SETNOTPERMITTED: int -CTL_E_GETNOTSUPPORTEDATRUNTIME: int -CTL_E_GETNOTSUPPORTED: int -CTL_E_PROPERTYNOTFOUND: int -CTL_E_INVALIDCLIPBOARDFORMAT: int -CTL_E_INVALIDPICTURE: int -CTL_E_PRINTERERROR: int -CTL_E_CANTSAVEFILETOTEMP: int -CTL_E_SEARCHTEXTNOTFOUND: int -CTL_E_REPLACEMENTSTOOLONG: int -CONNECT_E_FIRST: int -CONNECT_E_LAST: int -CONNECT_S_FIRST: int -CONNECT_S_LAST: int -CONNECT_E_NOCONNECTION: int -CONNECT_E_ADVISELIMIT: int -CONNECT_E_CANNOTCONNECT: int -CONNECT_E_OVERRIDDEN: int -CLASS_E_NOTLICENSED: int +CTL_E_ILLEGALFUNCTIONCALL: Final = -2146828283 +CTL_E_OVERFLOW: Final = -2146828282 +CTL_E_OUTOFMEMORY: Final = -2146828281 +CTL_E_DIVISIONBYZERO: Final = -2146828277 +CTL_E_OUTOFSTRINGSPACE: Final = -2146828274 +CTL_E_OUTOFSTACKSPACE: Final = -2146828260 +CTL_E_BADFILENAMEORNUMBER: Final = -2146828236 +CTL_E_FILENOTFOUND: Final = -2146828235 +CTL_E_BADFILEMODE: Final = -2146828234 +CTL_E_FILEALREADYOPEN: Final = -2146828233 +CTL_E_DEVICEIOERROR: Final = -2146828231 +CTL_E_FILEALREADYEXISTS: Final = -2146828230 +CTL_E_BADRECORDLENGTH: Final = -2146828229 +CTL_E_DISKFULL: Final = -2146828227 +CTL_E_BADRECORDNUMBER: Final = -2146828225 +CTL_E_BADFILENAME: Final = -2146828224 +CTL_E_TOOMANYFILES: Final = -2146828221 +CTL_E_DEVICEUNAVAILABLE: Final = -2146828220 +CTL_E_PERMISSIONDENIED: Final = -2146828218 +CTL_E_DISKNOTREADY: Final = -2146828217 +CTL_E_PATHFILEACCESSERROR: Final = -2146828213 +CTL_E_PATHNOTFOUND: Final = -2146828212 +CTL_E_INVALIDPATTERNSTRING: Final = -2146828195 +CTL_E_INVALIDUSEOFNULL: Final = -2146828194 +CTL_E_INVALIDFILEFORMAT: Final = -2146827967 +CTL_E_INVALIDPROPERTYVALUE: Final = -2146827908 +CTL_E_INVALIDPROPERTYARRAYINDEX: Final = -2146827907 +CTL_E_SETNOTSUPPORTEDATRUNTIME: Final = -2146827906 +CTL_E_SETNOTSUPPORTED: Final = -2146827905 +CTL_E_NEEDPROPERTYARRAYINDEX: Final = -2146827903 +CTL_E_SETNOTPERMITTED: Final = -2146827901 +CTL_E_GETNOTSUPPORTEDATRUNTIME: Final = -2146827895 +CTL_E_GETNOTSUPPORTED: Final = -2146827894 +CTL_E_PROPERTYNOTFOUND: Final = -2146827866 +CTL_E_INVALIDCLIPBOARDFORMAT: Final = -2146827828 +CTL_E_INVALIDPICTURE: Final = -2146827807 +CTL_E_PRINTERERROR: Final = -2146827806 +CTL_E_CANTSAVEFILETOTEMP: Final = -2146827553 +CTL_E_SEARCHTEXTNOTFOUND: Final = -2146827544 +CTL_E_REPLACEMENTSTOOLONG: Final = -2146827542 +CONNECT_E_FIRST: Final = -2147220992 +CONNECT_E_LAST: Final = -2147220977 +CONNECT_S_FIRST: Final = 262656 +CONNECT_S_LAST: Final = 262671 +CONNECT_E_NOCONNECTION: Final = -2147220992 +CONNECT_E_ADVISELIMIT: Final = -2147220991 +CONNECT_E_CANNOTCONNECT: Final = -2147220990 +CONNECT_E_OVERRIDDEN: Final = -2147220989 +CLASS_E_NOTLICENSED: Final = -2147221230 diff --git a/stubs/pywin32/win32com/server/connect.pyi b/stubs/pywin32/win32com/server/connect.pyi index 4c8a1878546e..d4f5e9994d9f 100644 --- a/stubs/pywin32/win32com/server/connect.pyi +++ b/stubs/pywin32/win32com/server/connect.pyi @@ -1,15 +1,22 @@ from _typeshed import Incomplete +from typing import Final -IConnectionPointContainer_methods: Incomplete -IConnectionPoint_methods: Incomplete +IConnectionPointContainer_methods: Final = ["EnumConnectionPoints", "FindConnectionPoint"] +IConnectionPoint_methods: Final = [ + "EnumConnections", + "Unadvise", + "Advise", + "GetConnectionPointContainer", + "GetConnectionInterface", +] class ConnectableServer: cookieNo: int - connections: Incomplete + connections: dict[int, Incomplete] def EnumConnections(self) -> None: ... def GetConnectionInterface(self) -> None: ... def GetConnectionPointContainer(self): ... - def Advise(self, pUnk): ... - def Unadvise(self, cookie) -> None: ... + def Advise(self, pUnk) -> int: ... + def Unadvise(self, cookie: int) -> None: ... def EnumConnectionPoints(self) -> None: ... - def FindConnectionPoint(self, iid): ... + def FindConnectionPoint(self, iid) -> Incomplete | None: ... diff --git a/stubs/pywin32/win32com/server/exception.pyi b/stubs/pywin32/win32com/server/exception.pyi index 39e793a336ed..44427b52a099 100644 --- a/stubs/pywin32/win32com/server/exception.pyi +++ b/stubs/pywin32/win32com/server/exception.pyi @@ -1,23 +1,21 @@ -from _typeshed import Incomplete - import pythoncom class COMException(pythoncom.com_error): - scode: Incomplete - description: Incomplete - source: Incomplete - helpfile: Incomplete - helpcontext: Incomplete + scode: int + description: str + source: str | None + helpfile: str | None + helpcontext: int | None def __init__( self, - description: Incomplete | None = ..., - scode: Incomplete | None = ..., - source: Incomplete | None = ..., - helpfile: Incomplete | None = ..., - helpContext: Incomplete | None = ..., - desc: Incomplete | None = ..., - hresult: Incomplete | None = ..., + description: str | None = None, + scode: int | None = None, + source: str | None = None, + helpfile: str | None = None, + helpContext: int | None = None, + desc: str | None = None, + hresult: int | None = None, ) -> None: ... -def IsCOMException(t: Incomplete | None = ...): ... -def IsCOMServerException(t: Incomplete | None = ...): ... +def IsCOMException(t: type[BaseException] | None = None) -> bool: ... +def IsCOMServerException(t: type[BaseException] | None = None) -> bool: ... diff --git a/stubs/pywin32/win32com/server/policy.pyi b/stubs/pywin32/win32com/server/policy.pyi index a6c079adc896..16a28eec5792 100644 --- a/stubs/pywin32/win32com/server/policy.pyi +++ b/stubs/pywin32/win32com/server/policy.pyi @@ -1,7 +1,10 @@ from _typeshed import Incomplete from abc import ABC, abstractmethod +from typing import Final -S_OK: int +import _win32typing + +S_OK: Final = 0 IDispatchType: Incomplete IUnknownType: Incomplete regSpec: str @@ -9,7 +12,7 @@ regPolicy: str regDispatcher: str regAddnPath: str -def CreateInstance(clsid, reqIID): ... +def CreateInstance(clsid, reqIID: _win32typing.PyIID) -> _win32typing.PyIUnknown: ... class BasicWrapPolicy(ABC): def __init__(self, object) -> None: ... @@ -29,8 +32,8 @@ class DynamicPolicy(BasicWrapPolicy): DefaultPolicy = DesignatedWrapPolicy -def resolve_func(spec): ... -def call_func(spec, *args): ... +def resolve_func(spec: str): ... +def call_func(spec: str, *args): ... DISPATCH_METHOD: int DISPATCH_PROPERTYGET: int diff --git a/stubs/pywin32/win32com/server/util.pyi b/stubs/pywin32/win32com/server/util.pyi index eb1051f81dc7..526057dbfe60 100644 --- a/stubs/pywin32/win32com/server/util.pyi +++ b/stubs/pywin32/win32com/server/util.pyi @@ -1,39 +1,48 @@ from _typeshed import Incomplete +from typing import Literal import _win32typing -def wrap(ob, iid: Incomplete | None = ..., usePolicy: Incomplete | None = ..., useDispatcher: Incomplete | None = ...): ... +def wrap( + ob, iid=None, usePolicy: type[Incomplete] | None = None, useDispatcher: type[Incomplete] | bool | Literal[0, 1] | None = None +): ... def unwrap(ob): ... class ListEnumerator: - index: Incomplete - def __init__(self, data, index: int = ..., iid=...) -> None: ... - def Next(self, count): ... - def Skip(self, count) -> None: ... + index: int + def __init__(self, data, index: int = 0, iid=...) -> None: ... + def Next(self, count: int): ... + def Skip(self, count: int) -> None: ... def Reset(self) -> None: ... def Clone(self): ... class ListEnumeratorGateway(ListEnumerator): - def Next(self, count): ... + def Next(self, count: int) -> map[Incomplete]: ... -def NewEnum(seq, cls=..., iid=..., usePolicy: Incomplete | None = ..., useDispatcher: Incomplete | None = ...): ... +def NewEnum( + seq, + cls=..., + iid=..., + usePolicy: type[Incomplete] | None = None, + useDispatcher: type[Incomplete] | bool | Literal[0, 1] | None = None, +): ... class Collection: data: Incomplete - def __init__(self, data: Incomplete | None = ..., readOnly: int = ...) -> None: ... + def __init__(self, data=None, readOnly: bool | Literal[0, 1] = 0) -> None: ... def Item(self, *args): ... def Count(self): ... def Add(self, value) -> None: ... def Remove(self, index) -> None: ... def Insert(self, index, value) -> None: ... -def NewCollection(seq, cls=...): ... +def NewCollection(seq, cls=...) -> _win32typing.PyIUnknown: ... class FileStream: file: Incomplete def __init__(self, file: _win32typing.Pymmapfile) -> None: ... def Read(self, amount): ... - def Write(self, data): ... + def Write(self, data) -> int: ... def Clone(self): ... - def CopyTo(self, dest, cb): ... + def CopyTo(self, dest, cb) -> tuple[int, int]: ... def Seek(self, offset: int, origin: int) -> int: ... diff --git a/stubs/pywin32/win32com/storagecon.pyi b/stubs/pywin32/win32com/storagecon.pyi index 3242473ca1d3..717bba5ebcba 100644 --- a/stubs/pywin32/win32com/storagecon.pyi +++ b/stubs/pywin32/win32com/storagecon.pyi @@ -1,113 +1,115 @@ -STGC_DEFAULT: int -STGC_OVERWRITE: int -STGC_ONLYIFCURRENT: int -STGC_DANGEROUSLYCOMMITMERELYTODISKCACHE: int -STGC_CONSOLIDATE: int -STGTY_STORAGE: int -STGTY_STREAM: int -STGTY_LOCKBYTES: int -STGTY_PROPERTY: int -STREAM_SEEK_SET: int -STREAM_SEEK_CUR: int -STREAM_SEEK_END: int -LOCK_WRITE: int -LOCK_EXCLUSIVE: int -LOCK_ONLYONCE: int -CWCSTORAGENAME: int -STGM_DIRECT: int -STGM_TRANSACTED: int -STGM_SIMPLE: int -STGM_READ: int -STGM_WRITE: int -STGM_READWRITE: int -STGM_SHARE_DENY_NONE: int -STGM_SHARE_DENY_READ: int -STGM_SHARE_DENY_WRITE: int -STGM_SHARE_EXCLUSIVE: int -STGM_PRIORITY: int -STGM_DELETEONRELEASE: int -STGM_NOSCRATCH: int -STGM_CREATE: int -STGM_CONVERT: int -STGM_FAILIFTHERE: int -STGM_NOSNAPSHOT: int -ASYNC_MODE_COMPATIBILITY: int -ASYNC_MODE_DEFAULT: int -STGTY_REPEAT: int -STG_TOEND: int -STG_LAYOUT_SEQUENTIAL: int -STG_LAYOUT_INTERLEAVED: int -COM_RIGHTS_EXECUTE: int -COM_RIGHTS_EXECUTE_LOCAL: int -COM_RIGHTS_EXECUTE_REMOTE: int -COM_RIGHTS_ACTIVATE_LOCAL: int -COM_RIGHTS_ACTIVATE_REMOTE: int -STGFMT_DOCUMENT: int -STGFMT_STORAGE: int -STGFMT_NATIVE: int -STGFMT_FILE: int -STGFMT_ANY: int -STGFMT_DOCFILE: int -PID_DICTIONARY: int -PID_CODEPAGE: int -PID_FIRST_USABLE: int -PID_FIRST_NAME_DEFAULT: int -PID_LOCALE: int -PID_MODIFY_TIME: int -PID_SECURITY: int -PID_BEHAVIOR: int -PID_ILLEGAL: int -PID_MIN_READONLY: int -PID_MAX_READONLY: int -PIDDI_THUMBNAIL: int -PIDSI_TITLE: int -PIDSI_SUBJECT: int -PIDSI_AUTHOR: int -PIDSI_KEYWORDS: int -PIDSI_COMMENTS: int -PIDSI_TEMPLATE: int -PIDSI_LASTAUTHOR: int -PIDSI_REVNUMBER: int -PIDSI_EDITTIME: int -PIDSI_LASTPRINTED: int -PIDSI_CREATE_DTM: int -PIDSI_LASTSAVE_DTM: int -PIDSI_PAGECOUNT: int -PIDSI_WORDCOUNT: int -PIDSI_CHARCOUNT: int -PIDSI_THUMBNAIL: int -PIDSI_APPNAME: int -PIDSI_DOC_SECURITY: int -PIDDSI_CATEGORY: int -PIDDSI_PRESFORMAT: int -PIDDSI_BYTECOUNT: int -PIDDSI_LINECOUNT: int -PIDDSI_PARCOUNT: int -PIDDSI_SLIDECOUNT: int -PIDDSI_NOTECOUNT: int -PIDDSI_HIDDENCOUNT: int -PIDDSI_MMCLIPCOUNT: int -PIDDSI_SCALE: int -PIDDSI_HEADINGPAIR: int -PIDDSI_DOCPARTS: int -PIDDSI_MANAGER: int -PIDDSI_COMPANY: int -PIDDSI_LINKSDIRTY: int -PIDMSI_EDITOR: int -PIDMSI_SUPPLIER: int -PIDMSI_SOURCE: int -PIDMSI_SEQUENCE_NO: int -PIDMSI_PROJECT: int -PIDMSI_STATUS: int -PIDMSI_OWNER: int -PIDMSI_RATING: int -PIDMSI_PRODUCTION: int -PIDMSI_COPYRIGHT: int -PROPSETFLAG_DEFAULT: int -PROPSETFLAG_NONSIMPLE: int -PROPSETFLAG_ANSI: int -PROPSETFLAG_UNBUFFERED: int -PROPSETFLAG_CASE_SENSITIVE: int -STGMOVE_MOVE: int -STGMOVE_COPY: int -STGMOVE_SHALLOWCOPY: int +from typing import Final + +STGC_DEFAULT: Final = 0 +STGC_OVERWRITE: Final = 1 +STGC_ONLYIFCURRENT: Final = 2 +STGC_DANGEROUSLYCOMMITMERELYTODISKCACHE: Final = 4 +STGC_CONSOLIDATE: Final = 8 +STGTY_STORAGE: Final = 1 +STGTY_STREAM: Final = 2 +STGTY_LOCKBYTES: Final = 3 +STGTY_PROPERTY: Final = 4 +STREAM_SEEK_SET: Final = 0 +STREAM_SEEK_CUR: Final = 1 +STREAM_SEEK_END: Final = 2 +LOCK_WRITE: Final = 1 +LOCK_EXCLUSIVE: Final = 2 +LOCK_ONLYONCE: Final = 4 +CWCSTORAGENAME: Final = 32 +STGM_DIRECT: Final = 0x00000000 +STGM_TRANSACTED: Final = 0x00010000 +STGM_SIMPLE: Final = 0x08000000 +STGM_READ: Final = 0x00000000 +STGM_WRITE: Final = 0x00000001 +STGM_READWRITE: Final = 0x00000002 +STGM_SHARE_DENY_NONE: Final = 0x00000040 +STGM_SHARE_DENY_READ: Final = 0x00000030 +STGM_SHARE_DENY_WRITE: Final = 0x00000020 +STGM_SHARE_EXCLUSIVE: Final = 0x00000010 +STGM_PRIORITY: Final = 0x00040000 +STGM_DELETEONRELEASE: Final = 0x04000000 +STGM_NOSCRATCH: Final = 0x00100000 +STGM_CREATE: Final = 0x00001000 +STGM_CONVERT: Final = 0x00020000 +STGM_FAILIFTHERE: Final = 0x00000000 +STGM_NOSNAPSHOT: Final = 0x00200000 +ASYNC_MODE_COMPATIBILITY: Final = 0x00000001 +ASYNC_MODE_DEFAULT: Final = 0x00000000 +STGTY_REPEAT: Final = 0x00000100 +STG_TOEND: Final = 0xFFFFFFFF +STG_LAYOUT_SEQUENTIAL: Final = 0x00000000 +STG_LAYOUT_INTERLEAVED: Final = 0x00000001 +COM_RIGHTS_EXECUTE: Final = 1 +COM_RIGHTS_EXECUTE_LOCAL: Final = 2 +COM_RIGHTS_EXECUTE_REMOTE: Final = 4 +COM_RIGHTS_ACTIVATE_LOCAL: Final = 8 +COM_RIGHTS_ACTIVATE_REMOTE: Final = 16 +STGFMT_DOCUMENT: Final = 0 +STGFMT_STORAGE: Final = 0 +STGFMT_NATIVE: Final = 1 +STGFMT_FILE: Final = 3 +STGFMT_ANY: Final = 4 +STGFMT_DOCFILE: Final = 5 +PID_DICTIONARY: Final = 0 +PID_CODEPAGE: Final = 1 +PID_FIRST_USABLE: Final = 2 +PID_FIRST_NAME_DEFAULT: Final = 4095 +PID_LOCALE: Final = -2147483648 +PID_MODIFY_TIME: Final = -2147483647 +PID_SECURITY: Final = -2147483646 +PID_BEHAVIOR: Final = -2147483645 +PID_ILLEGAL: Final = -1 +PID_MIN_READONLY: Final = -2147483648 +PID_MAX_READONLY: Final = -1073741825 +PIDDI_THUMBNAIL: Final = 0x00000002 +PIDSI_TITLE: Final = 2 +PIDSI_SUBJECT: Final = 3 +PIDSI_AUTHOR: Final = 4 +PIDSI_KEYWORDS: Final = 5 +PIDSI_COMMENTS: Final = 6 +PIDSI_TEMPLATE: Final = 7 +PIDSI_LASTAUTHOR: Final = 8 +PIDSI_REVNUMBER: Final = 9 +PIDSI_EDITTIME: Final = 10 +PIDSI_LASTPRINTED: Final = 11 +PIDSI_CREATE_DTM: Final = 12 +PIDSI_LASTSAVE_DTM: Final = 13 +PIDSI_PAGECOUNT: Final = 14 +PIDSI_WORDCOUNT: Final = 15 +PIDSI_CHARCOUNT: Final = 16 +PIDSI_THUMBNAIL: Final = 17 +PIDSI_APPNAME: Final = 18 +PIDSI_DOC_SECURITY: Final = 19 +PIDDSI_CATEGORY: Final = 2 +PIDDSI_PRESFORMAT: Final = 3 +PIDDSI_BYTECOUNT: Final = 4 +PIDDSI_LINECOUNT: Final = 5 +PIDDSI_PARCOUNT: Final = 6 +PIDDSI_SLIDECOUNT: Final = 7 +PIDDSI_NOTECOUNT: Final = 8 +PIDDSI_HIDDENCOUNT: Final = 9 +PIDDSI_MMCLIPCOUNT: Final = 10 +PIDDSI_SCALE: Final = 11 +PIDDSI_HEADINGPAIR: Final = 12 +PIDDSI_DOCPARTS: Final = 13 +PIDDSI_MANAGER: Final = 14 +PIDDSI_COMPANY: Final = 15 +PIDDSI_LINKSDIRTY: Final = 16 +PIDMSI_EDITOR: Final = 2 +PIDMSI_SUPPLIER: Final = 3 +PIDMSI_SOURCE: Final = 4 +PIDMSI_SEQUENCE_NO: Final = 5 +PIDMSI_PROJECT: Final = 6 +PIDMSI_STATUS: Final = 7 +PIDMSI_OWNER: Final = 8 +PIDMSI_RATING: Final = 9 +PIDMSI_PRODUCTION: Final = 10 +PIDMSI_COPYRIGHT: Final = 11 +PROPSETFLAG_DEFAULT: Final = 0 +PROPSETFLAG_NONSIMPLE: Final = 1 +PROPSETFLAG_ANSI: Final = 2 +PROPSETFLAG_UNBUFFERED: Final = 4 +PROPSETFLAG_CASE_SENSITIVE: Final = 8 +STGMOVE_MOVE: Final = 0 +STGMOVE_COPY: Final = 1 +STGMOVE_SHALLOWCOPY: Final = 2 diff --git a/stubs/pywin32/win32com/universal.pyi b/stubs/pywin32/win32com/universal.pyi index fe0e626fc0d3..01ed84f25c2f 100644 --- a/stubs/pywin32/win32com/universal.pyi +++ b/stubs/pywin32/win32com/universal.pyi @@ -1,5 +1,6 @@ from _typeshed import Incomplete -from collections.abc import Callable +from collections.abc import Callable, Iterable +from typing import Literal, SupportsIndex from typing_extensions import TypeAlias import pythoncom @@ -12,25 +13,34 @@ _WriteFromOutTupleType: TypeAlias = Callable[ [tuple[Incomplete, ...] | None, tuple[Incomplete, ...] | None, int], Incomplete | None ] -def RegisterInterfaces(typelibGUID, lcid, major, minor, interface_names: Incomplete | None = ...): ... +def RegisterInterfaces( + typelibGUID, lcid, major, minor, interface_names: Iterable[str] | None = None +) -> list[tuple[Incomplete, Incomplete, Incomplete]]: ... class Arg: name: Incomplete + vt: Incomplete + inOut: Incomplete + default: Incomplete + clsid: Incomplete + arg_info: Incomplete size: Incomplete offset: int - def __init__(self, arg_info, name: Incomplete | None = ...) -> None: ... + def __init__(self, arg_info, name=None) -> None: ... class Method: dispid: Incomplete invkind: Incomplete name: Incomplete - args: Incomplete + args: list[Arg] cbArgs: Incomplete - def __init__(self, method_info, isEventSink: int = ...) -> None: ... + def __init__(self, method_info, isEventSink: bool | Literal[0, 1] = 1) -> None: ... class Definition: def __init__(self, iid, is_dispatch, method_defs) -> None: ... def iid(self): ... - def vtbl_argsizes(self): ... - def vtbl_argcounts(self): ... - def dispatch(self, ob, index, argPtr, ReadFromInTuple=..., WriteFromOutTuple: _WriteFromOutTupleType = ...): ... + def vtbl_argsizes(self) -> list[Incomplete]: ... + def vtbl_argcounts(self) -> list[int]: ... + def dispatch( + self, ob, index: SupportsIndex, argPtr, ReadFromInTuple=..., WriteFromOutTuple: _WriteFromOutTupleType = ... + ): ... diff --git a/stubs/pywin32/win32com/util.pyi b/stubs/pywin32/win32com/util.pyi index 6c896a88618f..4b23324c4289 100644 --- a/stubs/pywin32/win32com/util.pyi +++ b/stubs/pywin32/win32com/util.pyi @@ -1 +1 @@ -def IIDToInterfaceName(iid): ... +def IIDToInterfaceName(iid) -> str: ... From 9cbb0e6ec4a3c01510d9aa0e8d0a07b2110642d5 Mon Sep 17 00:00:00 2001 From: donbarbos Date: Thu, 19 Mar 2026 23:12:00 +0400 Subject: [PATCH 02/12] fix errors --- stubs/pywin32/@tests/stubtest_allowlist_win32.txt | 1 - stubs/pywin32/win32com/universal.pyi | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/stubs/pywin32/@tests/stubtest_allowlist_win32.txt b/stubs/pywin32/@tests/stubtest_allowlist_win32.txt index 37ea55f8e223..b20e7455aa29 100644 --- a/stubs/pywin32/@tests/stubtest_allowlist_win32.txt +++ b/stubs/pywin32/@tests/stubtest_allowlist_win32.txt @@ -8,7 +8,6 @@ win32com.client.combrowse win32com.client.tlbrowse # Utilities to generate python bindings -win32com.client.build.* win32com.client.CLSIDToClass win32com.client.connect # "dynamic.CDipatch" is necessary for mypy to not throw AssertionError diff --git a/stubs/pywin32/win32com/universal.pyi b/stubs/pywin32/win32com/universal.pyi index 01ed84f25c2f..8c3ba6e0e467 100644 --- a/stubs/pywin32/win32com/universal.pyi +++ b/stubs/pywin32/win32com/universal.pyi @@ -34,7 +34,7 @@ class Method: name: Incomplete args: list[Arg] cbArgs: Incomplete - def __init__(self, method_info, isEventSink: bool | Literal[0, 1] = 1) -> None: ... + def __init__(self, method_info, isEventSink: bool | Literal[0, 1] = 0) -> None: ... class Definition: def __init__(self, iid, is_dispatch, method_defs) -> None: ... From fc1af2021aaad80056bdaa291c0d0d01481e25ec Mon Sep 17 00:00:00 2001 From: donbarbos Date: Sun, 22 Mar 2026 00:50:09 +0400 Subject: [PATCH 03/12] add suggestions and try to remove dynamic entry --- stubs/pywin32/@tests/stubtest_allowlist_win32.txt | 1 - stubs/pywin32/win32com/server/policy.pyi | 7 ++++--- stubs/pywin32/win32com/server/util.pyi | 3 ++- stubs/pywin32/win32com/universal.pyi | 1 - 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/stubs/pywin32/@tests/stubtest_allowlist_win32.txt b/stubs/pywin32/@tests/stubtest_allowlist_win32.txt index b20e7455aa29..4f83d67cf72a 100644 --- a/stubs/pywin32/@tests/stubtest_allowlist_win32.txt +++ b/stubs/pywin32/@tests/stubtest_allowlist_win32.txt @@ -11,7 +11,6 @@ win32com.client.tlbrowse win32com.client.CLSIDToClass win32com.client.connect # "dynamic.CDipatch" is necessary for mypy to not throw AssertionError -win32com.client.dynamic.* win32com.client.gencache.* win32com.client.genpy win32com.client.makepy diff --git a/stubs/pywin32/win32com/server/policy.pyi b/stubs/pywin32/win32com/server/policy.pyi index 16a28eec5792..d80030b680fa 100644 --- a/stubs/pywin32/win32com/server/policy.pyi +++ b/stubs/pywin32/win32com/server/policy.pyi @@ -1,9 +1,10 @@ from _typeshed import Incomplete from abc import ABC, abstractmethod -from typing import Final +from typing import Any, Final import _win32typing +__author__: Final[str] S_OK: Final = 0 IDispatchType: Incomplete IUnknownType: Incomplete @@ -32,8 +33,8 @@ class DynamicPolicy(BasicWrapPolicy): DefaultPolicy = DesignatedWrapPolicy -def resolve_func(spec: str): ... -def call_func(spec: str, *args): ... +def resolve_func(spec: str) -> Any: ... +def call_func(spec: str, *args) -> Any: ... DISPATCH_METHOD: int DISPATCH_PROPERTYGET: int diff --git a/stubs/pywin32/win32com/server/util.pyi b/stubs/pywin32/win32com/server/util.pyi index 526057dbfe60..fda3f8187ea8 100644 --- a/stubs/pywin32/win32com/server/util.pyi +++ b/stubs/pywin32/win32com/server/util.pyi @@ -1,4 +1,5 @@ from _typeshed import Incomplete +from collections.abc import Iterable from typing import Literal import _win32typing @@ -17,7 +18,7 @@ class ListEnumerator: def Clone(self): ... class ListEnumeratorGateway(ListEnumerator): - def Next(self, count: int) -> map[Incomplete]: ... + def Next(self, count: int) -> Iterable[Incomplete]: ... def NewEnum( seq, diff --git a/stubs/pywin32/win32com/universal.pyi b/stubs/pywin32/win32com/universal.pyi index 8c3ba6e0e467..2e8058f9bcb2 100644 --- a/stubs/pywin32/win32com/universal.pyi +++ b/stubs/pywin32/win32com/universal.pyi @@ -23,7 +23,6 @@ class Arg: inOut: Incomplete default: Incomplete clsid: Incomplete - arg_info: Incomplete size: Incomplete offset: int def __init__(self, arg_info, name=None) -> None: ... From 300503e5e38c98ec3f8b9f86253f48d952dafdd5 Mon Sep 17 00:00:00 2001 From: donbarbos Date: Sun, 22 Mar 2026 00:58:52 +0400 Subject: [PATCH 04/12] ignore error --- stubs/pywin32/@tests/stubtest_allowlist_win32.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/stubs/pywin32/@tests/stubtest_allowlist_win32.txt b/stubs/pywin32/@tests/stubtest_allowlist_win32.txt index 4f83d67cf72a..041116252a82 100644 --- a/stubs/pywin32/@tests/stubtest_allowlist_win32.txt +++ b/stubs/pywin32/@tests/stubtest_allowlist_win32.txt @@ -10,7 +10,8 @@ win32com.client.tlbrowse # Utilities to generate python bindings win32com.client.CLSIDToClass win32com.client.connect -# "dynamic.CDipatch" is necessary for mypy to not throw AssertionError +# Error: _GoodDispatchTypes is not a subclass of tuple +win32com.client.dynamic._GoodDispatchTypes win32com.client.gencache.* win32com.client.genpy win32com.client.makepy From 8e38cd6f76e2788dfcfa39fc8759a4160396b8f5 Mon Sep 17 00:00:00 2001 From: donbarbos Date: Sun, 22 Mar 2026 01:10:03 +0400 Subject: [PATCH 05/12] pretend _GoodDispatchTypes is Union --- stubs/pywin32/win32com/client/dynamic.pyi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stubs/pywin32/win32com/client/dynamic.pyi b/stubs/pywin32/win32com/client/dynamic.pyi index e0a8de476563..963f8232cb2f 100644 --- a/stubs/pywin32/win32com/client/dynamic.pyi +++ b/stubs/pywin32/win32com/client/dynamic.pyi @@ -31,7 +31,7 @@ def debug_attr_print(*args: object) -> None: ... PyIDispatchType = _win32typing.PyIDispatch PyIUnknownType = _win32typing.PyIUnknown -_GoodDispatchTypes: TypeAlias = tuple[type[str], type[IIDType]] +_GoodDispatchTypes: TypeAlias = str | IIDType @overload def Dispatch( From d21a4f0ffb5b0bb57d741713aaf29eaf27faa05e Mon Sep 17 00:00:00 2001 From: donbarbos Date: Sun, 22 Mar 2026 01:12:18 +0400 Subject: [PATCH 06/12] forgot to remove allowlist entry to see result of pretending --- stubs/pywin32/@tests/stubtest_allowlist_win32.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/stubs/pywin32/@tests/stubtest_allowlist_win32.txt b/stubs/pywin32/@tests/stubtest_allowlist_win32.txt index 041116252a82..f704cfa3e773 100644 --- a/stubs/pywin32/@tests/stubtest_allowlist_win32.txt +++ b/stubs/pywin32/@tests/stubtest_allowlist_win32.txt @@ -10,8 +10,6 @@ win32com.client.tlbrowse # Utilities to generate python bindings win32com.client.CLSIDToClass win32com.client.connect -# Error: _GoodDispatchTypes is not a subclass of tuple -win32com.client.dynamic._GoodDispatchTypes win32com.client.gencache.* win32com.client.genpy win32com.client.makepy From c0f4c671a73a9a9d698381bdf865d72f87ce8cba Mon Sep 17 00:00:00 2001 From: donbarbos Date: Sun, 22 Mar 2026 01:24:12 +0400 Subject: [PATCH 07/12] update again --- stubs/pywin32/@tests/stubtest_allowlist_win32.txt | 2 ++ stubs/pywin32/win32com/client/dynamic.pyi | 2 +- stubs/pywin32/win32com/server/policy.pyi | 5 ++++- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/stubs/pywin32/@tests/stubtest_allowlist_win32.txt b/stubs/pywin32/@tests/stubtest_allowlist_win32.txt index f704cfa3e773..544ad865dcbb 100644 --- a/stubs/pywin32/@tests/stubtest_allowlist_win32.txt +++ b/stubs/pywin32/@tests/stubtest_allowlist_win32.txt @@ -10,6 +10,8 @@ win32com.client.tlbrowse # Utilities to generate python bindings win32com.client.CLSIDToClass win32com.client.connect +# Error: _GoodDispatchTypes is not a Union or subclass of tuple +win32com.client.dynamic._GoodDispatchTypes win32com.client.gencache.* win32com.client.genpy win32com.client.makepy diff --git a/stubs/pywin32/win32com/client/dynamic.pyi b/stubs/pywin32/win32com/client/dynamic.pyi index 963f8232cb2f..e0a8de476563 100644 --- a/stubs/pywin32/win32com/client/dynamic.pyi +++ b/stubs/pywin32/win32com/client/dynamic.pyi @@ -31,7 +31,7 @@ def debug_attr_print(*args: object) -> None: ... PyIDispatchType = _win32typing.PyIDispatch PyIUnknownType = _win32typing.PyIUnknown -_GoodDispatchTypes: TypeAlias = str | IIDType +_GoodDispatchTypes: TypeAlias = tuple[type[str], type[IIDType]] @overload def Dispatch( diff --git a/stubs/pywin32/win32com/server/policy.pyi b/stubs/pywin32/win32com/server/policy.pyi index d80030b680fa..a14cfe8d8c03 100644 --- a/stubs/pywin32/win32com/server/policy.pyi +++ b/stubs/pywin32/win32com/server/policy.pyi @@ -33,8 +33,11 @@ class DynamicPolicy(BasicWrapPolicy): DefaultPolicy = DesignatedWrapPolicy +# Imports an arbitrary object by it's fully-qualified name. def resolve_func(spec: str) -> Any: ... -def call_func(spec: str, *args) -> Any: ... + +# Imports and calls an arbitrary callable by it's fully-qualified name. +def call_func(spec: str, *args: Any) -> Any: ... DISPATCH_METHOD: int DISPATCH_PROPERTYGET: int From 34147bafc7782fa4c010054a0a7aec84f1d6a8aa Mon Sep 17 00:00:00 2001 From: donbarbos Date: Sun, 22 Mar 2026 01:48:46 +0400 Subject: [PATCH 08/12] Annotate gencache --- .../@tests/stubtest_allowlist_win32.txt | 1 - stubs/pywin32/win32com/client/gencache.pyi | 54 ++++++++++++++++++- 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/stubs/pywin32/@tests/stubtest_allowlist_win32.txt b/stubs/pywin32/@tests/stubtest_allowlist_win32.txt index 544ad865dcbb..5a68613fb13c 100644 --- a/stubs/pywin32/@tests/stubtest_allowlist_win32.txt +++ b/stubs/pywin32/@tests/stubtest_allowlist_win32.txt @@ -12,7 +12,6 @@ win32com.client.CLSIDToClass win32com.client.connect # Error: _GoodDispatchTypes is not a Union or subclass of tuple win32com.client.dynamic._GoodDispatchTypes -win32com.client.gencache.* win32com.client.genpy win32com.client.makepy win32com.client.selecttlb diff --git a/stubs/pywin32/win32com/client/gencache.pyi b/stubs/pywin32/win32com/client/gencache.pyi index d25ec58c0f59..6fb636841fb3 100644 --- a/stubs/pywin32/win32com/client/gencache.pyi +++ b/stubs/pywin32/win32com/client/gencache.pyi @@ -1,8 +1,60 @@ -from typing import Literal +from _typeshed import Incomplete, Unused +from collections.abc import Generator +from contextlib import contextmanager +from types import ModuleType +from typing import Literal, NoReturn from win32com.client import dynamic +bForDemandDefault: int +clsidToTypelib: dict[str, tuple[str, int, int, int]] +versionRedirectMap: dict[tuple[str, int, int, int], ModuleType | None] +is_readonly: bool +is_zip: bool +demandGeneratedTypeLibraries: dict[tuple[str, int, int, int], Incomplete] +pickleVersion: int + +@contextmanager +def ModuleMutex(module_name: str) -> Generator[None]: ... +def GetGeneratedFileName(clsid, lcid, major, minor) -> str: ... +def SplitGeneratedFileName(fname: str) -> tuple[str, ...]: ... +def GetGeneratePath() -> str: ... +def GetClassForProgID(progid: str) -> type | None: ... +def GetClassForCLSID(clsid) -> type | None: ... +def GetModuleForProgID(progid: str) -> ModuleType | None: ... +def GetModuleForCLSID(clsid) -> ModuleType | None: ... +def GetModuleForTypelib(typelibCLSID, lcid, major, minor) -> ModuleType: ... +def MakeModuleForTypelib( + typelibCLSID, + lcid, + major, + minor, + progressInstance=None, + bForDemand: bool | Literal[0, 1] = ..., + bBuildHidden: bool | Literal[0, 1] = 1, +) -> ModuleType: ... +def MakeModuleForTypelibInterface( + typelib_ob, progressInstance=None, bForDemand: Unused = ..., bBuildHidden: bool | Literal[0, 1] = 1 +) -> ModuleType | None: ... +def EnsureModuleForTypelibInterface( + typelib_ob, progressInstance=None, bForDemand: bool | Literal[0, 1] = ..., bBuildHidden: bool | Literal[0, 1] = 1 +) -> ModuleType | None: ... +def ForgetAboutTypelibInterface(typelib_ob) -> None: ... +def EnsureModule( + typelibCLSID, + lcid, + major, + minor, + progressInstance=None, + bValidateFile: bool | Literal[0, 1] = ..., + bForDemand: bool | Literal[0, 1] = ..., + bBuildHidden: bool | Literal[0, 1] = 1, +) -> ModuleType | None: ... def EnsureDispatch( prog_id: str | dynamic.PyIDispatchType | dynamic._GoodDispatchTypes | dynamic.PyIUnknownType, bForDemand: bool | Literal[0, 1] = 1, ) -> dynamic.CDispatch: ... +def AddModuleToCache(typelibclsid, lcid, major, minor, verbose: Unused = 1, bFlushNow: bool | Literal[0, 1] = ...) -> None: ... +def GetGeneratedInfos() -> list[tuple[Incomplete, Incomplete, Incomplete, Incomplete]]: ... +def Rebuild(verbose: bool | Literal[0, 1] = 1) -> None: ... +def usage() -> NoReturn: ... From 473022727ddfe5ec26f01318060169e6c27c58cd Mon Sep 17 00:00:00 2001 From: donbarbos Date: Sun, 22 Mar 2026 01:51:25 +0400 Subject: [PATCH 09/12] Use Union for _GoodDispatchTypes --- stubs/pywin32/win32com/client/dynamic.pyi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stubs/pywin32/win32com/client/dynamic.pyi b/stubs/pywin32/win32com/client/dynamic.pyi index e0a8de476563..963f8232cb2f 100644 --- a/stubs/pywin32/win32com/client/dynamic.pyi +++ b/stubs/pywin32/win32com/client/dynamic.pyi @@ -31,7 +31,7 @@ def debug_attr_print(*args: object) -> None: ... PyIDispatchType = _win32typing.PyIDispatch PyIUnknownType = _win32typing.PyIUnknown -_GoodDispatchTypes: TypeAlias = tuple[type[str], type[IIDType]] +_GoodDispatchTypes: TypeAlias = str | IIDType @overload def Dispatch( From 0943e0fb161c8ca6a6720a9fd716340229ef7e70 Mon Sep 17 00:00:00 2001 From: donbarbos Date: Sun, 22 Mar 2026 01:53:09 +0400 Subject: [PATCH 10/12] add missing function --- stubs/pywin32/win32com/client/gencache.pyi | 3 +++ 1 file changed, 3 insertions(+) diff --git a/stubs/pywin32/win32com/client/gencache.pyi b/stubs/pywin32/win32com/client/gencache.pyi index 6fb636841fb3..19385e10c999 100644 --- a/stubs/pywin32/win32com/client/gencache.pyi +++ b/stubs/pywin32/win32com/client/gencache.pyi @@ -12,6 +12,9 @@ versionRedirectMap: dict[tuple[str, int, int, int], ModuleType | None] is_readonly: bool is_zip: bool demandGeneratedTypeLibraries: dict[tuple[str, int, int, int], Incomplete] + +def __init__() -> None: ... + pickleVersion: int @contextmanager From e60f51817c21db129f74a97e37eca527a75b0cf2 Mon Sep 17 00:00:00 2001 From: donbarbos Date: Sun, 22 Mar 2026 09:18:37 +0400 Subject: [PATCH 11/12] Remove _GoodDispatchTypes TypeAlias --- stubs/pywin32/win32com/client/__init__.pyi | 3 ++- stubs/pywin32/win32com/client/dynamic.pyi | 9 +++------ stubs/pywin32/win32com/client/gencache.pyi | 6 +++--- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/stubs/pywin32/win32com/client/__init__.pyi b/stubs/pywin32/win32com/client/__init__.pyi index 1afbe6dda5f6..44f2aa61cd96 100644 --- a/stubs/pywin32/win32com/client/__init__.pyi +++ b/stubs/pywin32/win32com/client/__init__.pyi @@ -5,6 +5,7 @@ from typing_extensions import TypeAlias import _win32typing from pythoncom import com_record +from win32.lib.pywintypes import IIDType from win32com.client import dynamic _Stringifiable: TypeAlias = object @@ -13,7 +14,7 @@ def GetObject(Pathname: str | None = None, Class=None, clsctx=None) -> CDispatch def GetActiveObject(Class: str, clsctx=...): ... def Moniker(Pathname: str, clsctx=...): ... def Dispatch( - dispatch: str | dynamic.PyIDispatchType | dynamic._GoodDispatchTypes | dynamic.PyIUnknownType, + dispatch: str | dynamic.PyIDispatchType | IIDType | dynamic.PyIUnknownType, userName: str | None = None, resultCLSID: _Stringifiable | None = None, typeinfo: _win32typing.PyITypeInfo | None = None, diff --git a/stubs/pywin32/win32com/client/dynamic.pyi b/stubs/pywin32/win32com/client/dynamic.pyi index 963f8232cb2f..7d910d2b40fa 100644 --- a/stubs/pywin32/win32com/client/dynamic.pyi +++ b/stubs/pywin32/win32com/client/dynamic.pyi @@ -1,6 +1,5 @@ from _typeshed import Incomplete from typing import Any, Final, Literal, Protocol, TypeVar, overload, type_check_only -from typing_extensions import TypeAlias import _win32typing from win32.lib.pywintypes import IIDType @@ -13,7 +12,7 @@ _T = TypeVar("_T") class _DispatchCreateClass(Protocol[_T_co]): @staticmethod def __call__( - IDispatch: str | PyIDispatchType | _GoodDispatchTypes | PyIUnknownType, + IDispatch: str | PyIDispatchType | IIDType | PyIUnknownType, olerepr: build.DispatchItem | build.LazyDispatchItem, userName: str | None = None, lazydata=None, @@ -31,11 +30,9 @@ def debug_attr_print(*args: object) -> None: ... PyIDispatchType = _win32typing.PyIDispatch PyIUnknownType = _win32typing.PyIUnknown -_GoodDispatchTypes: TypeAlias = str | IIDType - @overload def Dispatch( - IDispatch: str | PyIDispatchType | _GoodDispatchTypes | PyIUnknownType, + IDispatch: str | PyIDispatchType | IIDType | PyIUnknownType, userName: str | None, createClass: _DispatchCreateClass[_T], typeinfo: _win32typing.PyITypeInfo | None = None, @@ -43,7 +40,7 @@ def Dispatch( ) -> _T: ... @overload def Dispatch( - IDispatch: str | PyIDispatchType | _GoodDispatchTypes | PyIUnknownType, + IDispatch: str | PyIDispatchType | IIDType | PyIUnknownType, userName: str | None = None, createClass: None = None, typeinfo: _win32typing.PyITypeInfo | None = None, diff --git a/stubs/pywin32/win32com/client/gencache.pyi b/stubs/pywin32/win32com/client/gencache.pyi index 19385e10c999..e12756df8887 100644 --- a/stubs/pywin32/win32com/client/gencache.pyi +++ b/stubs/pywin32/win32com/client/gencache.pyi @@ -4,6 +4,7 @@ from contextlib import contextmanager from types import ModuleType from typing import Literal, NoReturn +from win32.lib.pywintypes import IIDType from win32com.client import dynamic bForDemandDefault: int @@ -37,7 +38,7 @@ def MakeModuleForTypelib( bBuildHidden: bool | Literal[0, 1] = 1, ) -> ModuleType: ... def MakeModuleForTypelibInterface( - typelib_ob, progressInstance=None, bForDemand: Unused = ..., bBuildHidden: bool | Literal[0, 1] = 1 + typelib_ob, progressInstance=None, bForDemand: bool | Literal[0, 1] = ..., bBuildHidden: bool | Literal[0, 1] = 1 ) -> ModuleType | None: ... def EnsureModuleForTypelibInterface( typelib_ob, progressInstance=None, bForDemand: bool | Literal[0, 1] = ..., bBuildHidden: bool | Literal[0, 1] = 1 @@ -54,8 +55,7 @@ def EnsureModule( bBuildHidden: bool | Literal[0, 1] = 1, ) -> ModuleType | None: ... def EnsureDispatch( - prog_id: str | dynamic.PyIDispatchType | dynamic._GoodDispatchTypes | dynamic.PyIUnknownType, - bForDemand: bool | Literal[0, 1] = 1, + prog_id: str | dynamic.PyIDispatchType | IIDType | dynamic.PyIUnknownType, bForDemand: bool | Literal[0, 1] = 1 ) -> dynamic.CDispatch: ... def AddModuleToCache(typelibclsid, lcid, major, minor, verbose: Unused = 1, bFlushNow: bool | Literal[0, 1] = ...) -> None: ... def GetGeneratedInfos() -> list[tuple[Incomplete, Incomplete, Incomplete, Incomplete]]: ... From e5592a9d44f06d8712ecb19d99cca0b463b7ba80 Mon Sep 17 00:00:00 2001 From: donbarbos Date: Sun, 22 Mar 2026 09:20:45 +0400 Subject: [PATCH 12/12] update allowlist --- stubs/pywin32/@tests/stubtest_allowlist_win32.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/stubs/pywin32/@tests/stubtest_allowlist_win32.txt b/stubs/pywin32/@tests/stubtest_allowlist_win32.txt index 5a68613fb13c..434db4abcb5a 100644 --- a/stubs/pywin32/@tests/stubtest_allowlist_win32.txt +++ b/stubs/pywin32/@tests/stubtest_allowlist_win32.txt @@ -10,8 +10,6 @@ win32com.client.tlbrowse # Utilities to generate python bindings win32com.client.CLSIDToClass win32com.client.connect -# Error: _GoodDispatchTypes is not a Union or subclass of tuple -win32com.client.dynamic._GoodDispatchTypes win32com.client.genpy win32com.client.makepy win32com.client.selecttlb