From d9759ce5ade4fb5562c87c6b30fdd18e2a5396ca Mon Sep 17 00:00:00 2001 From: Brian Schubert Date: Sun, 14 Sep 2025 07:31:02 -0400 Subject: [PATCH 1/5] Add `@disjoint_base` decorator to the third-party stubs --- stubs/PyYAML/yaml/_yaml.pyi | 5 ++++- stubs/cffi/_cffi_backend.pyi | 3 ++- stubs/gdb/gdb/__init__.pyi | 10 ++++++++- stubs/gdb/gdb/disassembler.pyi | 2 ++ stubs/gevent/gevent/_greenlet_primitives.pyi | 2 ++ stubs/gevent/gevent/_hub_primitives.pyi | 3 ++- stubs/gevent/gevent/_imap.pyi | 4 +++- stubs/gevent/gevent/greenlet.pyi | 3 ++- stubs/gevent/gevent/libev/corecext.pyi | 4 ++-- stubs/gevent/gevent/resolver/cares.pyi | 4 +++- stubs/greenlet/greenlet/_greenlet.pyi | 3 ++- stubs/hdbcli/hdbcli/dbapi.pyi | 5 ++++- stubs/hdbcli/hdbcli/resultrow.pyi | 2 ++ stubs/lupa/lupa/lua51.pyi | 4 +++- stubs/lupa/lupa/lua52.pyi | 4 +++- stubs/lupa/lupa/lua53.pyi | 4 +++- stubs/lupa/lupa/lua54.pyi | 4 +++- stubs/lupa/lupa/luajit20.pyi | 3 +++ stubs/lupa/lupa/luajit21.pyi | 3 +++ stubs/mysqlclient/MySQLdb/_mysql.pyi | 3 +++ stubs/psycopg2/psycopg2/_psycopg.pyi | 23 +++++++++++++++++++- stubs/pywin32/_win32typing.pyi | 17 ++++++++++++++- stubs/pywin32/pythoncom.pyi | 3 ++- stubs/pywin32/win32/lib/pywintypes.pyi | 3 ++- stubs/shapely/shapely/lib.pyi | 3 ++- 25 files changed, 104 insertions(+), 20 deletions(-) diff --git a/stubs/PyYAML/yaml/_yaml.pyi b/stubs/PyYAML/yaml/_yaml.pyi index 33dfb5969a4a..2901bc271310 100644 --- a/stubs/PyYAML/yaml/_yaml.pyi +++ b/stubs/PyYAML/yaml/_yaml.pyi @@ -1,6 +1,7 @@ from _typeshed import Incomplete, SupportsRead from collections.abc import Mapping, Sequence from typing import IO, Any +from typing_extensions import disjoint_base from .events import Event from .nodes import Node @@ -8,7 +9,7 @@ from .tokens import Token def get_version_string() -> str: ... def get_version() -> tuple[int, int, int]: ... - +@disjoint_base class Mark: name: Any index: int @@ -19,6 +20,7 @@ class Mark: def __init__(self, name, index: int, line: int, column: int, buffer, pointer) -> None: ... def get_snippet(self): ... +@disjoint_base class CParser: def __init__(self, stream: str | bytes | SupportsRead[str | bytes]) -> None: ... def dispose(self) -> None: ... @@ -34,6 +36,7 @@ class CParser: def raw_parse(self) -> int: ... def raw_scan(self) -> int: ... +@disjoint_base class CEmitter: def __init__( self, diff --git a/stubs/cffi/_cffi_backend.pyi b/stubs/cffi/_cffi_backend.pyi index 7362010e2049..f2856bb90213 100644 --- a/stubs/cffi/_cffi_backend.pyi +++ b/stubs/cffi/_cffi_backend.pyi @@ -3,7 +3,7 @@ import types from _typeshed import Incomplete, ReadableBuffer, WriteableBuffer from collections.abc import Callable, Hashable from typing import Any, ClassVar, Literal, Protocol, SupportsIndex, TypeVar, final, overload, type_check_only -from typing_extensions import Self, TypeAlias +from typing_extensions import Self, TypeAlias, disjoint_base _T = TypeVar("_T") @@ -111,6 +111,7 @@ class buffer: _tmp_CType = CType _tmp_buffer = buffer +@disjoint_base class FFI: CData: TypeAlias = _CDataBase CType: TypeAlias = _tmp_CType diff --git a/stubs/gdb/gdb/__init__.pyi b/stubs/gdb/gdb/__init__.pyi index 4f4a67b28427..0a909b225bb0 100644 --- a/stubs/gdb/gdb/__init__.pyi +++ b/stubs/gdb/gdb/__init__.pyi @@ -7,7 +7,7 @@ import threading from collections.abc import Callable, Iterator, Mapping, Sequence from contextlib import AbstractContextManager from typing import Any, Final, Generic, Literal, Protocol, TypedDict, TypeVar, final, overload, type_check_only -from typing_extensions import TypeAlias, deprecated +from typing_extensions import TypeAlias, deprecated, disjoint_base import gdb.FrameDecorator import gdb.types @@ -74,6 +74,7 @@ class GdbError(Exception): ... _ValueOrNative: TypeAlias = bool | int | float | str | Value | LazyString _ValueOrInt: TypeAlias = Value | int +@disjoint_base class Value: address: Value is_optimized_out: bool @@ -406,6 +407,7 @@ class RecordFunctionSegment: # CLI Commands +@disjoint_base class Command: def __init__(self, name: str, command_class: int, completer_class: int = ..., prefix: bool = ...) -> None: ... def dont_repeat(self) -> None: ... @@ -437,6 +439,7 @@ COMPLETE_EXPRESSION: int # GDB/MI Commands +@disjoint_base class MICommand: name: str installed: bool @@ -446,6 +449,7 @@ class MICommand: # Parameters +@disjoint_base class Parameter: set_doc: str show_doc: str @@ -682,6 +686,7 @@ class LineTable: # Breakpoints +@disjoint_base class Breakpoint: # The where="spec" form of __init__(). See py-breakpoints.c:bppy_init():keywords for the positional order. @overload @@ -854,6 +859,7 @@ WP_ACCESS: int # Finish Breakpoints +@disjoint_base class FinishBreakpoint(Breakpoint): return_value: Value | None @@ -907,6 +913,7 @@ class RegisterGroupsIterator(Iterator[RegisterGroup]): # Connections +@disjoint_base class TargetConnection: def is_valid(self) -> bool: ... @@ -941,6 +948,7 @@ class _Window(Protocol): def click(self, x: int, y: int, button: int) -> None: ... # Events +@disjoint_base class Event: ... class ThreadEvent(Event): diff --git a/stubs/gdb/gdb/disassembler.pyi b/stubs/gdb/gdb/disassembler.pyi index 9310e382307a..e878264cfef5 100644 --- a/stubs/gdb/gdb/disassembler.pyi +++ b/stubs/gdb/gdb/disassembler.pyi @@ -1,5 +1,6 @@ from collections.abc import Sequence from typing import Final, final +from typing_extensions import disjoint_base import gdb from gdb import Architecture, Progspace @@ -8,6 +9,7 @@ class Disassembler: def __init__(self, name: str) -> None: ... def __call__(self, info): ... +@disjoint_base class DisassembleInfo: address: int architecture: Architecture diff --git a/stubs/gevent/gevent/_greenlet_primitives.pyi b/stubs/gevent/gevent/_greenlet_primitives.pyi index 334f4178491b..c1e1b36c2798 100644 --- a/stubs/gevent/gevent/_greenlet_primitives.pyi +++ b/stubs/gevent/gevent/_greenlet_primitives.pyi @@ -1,11 +1,13 @@ from abc import abstractmethod from typing import Any, NoReturn +from typing_extensions import disjoint_base from gevent._types import _Loop from greenlet import greenlet class TrackedRawGreenlet(greenlet): ... +@disjoint_base class SwitchOutGreenletWithLoop(TrackedRawGreenlet): @property @abstractmethod diff --git a/stubs/gevent/gevent/_hub_primitives.pyi b/stubs/gevent/gevent/_hub_primitives.pyi index e308682edc42..0d9c12228af3 100644 --- a/stubs/gevent/gevent/_hub_primitives.pyi +++ b/stubs/gevent/gevent/_hub_primitives.pyi @@ -2,7 +2,7 @@ from _typeshed import FileDescriptor from collections.abc import Callable, Collection, Iterable from types import TracebackType from typing import Any, Generic, Protocol, TypeVar, overload, type_check_only -from typing_extensions import Self, TypeVarTuple, Unpack +from typing_extensions import Self, TypeVarTuple, Unpack, disjoint_base from gevent._greenlet_primitives import SwitchOutGreenletWithLoop from gevent._types import _Loop, _Watcher @@ -32,6 +32,7 @@ class WaitOperationsGreenlet(SwitchOutGreenletWithLoop): ) -> None: ... def cancel_wait(self, watcher: _Watcher, error: type[BaseException] | BaseException, close_watcher: bool = False) -> None: ... +@disjoint_base class _WaitIterator(Generic[_T]): def __init__(self, objects: Collection[_T], hub: Hub, timeout: float, count: None | int) -> None: ... def __enter__(self) -> Self: ... diff --git a/stubs/gevent/gevent/_imap.pyi b/stubs/gevent/gevent/_imap.pyi index 1220d57a65c6..6ead2113e922 100644 --- a/stubs/gevent/gevent/_imap.pyi +++ b/stubs/gevent/gevent/_imap.pyi @@ -1,6 +1,6 @@ from collections.abc import Callable, Iterable from typing import Any, TypeVar -from typing_extensions import ParamSpec, Self +from typing_extensions import ParamSpec, Self, disjoint_base from gevent.greenlet import Greenlet from gevent.queue import UnboundQueue @@ -12,6 +12,7 @@ _P = ParamSpec("_P") # returned by some public API functions, we don't bother adding a whole bunch of overloads to handle # the case of 1-n Iterables being passed in and just go for the fully unsafe signature # we do the crazy overloads instead in the functions that create these objects +@disjoint_base class IMapUnordered(Greenlet[_P, _T]): finished: bool # it may contain an undocumented Failure object @@ -20,6 +21,7 @@ class IMapUnordered(Greenlet[_P, _T]): def __iter__(self) -> Self: ... def __next__(self) -> _T: ... +@disjoint_base class IMap(IMapUnordered[_P, _T]): index: int diff --git a/stubs/gevent/gevent/greenlet.pyi b/stubs/gevent/gevent/greenlet.pyi index 51ca9730d2eb..96f4893f9914 100644 --- a/stubs/gevent/gevent/greenlet.pyi +++ b/stubs/gevent/gevent/greenlet.pyi @@ -2,7 +2,7 @@ import weakref from collections.abc import Callable, Iterable, Sequence from types import FrameType, TracebackType from typing import Any, ClassVar, Generic, TypeVar, overload -from typing_extensions import ParamSpec, Self +from typing_extensions import ParamSpec, Self, disjoint_base import greenlet from gevent._types import _Loop @@ -12,6 +12,7 @@ _T = TypeVar("_T") _G = TypeVar("_G", bound=greenlet.greenlet) _P = ParamSpec("_P") +@disjoint_base class Greenlet(greenlet.greenlet, Generic[_P, _T]): # we can't use _P.args/_P.kwargs here because pyright will complain # mypy doesn't seem to mind though diff --git a/stubs/gevent/gevent/libev/corecext.pyi b/stubs/gevent/gevent/libev/corecext.pyi index 8edbbc56a110..2a6b3858b415 100644 --- a/stubs/gevent/gevent/libev/corecext.pyi +++ b/stubs/gevent/gevent/libev/corecext.pyi @@ -3,7 +3,7 @@ from _typeshed import FileDescriptor from collections.abc import Callable, Sequence from types import TracebackType from typing import Any -from typing_extensions import ParamSpec +from typing_extensions import ParamSpec, disjoint_base from gevent._ffi.loop import _ErrorHandler from gevent._types import _Callback @@ -20,7 +20,7 @@ if sys.platform != "win32": def recommended_backends() -> list[str | int]: ... def supported_backends() -> list[str | int]: ... def time() -> float: ... - + @disjoint_base class loop: starting_timer_may_update_loop_time: bool error_handler: _ErrorHandler diff --git a/stubs/gevent/gevent/resolver/cares.pyi b/stubs/gevent/gevent/resolver/cares.pyi index c6b8dc645105..01dbe77d2e2c 100644 --- a/stubs/gevent/gevent/resolver/cares.pyi +++ b/stubs/gevent/gevent/resolver/cares.pyi @@ -1,6 +1,6 @@ from collections.abc import Callable, Iterable, Sequence from typing import Any, Generic, TypeVar -from typing_extensions import Self +from typing_extensions import Self, disjoint_base from gevent._types import _AddrinfoResult, _Loop, _NameinfoResult, _SockAddr @@ -10,6 +10,7 @@ class ares_host_result(tuple[str, list[str], list[str]]): family: int def __new__(cls, family: int, iterable: Iterable[Any]) -> Self: ... +@disjoint_base class Result(Generic[_T]): exception: BaseException | None value: _T | None @@ -17,6 +18,7 @@ class Result(Generic[_T]): def get(self) -> Any | None: ... def successful(self) -> bool: ... +@disjoint_base class channel: @property def loop(self) -> _Loop: ... diff --git a/stubs/greenlet/greenlet/_greenlet.pyi b/stubs/greenlet/greenlet/_greenlet.pyi index aafc728fa4e3..92607c354f82 100644 --- a/stubs/greenlet/greenlet/_greenlet.pyi +++ b/stubs/greenlet/greenlet/_greenlet.pyi @@ -3,7 +3,7 @@ from collections.abc import Callable from contextvars import Context from types import FrameType, TracebackType from typing import Any, Literal, Protocol, overload, type_check_only -from typing_extensions import TypeAlias +from typing_extensions import TypeAlias, disjoint_base _TraceEvent: TypeAlias = Literal["switch", "throw"] _TraceCallback: TypeAlias = Callable[[_TraceEvent, tuple[greenlet, greenlet]], object] @@ -27,6 +27,7 @@ class _ParentDescriptor(Protocol): class GreenletExit(BaseException): ... class error(Exception): ... +@disjoint_base class greenlet: @property def dead(self) -> bool: ... diff --git a/stubs/hdbcli/hdbcli/dbapi.pyi b/stubs/hdbcli/hdbcli/dbapi.pyi index 0db854ac86a9..8cccb842afe8 100644 --- a/stubs/hdbcli/hdbcli/dbapi.pyi +++ b/stubs/hdbcli/hdbcli/dbapi.pyi @@ -4,7 +4,7 @@ from collections.abc import Callable, Sequence from datetime import date, datetime, time from types import TracebackType from typing import Any, Final, Literal, overload -from typing_extensions import Self, TypeAlias +from typing_extensions import Self, TypeAlias, disjoint_base from .resultrow import ResultRow @@ -12,6 +12,7 @@ apilevel: Final[str] threadsafety: Final[int] paramstyle: Final[tuple[str, ...]] # hdbcli defines it as a tuple which does not follow PEP 249 +@disjoint_base class Connection: def __init__( self, @@ -42,6 +43,7 @@ class Connection: connect = Connection +@disjoint_base class LOB: def __init__(self, *args: Any, **kwargs: Any) -> None: ... def close(self) -> bool: ... @@ -52,6 +54,7 @@ class LOB: _Parameters: TypeAlias = Sequence[tuple[Any, ...]] | None _Holdability: TypeAlias = Literal[0, 1, 2, 3] +@disjoint_base class Cursor: description: tuple[tuple[Any, ...], ...] rowcount: int diff --git a/stubs/hdbcli/hdbcli/resultrow.pyi b/stubs/hdbcli/hdbcli/resultrow.pyi index 26b6c37fc773..d3942e84a822 100644 --- a/stubs/hdbcli/hdbcli/resultrow.pyi +++ b/stubs/hdbcli/hdbcli/resultrow.pyi @@ -1,6 +1,8 @@ from collections.abc import Iterator, Sequence from typing import Any, overload +from typing_extensions import disjoint_base +@disjoint_base class ResultRow: def __init__(self, *args: Any, **kwargs: Any) -> None: ... column_names: tuple[str, ...] diff --git a/stubs/lupa/lupa/lua51.pyi b/stubs/lupa/lupa/lua51.pyi index a46b772bec38..6cc8152115ca 100644 --- a/stubs/lupa/lupa/lua51.pyi +++ b/stubs/lupa/lupa/lua51.pyi @@ -1,7 +1,7 @@ from _typeshed import MaybeNone from collections.abc import Callable, Iterable from typing import Any, Final, Generic, TypeVar, type_check_only -from typing_extensions import Self, TypeAlias +from typing_extensions import Self, TypeAlias, disjoint_base __all__ = [ "LUA_VERSION", @@ -62,6 +62,7 @@ class _LuaNoGC: ... _bint = TypeVar("_bint", bool, int) +@disjoint_base class FastRLock(Generic[_bint]): # @classmethod # def __init__(cls, /, *args: Any, **kwargs: Any) -> None: ... @@ -74,6 +75,7 @@ class LuaError(Exception): ... class LuaSyntaxError(LuaError): ... class LuaMemoryError(LuaError, MemoryError): ... +@disjoint_base class LuaRuntime: lua_implementation: Final[str] lua_version: Final[tuple[int, int]] diff --git a/stubs/lupa/lupa/lua52.pyi b/stubs/lupa/lupa/lua52.pyi index a46b772bec38..6cc8152115ca 100644 --- a/stubs/lupa/lupa/lua52.pyi +++ b/stubs/lupa/lupa/lua52.pyi @@ -1,7 +1,7 @@ from _typeshed import MaybeNone from collections.abc import Callable, Iterable from typing import Any, Final, Generic, TypeVar, type_check_only -from typing_extensions import Self, TypeAlias +from typing_extensions import Self, TypeAlias, disjoint_base __all__ = [ "LUA_VERSION", @@ -62,6 +62,7 @@ class _LuaNoGC: ... _bint = TypeVar("_bint", bool, int) +@disjoint_base class FastRLock(Generic[_bint]): # @classmethod # def __init__(cls, /, *args: Any, **kwargs: Any) -> None: ... @@ -74,6 +75,7 @@ class LuaError(Exception): ... class LuaSyntaxError(LuaError): ... class LuaMemoryError(LuaError, MemoryError): ... +@disjoint_base class LuaRuntime: lua_implementation: Final[str] lua_version: Final[tuple[int, int]] diff --git a/stubs/lupa/lupa/lua53.pyi b/stubs/lupa/lupa/lua53.pyi index a46b772bec38..6cc8152115ca 100644 --- a/stubs/lupa/lupa/lua53.pyi +++ b/stubs/lupa/lupa/lua53.pyi @@ -1,7 +1,7 @@ from _typeshed import MaybeNone from collections.abc import Callable, Iterable from typing import Any, Final, Generic, TypeVar, type_check_only -from typing_extensions import Self, TypeAlias +from typing_extensions import Self, TypeAlias, disjoint_base __all__ = [ "LUA_VERSION", @@ -62,6 +62,7 @@ class _LuaNoGC: ... _bint = TypeVar("_bint", bool, int) +@disjoint_base class FastRLock(Generic[_bint]): # @classmethod # def __init__(cls, /, *args: Any, **kwargs: Any) -> None: ... @@ -74,6 +75,7 @@ class LuaError(Exception): ... class LuaSyntaxError(LuaError): ... class LuaMemoryError(LuaError, MemoryError): ... +@disjoint_base class LuaRuntime: lua_implementation: Final[str] lua_version: Final[tuple[int, int]] diff --git a/stubs/lupa/lupa/lua54.pyi b/stubs/lupa/lupa/lua54.pyi index a46b772bec38..6cc8152115ca 100644 --- a/stubs/lupa/lupa/lua54.pyi +++ b/stubs/lupa/lupa/lua54.pyi @@ -1,7 +1,7 @@ from _typeshed import MaybeNone from collections.abc import Callable, Iterable from typing import Any, Final, Generic, TypeVar, type_check_only -from typing_extensions import Self, TypeAlias +from typing_extensions import Self, TypeAlias, disjoint_base __all__ = [ "LUA_VERSION", @@ -62,6 +62,7 @@ class _LuaNoGC: ... _bint = TypeVar("_bint", bool, int) +@disjoint_base class FastRLock(Generic[_bint]): # @classmethod # def __init__(cls, /, *args: Any, **kwargs: Any) -> None: ... @@ -74,6 +75,7 @@ class LuaError(Exception): ... class LuaSyntaxError(LuaError): ... class LuaMemoryError(LuaError, MemoryError): ... +@disjoint_base class LuaRuntime: lua_implementation: Final[str] lua_version: Final[tuple[int, int]] diff --git a/stubs/lupa/lupa/luajit20.pyi b/stubs/lupa/lupa/luajit20.pyi index cdd4e4b096dd..5e5009bb287f 100644 --- a/stubs/lupa/lupa/luajit20.pyi +++ b/stubs/lupa/lupa/luajit20.pyi @@ -1,6 +1,7 @@ from _typeshed import MaybeNone from collections.abc import Callable, Iterator from typing import Any, Final, Generic, TypeVar, type_check_only +from typing_extensions import disjoint_base __all__ = [ "LUA_VERSION", @@ -54,6 +55,7 @@ class _LuaObject: ... _bint = TypeVar("_bint", bool, int) +@disjoint_base class FastRLock(Generic[_bint]): # @classmethod # def __init__(cls, /, *args: Any, **kwargs: Any) -> None: ... @@ -66,6 +68,7 @@ class LuaError(Exception): ... class LuaSyntaxError(LuaError): ... class LuaMemoryError(LuaError, MemoryError): ... +@disjoint_base class LuaRuntime: lua_implementation: Final[str] lua_version: Final[tuple[int, int]] diff --git a/stubs/lupa/lupa/luajit21.pyi b/stubs/lupa/lupa/luajit21.pyi index cdd4e4b096dd..5e5009bb287f 100644 --- a/stubs/lupa/lupa/luajit21.pyi +++ b/stubs/lupa/lupa/luajit21.pyi @@ -1,6 +1,7 @@ from _typeshed import MaybeNone from collections.abc import Callable, Iterator from typing import Any, Final, Generic, TypeVar, type_check_only +from typing_extensions import disjoint_base __all__ = [ "LUA_VERSION", @@ -54,6 +55,7 @@ class _LuaObject: ... _bint = TypeVar("_bint", bool, int) +@disjoint_base class FastRLock(Generic[_bint]): # @classmethod # def __init__(cls, /, *args: Any, **kwargs: Any) -> None: ... @@ -66,6 +68,7 @@ class LuaError(Exception): ... class LuaSyntaxError(LuaError): ... class LuaMemoryError(LuaError, MemoryError): ... +@disjoint_base class LuaRuntime: lua_implementation: Final[str] lua_version: Final[tuple[int, int]] diff --git a/stubs/mysqlclient/MySQLdb/_mysql.pyi b/stubs/mysqlclient/MySQLdb/_mysql.pyi index 0ab789e41d46..2ee0b9493565 100644 --- a/stubs/mysqlclient/MySQLdb/_mysql.pyi +++ b/stubs/mysqlclient/MySQLdb/_mysql.pyi @@ -1,5 +1,6 @@ import builtins from _typeshed import Incomplete +from typing_extensions import disjoint_base import MySQLdb._exceptions @@ -17,6 +18,7 @@ class OperationalError(MySQLdb._exceptions.DatabaseError): ... class ProgrammingError(MySQLdb._exceptions.DatabaseError): ... class Warning(builtins.Warning, MySQLdb._exceptions.MySQLError): ... +@disjoint_base class connection: client_flag: Incomplete converter: Incomplete @@ -67,6 +69,7 @@ class connection: def __delattr__(self, name: str, /) -> None: ... def __setattr__(self, name: str, value, /) -> None: ... +@disjoint_base class result: converter: Incomplete has_next: Incomplete diff --git a/stubs/psycopg2/psycopg2/_psycopg.pyi b/stubs/psycopg2/psycopg2/_psycopg.pyi index 3a1b46606cbd..8899cb13f8de 100644 --- a/stubs/psycopg2/psycopg2/_psycopg.pyi +++ b/stubs/psycopg2/psycopg2/_psycopg.pyi @@ -3,7 +3,7 @@ from _typeshed import ConvertibleToInt, Incomplete, SupportsRead, SupportsReadli from collections.abc import Callable, Iterable, Mapping, Sequence from types import TracebackType from typing import Any, Literal, NoReturn, Protocol, TextIO, TypeVar, overload, type_check_only -from typing_extensions import Self, TypeAlias +from typing_extensions import Self, TypeAlias, disjoint_base from psycopg2.extras import ReplicationCursor as extras_ReplicationCursor from psycopg2.sql import Composable @@ -89,6 +89,7 @@ _T_co = TypeVar("_T_co", covariant=True) @type_check_only class _SupportsReadAndReadline(SupportsRead[_T_co], SupportsReadline[_T_co], Protocol[_T_co]): ... +@disjoint_base class cursor: arraysize: int binary_types: Incomplete | None @@ -165,6 +166,7 @@ class cursor: _Cursor: TypeAlias = cursor +@disjoint_base class AsIs: def __init__(self, obj: object, /, **kwargs: Unused) -> None: ... @property @@ -172,6 +174,7 @@ class AsIs: def getquoted(self) -> bytes: ... def __conform__(self, proto, /) -> Self | None: ... +@disjoint_base class Binary: def __init__(self, str: object, /, **kwargs: Unused) -> None: ... @property @@ -182,6 +185,7 @@ class Binary: def prepare(self, conn: connection, /) -> None: ... def __conform__(self, proto, /) -> Self | None: ... +@disjoint_base class Boolean: def __init__(self, obj: object, /, **kwargs: Unused) -> None: ... @property @@ -189,6 +193,7 @@ class Boolean: def getquoted(self) -> bytes: ... def __conform__(self, proto, /) -> Self | None: ... +@disjoint_base class Column: display_size: Any internal_size: Any @@ -211,6 +216,7 @@ class Column: def __ne__(self, other, /): ... def __setstate__(self, state, /): ... +@disjoint_base class ConnectionInfo: # Note: the following properties can be None if their corresponding libpq function # returns NULL. They're not annotated as such, because this is very unlikely in @@ -270,6 +276,7 @@ class ConnectionInfo: def parameter_status(self, name: str) -> str | None: ... def ssl_attribute(self, name: str) -> str | None: ... +@disjoint_base class Error(Exception): cursor: _Cursor | None diag: Diagnostics @@ -291,6 +298,7 @@ class TransactionRollbackError(OperationalError): ... class InterfaceError(Error): ... class Warning(Exception): ... +@disjoint_base class ISQLQuote: _wrapped: Any def __init__(self, wrapped: object, /, **kwargs) -> None: ... @@ -298,6 +306,7 @@ class ISQLQuote: def getbuffer(self): ... def getquoted(self) -> bytes: ... +@disjoint_base class Decimal: def __init__(self, value: object, /, **kwargs: Unused) -> None: ... @property @@ -305,6 +314,7 @@ class Decimal: def getquoted(self) -> bytes: ... def __conform__(self, proto, /) -> Self | None: ... +@disjoint_base class Diagnostics: column_name: str | None constraint_name: str | None @@ -326,6 +336,7 @@ class Diagnostics: table_name: str | None def __init__(self, err: Error, /) -> None: ... +@disjoint_base class Float: def __init__(self, value: float, /, **kwargs: Unused) -> None: ... @property @@ -333,6 +344,7 @@ class Float: def getquoted(self) -> bytes: ... def __conform__(self, proto, /) -> Self | None: ... +@disjoint_base class Int: def __init__(self, value: ConvertibleToInt, /, **kwargs: Unused) -> None: ... @property @@ -340,6 +352,7 @@ class Int: def getquoted(self) -> bytes: ... def __conform__(self, proto, /) -> Self | None: ... +@disjoint_base class List: def __init__(self, objs: list[object], /, **kwargs: Unused) -> None: ... @property @@ -348,6 +361,7 @@ class List: def prepare(self, conn: connection, /) -> None: ... def __conform__(self, proto, /) -> Self | None: ... +@disjoint_base class Notify: channel: Any payload: Any @@ -363,6 +377,7 @@ class Notify: def __lt__(self, other, /): ... def __ne__(self, other, /): ... +@disjoint_base class QuotedString: encoding: str def __init__(self, str: object, /, **kwargs: Unused) -> None: ... @@ -374,6 +389,7 @@ class QuotedString: def prepare(self, conn: connection, /) -> None: ... def __conform__(self, proto, /) -> Self | None: ... +@disjoint_base class ReplicationCursor(cursor): feedback_timestamp: Any io_timestamp: Any @@ -384,6 +400,7 @@ class ReplicationCursor(cursor): def send_feedback(self, write_lsn=..., flush_lsn=..., apply_lsn=..., reply=..., force=...): ... def start_replication_expert(self, command, decode=..., status_interval=...): ... +@disjoint_base class ReplicationMessage: cursor: Any data_size: Any @@ -393,6 +410,7 @@ class ReplicationMessage: wal_end: Any def __init__(self, *args, **kwargs) -> None: ... +@disjoint_base class Xid: bqual: Any database: Any @@ -407,6 +425,7 @@ class Xid: _T_cur = TypeVar("_T_cur", bound=cursor) +@disjoint_base class connection: DataError: type[DataError] DatabaseError: type[DatabaseError] @@ -521,6 +540,7 @@ class connection: _Connection: TypeAlias = connection +@disjoint_base class ReplicationConnection(connection): autocommit: Any isolation_level: Any @@ -554,6 +574,7 @@ class ReplicationConnection(connection): scrollable: bool | None = None, ) -> _T_cur: ... +@disjoint_base class lobject: closed: Any mode: Any diff --git a/stubs/pywin32/_win32typing.pyi b/stubs/pywin32/_win32typing.pyi index becc168ca7f0..38d9d578b468 100644 --- a/stubs/pywin32/_win32typing.pyi +++ b/stubs/pywin32/_win32typing.pyi @@ -2,7 +2,7 @@ from _typeshed import Incomplete, Unused from collections.abc import Iterable, Sequence from typing import Literal, NoReturn, SupportsIndex, final, overload -from typing_extensions import Self, TypeAlias, deprecated +from typing_extensions import Self, TypeAlias, deprecated, disjoint_base from win32.lib.pywintypes import TimeType @@ -16,6 +16,7 @@ class PyOleEmpty: ... class PyOleMissing: ... class PyOleNothing: ... +@disjoint_base class PyDSCAPSType: @property def dwFlags(self): ... @@ -60,12 +61,14 @@ class PyDSCAPSType: @property def dwUnlockTransferRateHwBuffers(self): ... +@disjoint_base class PyDSCBCAPSType: @property def dwBufferBytes(self): ... @property def dwFlags(self): ... +@disjoint_base class PyDSCCAPSType: @property def dwChannels(self): ... @@ -609,11 +612,13 @@ class PyConsoleScreenBuffer: def Close(self, *args): ... # incomplete def Detach(self, *args): ... # incomplete +@disjoint_base class PyCredHandle: def Detach(self): ... def FreeCredentialsHandle(self) -> None: ... def QueryCredentialsAttributes(self, Attribute: int, /) -> str: ... +@disjoint_base class PyCtxtHandle: def Detach(self): ... def CompleteAuthToken(self, Token: PySecBufferDesc, /) -> None: ... @@ -814,6 +819,7 @@ class PyDEVMODEW: @DriverData.setter def DriverData(self, value: bytes) -> None: ... +@disjoint_base class PyDISPLAY_DEVICE: @property def Size(self) -> int: ... @@ -1650,6 +1656,7 @@ class PySTARTUPINFO: lpDesktop: str lpTitle: str +@disjoint_base class PySecBuffer: def __new__(self, BufferSize, BufferType) -> Self: ... @property @@ -1662,6 +1669,7 @@ class PySecBuffer: def MaxBufferSize(self): ... def Clear(self) -> None: ... +@disjoint_base class PySecBufferDesc: def __new__(self, Version=...) -> Self: ... Version: Incomplete @@ -2649,6 +2657,7 @@ class PyBIND_OPTS: class PyCMINVOKECOMMANDINFO: ... +@disjoint_base class PyDSBCAPS: @property def dwFlags(self) -> int: ... @@ -2659,6 +2668,7 @@ class PyDSBCAPS: @property def dwPlayCpuOverhead(self): ... +@disjoint_base class PyDSBUFFERDESC: @property def dwFlags(self) -> int: ... @@ -2667,6 +2677,7 @@ class PyDSBUFFERDESC: @property def lpwfxFormat(self): ... +@disjoint_base class PyDSCAPS: @property def dwFlags(self) -> int: ... @@ -2711,12 +2722,14 @@ class PyDSCAPS: @property def dwPlayCpuOverheadSwBuffers(self) -> int: ... +@disjoint_base class PyDSCBCAPS: @property def dwFlags(self) -> int: ... @property def dwBufferBytes(self) -> int: ... +@disjoint_base class PyDSCBUFFERDESC: @property def dwFlags(self) -> int: ... @@ -2725,6 +2738,7 @@ class PyDSCBUFFERDESC: @property def lpwfxFormat(self): ... +@disjoint_base class PyDSCCAPS: @property def dwFlags(self) -> int: ... @@ -2751,6 +2765,7 @@ class PyDSOP_SCOPE_INIT_INFO: @property def filterFlags(self) -> PyDSOP_FILTER_FLAGS: ... +@disjoint_base class PyDSOP_SCOPE_INIT_INFOs: def __new__(cls, size, /): ... diff --git a/stubs/pywin32/pythoncom.pyi b/stubs/pywin32/pythoncom.pyi index 657a736f0c55..6368357725a9 100644 --- a/stubs/pywin32/pythoncom.pyi +++ b/stubs/pywin32/pythoncom.pyi @@ -2,7 +2,7 @@ from _typeshed import Incomplete, Unused from abc import abstractmethod from collections.abc import Sequence from typing import ClassVar, SupportsInt, overload -from typing_extensions import TypeAlias, deprecated +from typing_extensions import TypeAlias, deprecated, disjoint_base import _win32typing from win32.lib.pywintypes import TimeType, com_error as com_error @@ -11,6 +11,7 @@ error: TypeAlias = com_error # noqa: Y042 class internal_error(Exception): ... +@disjoint_base class com_record: @abstractmethod def __init__(self, /, *args, **kwargs) -> None: ... diff --git a/stubs/pywin32/win32/lib/pywintypes.pyi b/stubs/pywin32/win32/lib/pywintypes.pyi index c5f83fb354b3..6a4d4c6872b1 100644 --- a/stubs/pywin32/win32/lib/pywintypes.pyi +++ b/stubs/pywin32/win32/lib/pywintypes.pyi @@ -4,7 +4,7 @@ from _typeshed import Incomplete from collections.abc import Sequence from datetime import datetime from typing import ClassVar, Final, NoReturn, SupportsInt, overload -from typing_extensions import Never, deprecated +from typing_extensions import Never, deprecated, disjoint_base import _win32typing @@ -16,6 +16,7 @@ class error(Exception): class com_error(Exception): ... +@disjoint_base class HANDLEType: def __new__(self, *args: Never) -> NoReturn: ... @property diff --git a/stubs/shapely/shapely/lib.pyi b/stubs/shapely/shapely/lib.pyi index 4bb5146b779f..45a785f91909 100644 --- a/stubs/shapely/shapely/lib.pyi +++ b/stubs/shapely/shapely/lib.pyi @@ -1,5 +1,5 @@ from typing import Literal, SupportsIndex, final, overload -from typing_extensions import Never, Self +from typing_extensions import Never, Self, disjoint_base import numpy as np from numpy.typing import NDArray @@ -142,6 +142,7 @@ geos_version: tuple[int, int, int] geos_version_string: str registry: list[type[Geometry]] +@disjoint_base class Geometry: def __hash__(self) -> int: ... def __eq__(self, other: object, /) -> bool: ... From 43f9e352257304b8bf5bfe74c8375f28603a4fd8 Mon Sep 17 00:00:00 2001 From: Brian Schubert Date: Fri, 12 Sep 2025 09:25:41 -0400 Subject: [PATCH 2/5] Add allowlist entry for `gevent.socket.SocketType` --- stubs/gevent/@tests/stubtest_allowlist.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/stubs/gevent/@tests/stubtest_allowlist.txt b/stubs/gevent/@tests/stubtest_allowlist.txt index 19832db85422..8e42b951b9e8 100644 --- a/stubs/gevent/@tests/stubtest_allowlist.txt +++ b/stubs/gevent/@tests/stubtest_allowlist.txt @@ -64,6 +64,10 @@ gevent.socket.SocketType.makefile gevent.socket.SocketType.sendfile gevent.socket.SocketType.set_inheritable +# Pretends to re-export a type marked @disjoint_base in the stubs, but runtime +# defines __slots__ +gevent.socket.SocketType$ + # zope.interface related attributes we can ignore gevent.[\w\.]+\.__implemented__ gevent.[\w\.]+\.__providedBy__ From eaf8172033a418ee3201e36704e0053bfbe19eac Mon Sep 17 00:00:00 2001 From: Brian Schubert Date: Sun, 14 Sep 2025 07:35:58 -0400 Subject: [PATCH 3/5] Workaround for applying @disjoint_base when __new__ returns Never ``` error: not checking stubs due to mypy build errors: stubs\pywin32\win32\lib\pywintypes.pyi:20: error: Value of type variable "_TC" of "disjoint_base" cannot be "Callable[[VarArg(Never)], Never]" [type-var] ``` --- stubs/pywin32/win32/lib/pywintypes.pyi | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/stubs/pywin32/win32/lib/pywintypes.pyi b/stubs/pywin32/win32/lib/pywintypes.pyi index 6a4d4c6872b1..45d14c0c12f0 100644 --- a/stubs/pywin32/win32/lib/pywintypes.pyi +++ b/stubs/pywin32/win32/lib/pywintypes.pyi @@ -3,8 +3,8 @@ from _typeshed import Incomplete from collections.abc import Sequence from datetime import datetime -from typing import ClassVar, Final, NoReturn, SupportsInt, overload -from typing_extensions import Never, deprecated, disjoint_base +from typing import ClassVar, Final, SupportsInt, overload +from typing_extensions import Never, Self, deprecated, disjoint_base import _win32typing @@ -18,7 +18,7 @@ class com_error(Exception): ... @disjoint_base class HANDLEType: - def __new__(self, *args: Never) -> NoReturn: ... + def __new__(cls, *args: Never) -> Self: ... @property def handle(self) -> int: ... def Close(self) -> None: ... From f58c02cdd3f800984b658d41d34dc5951166da3b Mon Sep 17 00:00:00 2001 From: Brian Schubert Date: Sun, 14 Sep 2025 07:40:57 -0400 Subject: [PATCH 4/5] Revert "Add `--ignore-disjoint-bases` to 3rd party stubtest" This reverts commit fd65d0e3d234ca9a8a36eff19a5dfd1022bb0a23. --- tests/stubtest_third_party.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/stubtest_third_party.py b/tests/stubtest_third_party.py index 8224d22fd383..d2ea4190bc77 100755 --- a/tests/stubtest_third_party.py +++ b/tests/stubtest_third_party.py @@ -116,8 +116,6 @@ def run_stubtest(dist: Path, *, verbose: bool = False, ci_platforms_only: bool = *packages_to_check, *modules_to_check, *allowlist_stubtest_arguments(dist_name), - # FIXME: remove once issues are fixed, refs #14699 - "--ignore-disjoint-bases", ] stubs_dir = dist.parent From 38bee75bb2a2bc8f13280800a358003492323aa8 Mon Sep 17 00:00:00 2001 From: Brian Schubert Date: Sun, 14 Sep 2025 16:51:28 -0400 Subject: [PATCH 5/5] Tweak `HANDLEType` --- stubs/pywin32/win32/lib/pywintypes.pyi | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/stubs/pywin32/win32/lib/pywintypes.pyi b/stubs/pywin32/win32/lib/pywintypes.pyi index 45d14c0c12f0..726f7b48ab31 100644 --- a/stubs/pywin32/win32/lib/pywintypes.pyi +++ b/stubs/pywin32/win32/lib/pywintypes.pyi @@ -3,8 +3,8 @@ from _typeshed import Incomplete from collections.abc import Sequence from datetime import datetime -from typing import ClassVar, Final, SupportsInt, overload -from typing_extensions import Never, Self, deprecated, disjoint_base +from typing import ClassVar, Final, NoReturn, SupportsInt, overload +from typing_extensions import Never, deprecated, disjoint_base import _win32typing @@ -17,8 +17,8 @@ class error(Exception): class com_error(Exception): ... @disjoint_base -class HANDLEType: - def __new__(cls, *args: Never) -> Self: ... +class HANDLEType: # type: ignore[type-var] + def __new__(cls, *args: Never) -> NoReturn: ... @property def handle(self) -> int: ... def Close(self) -> None: ...