From 547c05a94b33ac00756906bb76513e15708cda4c Mon Sep 17 00:00:00 2001 From: jorenham Date: Sun, 12 Apr 2026 21:22:38 +0200 Subject: [PATCH 1/3] `ctypes`: add `__ctype_{be,le}__` class attributes --- stdlib/ctypes/__init__.pyi | 60 +++++++++++++++++++++----------------- 1 file changed, 34 insertions(+), 26 deletions(-) diff --git a/stdlib/ctypes/__init__.pyi b/stdlib/ctypes/__init__.pyi index 8d048aa97e7d..a1915c3849c4 100644 --- a/stdlib/ctypes/__init__.pyi +++ b/stdlib/ctypes/__init__.pyi @@ -219,87 +219,95 @@ class py_object(_CanCastTo, _SimpleCData[_T]): if sys.version_info >= (3, 14): def __class_getitem__(cls, item: Any, /) -> GenericAlias: ... -class c_bool(_SimpleCData[bool]): +@type_check_only +class _SwappableCData: + __ctype_be__: ClassVar[type[Self]] + __ctype_le__: ClassVar[type[Self]] + +class c_bool(_SwappableCData, _SimpleCData[bool]): _type_: ClassVar[Literal["?"]] def __init__(self, value: SupportsBool | SupportsLen | None = ...) -> None: ... -class c_byte(_SimpleCData[int]): +class c_byte(_SwappableCData, _SimpleCData[int]): _type_: ClassVar[Literal["b"]] -class c_ubyte(_SimpleCData[int]): +class c_ubyte(_SwappableCData, _SimpleCData[int]): _type_: ClassVar[Literal["B"]] -class c_short(_SimpleCData[int]): +class c_short(_SwappableCData, _SimpleCData[int]): _type_: ClassVar[Literal["h"]] -class c_ushort(_SimpleCData[int]): +class c_ushort(_SwappableCData, _SimpleCData[int]): _type_: ClassVar[Literal["H"]] -class c_long(_SimpleCData[int]): +class c_long(_SwappableCData, _SimpleCData[int]): _type_: ClassVar[Literal["l"]] -class c_ulong(_SimpleCData[int]): +class c_ulong(_SwappableCData, _SimpleCData[int]): _type_: ClassVar[Literal["L"]] -class c_int(_SimpleCData[int]): # can be an alias for c_long +class c_int(_SwappableCData, _SimpleCData[int]): # can be an alias for c_long _type_: ClassVar[Literal["i", "l"]] -class c_uint(_SimpleCData[int]): # can be an alias for c_ulong +class c_uint(_SwappableCData, _SimpleCData[int]): # can be an alias for c_ulong _type_: ClassVar[Literal["I", "L"]] -class c_longlong(_SimpleCData[int]): # can be an alias for c_long +class c_longlong(_SwappableCData, _SimpleCData[int]): # can be an alias for c_long _type_: ClassVar[Literal["q", "l"]] -class c_ulonglong(_SimpleCData[int]): # can be an alias for c_ulong +class c_ulonglong(_SwappableCData, _SimpleCData[int]): # can be an alias for c_ulong _type_: ClassVar[Literal["Q", "L"]] c_int8 = c_byte c_uint8 = c_ubyte -class c_int16(_SimpleCData[int]): # can be an alias for c_short or c_int +class c_int16(_SwappableCData, _SimpleCData[int]): # can be an alias for c_short or c_int _type_: ClassVar[Literal["h", "i"]] -class c_uint16(_SimpleCData[int]): # can be an alias for c_ushort or c_uint +class c_uint16(_SwappableCData, _SimpleCData[int]): # can be an alias for c_ushort or c_uint _type_: ClassVar[Literal["H", "I"]] -class c_int32(_SimpleCData[int]): # can be an alias for c_int or c_long +class c_int32(_SwappableCData, _SimpleCData[int]): # can be an alias for c_int or c_long _type_: ClassVar[Literal["i", "l"]] -class c_uint32(_SimpleCData[int]): # can be an alias for c_uint or c_ulong +class c_uint32(_SwappableCData, _SimpleCData[int]): # can be an alias for c_uint or c_ulong _type_: ClassVar[Literal["I", "L"]] -class c_int64(_SimpleCData[int]): # can be an alias for c_long or c_longlong +class c_int64(_SwappableCData, _SimpleCData[int]): # can be an alias for c_long or c_longlong _type_: ClassVar[Literal["l", "q"]] -class c_uint64(_SimpleCData[int]): # can be an alias for c_ulong or c_ulonglong +class c_uint64(_SwappableCData, _SimpleCData[int]): # can be an alias for c_ulong or c_ulonglong _type_: ClassVar[Literal["L", "Q"]] -class c_ssize_t(_SimpleCData[int]): # alias for c_int, c_long, or c_longlong +class c_ssize_t(_SwappableCData, _SimpleCData[int]): # alias for c_int, c_long, or c_longlong _type_: ClassVar[Literal["i", "l", "q"]] -class c_size_t(_SimpleCData[int]): # alias for c_uint, c_ulong, or c_ulonglong +class c_size_t(_SwappableCData, _SimpleCData[int]): # alias for c_uint, c_ulong, or c_ulonglong _type_: ClassVar[Literal["I", "L", "Q"]] -class c_float(_SimpleCData[float]): +class c_float(_SwappableCData, _SimpleCData[float]): _type_: ClassVar[Literal["f"]] -class c_double(_SimpleCData[float]): +class c_double(_SwappableCData, _SimpleCData[float]): _type_: ClassVar[Literal["d"]] -class c_longdouble(_SimpleCData[float]): # can be an alias for c_double +class c_longdouble(_SwappableCData, _SimpleCData[float]): # can be an alias for c_double _type_: ClassVar[Literal["d", "g"]] if sys.version_info >= (3, 14) and sys.platform != "win32": - class c_double_complex(_SimpleCData[complex]): + # NOTE: currently (3.14.4) the `__ctype_{be,le}__` attributes of these complex types are missing at runtime: + # https://github.com/python/cpython/issues/148464 + + class c_double_complex(_SwappableCData, _SimpleCData[complex]): _type_: ClassVar[Literal["D"]] - class c_float_complex(_SimpleCData[complex]): + class c_float_complex(_SwappableCData, _SimpleCData[complex]): _type_: ClassVar[Literal["F"]] - class c_longdouble_complex(_SimpleCData[complex]): + class c_longdouble_complex(_SwappableCData, _SimpleCData[complex]): _type_: ClassVar[Literal["G"]] -class c_char(_SimpleCData[bytes]): +class c_char(_SwappableCData, _SimpleCData[bytes]): _type_: ClassVar[Literal["c"]] def __init__(self, value: int | bytes | bytearray = ...) -> None: ... From 7eb3501fc73ae993a78922c4bf0499dfd5bdac19 Mon Sep 17 00:00:00 2001 From: jorenham Date: Sun, 12 Apr 2026 21:38:33 +0200 Subject: [PATCH 2/3] `ctypes`: swap order of `_SwappableCData` (type-check-only) mixin to avoid a mypy_primer error --- stdlib/ctypes/__init__.pyi | 52 +++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/stdlib/ctypes/__init__.pyi b/stdlib/ctypes/__init__.pyi index a1915c3849c4..f4796370f504 100644 --- a/stdlib/ctypes/__init__.pyi +++ b/stdlib/ctypes/__init__.pyi @@ -224,90 +224,90 @@ class _SwappableCData: __ctype_be__: ClassVar[type[Self]] __ctype_le__: ClassVar[type[Self]] -class c_bool(_SwappableCData, _SimpleCData[bool]): +class c_bool(_SimpleCData[bool], _SwappableCData): _type_: ClassVar[Literal["?"]] def __init__(self, value: SupportsBool | SupportsLen | None = ...) -> None: ... -class c_byte(_SwappableCData, _SimpleCData[int]): +class c_byte(_SimpleCData[int], _SwappableCData): _type_: ClassVar[Literal["b"]] -class c_ubyte(_SwappableCData, _SimpleCData[int]): +class c_ubyte(_SimpleCData[int], _SwappableCData): _type_: ClassVar[Literal["B"]] -class c_short(_SwappableCData, _SimpleCData[int]): +class c_short(_SimpleCData[int], _SwappableCData): _type_: ClassVar[Literal["h"]] -class c_ushort(_SwappableCData, _SimpleCData[int]): +class c_ushort(_SimpleCData[int], _SwappableCData): _type_: ClassVar[Literal["H"]] -class c_long(_SwappableCData, _SimpleCData[int]): +class c_long(_SimpleCData[int], _SwappableCData): _type_: ClassVar[Literal["l"]] -class c_ulong(_SwappableCData, _SimpleCData[int]): +class c_ulong(_SimpleCData[int], _SwappableCData): _type_: ClassVar[Literal["L"]] -class c_int(_SwappableCData, _SimpleCData[int]): # can be an alias for c_long +class c_int(_SimpleCData[int], _SwappableCData): # can be an alias for c_long _type_: ClassVar[Literal["i", "l"]] -class c_uint(_SwappableCData, _SimpleCData[int]): # can be an alias for c_ulong +class c_uint(_SimpleCData[int], _SwappableCData): # can be an alias for c_ulong _type_: ClassVar[Literal["I", "L"]] -class c_longlong(_SwappableCData, _SimpleCData[int]): # can be an alias for c_long +class c_longlong(_SimpleCData[int], _SwappableCData): # can be an alias for c_long _type_: ClassVar[Literal["q", "l"]] -class c_ulonglong(_SwappableCData, _SimpleCData[int]): # can be an alias for c_ulong +class c_ulonglong(_SimpleCData[int], _SwappableCData): # can be an alias for c_ulong _type_: ClassVar[Literal["Q", "L"]] c_int8 = c_byte c_uint8 = c_ubyte -class c_int16(_SwappableCData, _SimpleCData[int]): # can be an alias for c_short or c_int +class c_int16(_SimpleCData[int], _SwappableCData): # can be an alias for c_short or c_int _type_: ClassVar[Literal["h", "i"]] -class c_uint16(_SwappableCData, _SimpleCData[int]): # can be an alias for c_ushort or c_uint +class c_uint16(_SimpleCData[int], _SwappableCData): # can be an alias for c_ushort or c_uint _type_: ClassVar[Literal["H", "I"]] -class c_int32(_SwappableCData, _SimpleCData[int]): # can be an alias for c_int or c_long +class c_int32(_SimpleCData[int], _SwappableCData): # can be an alias for c_int or c_long _type_: ClassVar[Literal["i", "l"]] -class c_uint32(_SwappableCData, _SimpleCData[int]): # can be an alias for c_uint or c_ulong +class c_uint32(_SimpleCData[int], _SwappableCData): # can be an alias for c_uint or c_ulong _type_: ClassVar[Literal["I", "L"]] -class c_int64(_SwappableCData, _SimpleCData[int]): # can be an alias for c_long or c_longlong +class c_int64(_SimpleCData[int], _SwappableCData): # can be an alias for c_long or c_longlong _type_: ClassVar[Literal["l", "q"]] -class c_uint64(_SwappableCData, _SimpleCData[int]): # can be an alias for c_ulong or c_ulonglong +class c_uint64(_SimpleCData[int], _SwappableCData): # can be an alias for c_ulong or c_ulonglong _type_: ClassVar[Literal["L", "Q"]] -class c_ssize_t(_SwappableCData, _SimpleCData[int]): # alias for c_int, c_long, or c_longlong +class c_ssize_t(_SimpleCData[int], _SwappableCData): # alias for c_int, c_long, or c_longlong _type_: ClassVar[Literal["i", "l", "q"]] -class c_size_t(_SwappableCData, _SimpleCData[int]): # alias for c_uint, c_ulong, or c_ulonglong +class c_size_t(_SimpleCData[int], _SwappableCData): # alias for c_uint, c_ulong, or c_ulonglong _type_: ClassVar[Literal["I", "L", "Q"]] -class c_float(_SwappableCData, _SimpleCData[float]): +class c_float(_SimpleCData[float], _SwappableCData): _type_: ClassVar[Literal["f"]] -class c_double(_SwappableCData, _SimpleCData[float]): +class c_double(_SimpleCData[float], _SwappableCData): _type_: ClassVar[Literal["d"]] -class c_longdouble(_SwappableCData, _SimpleCData[float]): # can be an alias for c_double +class c_longdouble(_SimpleCData[float], _SwappableCData): # can be an alias for c_double _type_: ClassVar[Literal["d", "g"]] if sys.version_info >= (3, 14) and sys.platform != "win32": # NOTE: currently (3.14.4) the `__ctype_{be,le}__` attributes of these complex types are missing at runtime: # https://github.com/python/cpython/issues/148464 - class c_double_complex(_SwappableCData, _SimpleCData[complex]): + class c_double_complex(_SimpleCData[complex], _SwappableCData): _type_: ClassVar[Literal["D"]] - class c_float_complex(_SwappableCData, _SimpleCData[complex]): + class c_float_complex(_SimpleCData[complex], _SwappableCData): _type_: ClassVar[Literal["F"]] - class c_longdouble_complex(_SwappableCData, _SimpleCData[complex]): + class c_longdouble_complex(_SimpleCData[complex], _SwappableCData): _type_: ClassVar[Literal["G"]] -class c_char(_SwappableCData, _SimpleCData[bytes]): +class c_char(_SimpleCData[bytes], _SwappableCData): _type_: ClassVar[Literal["c"]] def __init__(self, value: int | bytes | bytearray = ...) -> None: ... From 3f3fe64188838d0b9d4e2f4b581e6be6bb2be3fa Mon Sep 17 00:00:00 2001 From: jorenham Date: Mon, 13 Apr 2026 09:45:29 +0200 Subject: [PATCH 3/3] `ctypes`: replace type-check-only mixin with direct `__dtype_{be,le}__` class attr declarations --- stdlib/ctypes/__init__.pyi | 103 ++++++++++++++++++++++++++----------- 1 file changed, 73 insertions(+), 30 deletions(-) diff --git a/stdlib/ctypes/__init__.pyi b/stdlib/ctypes/__init__.pyi index f4796370f504..b9ff85ef39f2 100644 --- a/stdlib/ctypes/__init__.pyi +++ b/stdlib/ctypes/__init__.pyi @@ -219,96 +219,139 @@ class py_object(_CanCastTo, _SimpleCData[_T]): if sys.version_info >= (3, 14): def __class_getitem__(cls, item: Any, /) -> GenericAlias: ... -@type_check_only -class _SwappableCData: +class c_bool(_SimpleCData[bool]): + _type_: ClassVar[Literal["?"]] __ctype_be__: ClassVar[type[Self]] __ctype_le__: ClassVar[type[Self]] - -class c_bool(_SimpleCData[bool], _SwappableCData): - _type_: ClassVar[Literal["?"]] def __init__(self, value: SupportsBool | SupportsLen | None = ...) -> None: ... -class c_byte(_SimpleCData[int], _SwappableCData): +class c_byte(_SimpleCData[int]): _type_: ClassVar[Literal["b"]] + __ctype_be__: ClassVar[type[Self]] + __ctype_le__: ClassVar[type[Self]] -class c_ubyte(_SimpleCData[int], _SwappableCData): +class c_ubyte(_SimpleCData[int]): _type_: ClassVar[Literal["B"]] + __ctype_be__: ClassVar[type[Self]] + __ctype_le__: ClassVar[type[Self]] -class c_short(_SimpleCData[int], _SwappableCData): +class c_short(_SimpleCData[int]): _type_: ClassVar[Literal["h"]] + __ctype_be__: ClassVar[type[Self]] + __ctype_le__: ClassVar[type[Self]] -class c_ushort(_SimpleCData[int], _SwappableCData): +class c_ushort(_SimpleCData[int]): _type_: ClassVar[Literal["H"]] + __ctype_be__: ClassVar[type[Self]] + __ctype_le__: ClassVar[type[Self]] -class c_long(_SimpleCData[int], _SwappableCData): +class c_long(_SimpleCData[int]): _type_: ClassVar[Literal["l"]] + __ctype_be__: ClassVar[type[Self]] + __ctype_le__: ClassVar[type[Self]] -class c_ulong(_SimpleCData[int], _SwappableCData): +class c_ulong(_SimpleCData[int]): _type_: ClassVar[Literal["L"]] + __ctype_be__: ClassVar[type[Self]] + __ctype_le__: ClassVar[type[Self]] -class c_int(_SimpleCData[int], _SwappableCData): # can be an alias for c_long +class c_int(_SimpleCData[int]): # can be an alias for c_long _type_: ClassVar[Literal["i", "l"]] + __ctype_be__: ClassVar[type[Self]] + __ctype_le__: ClassVar[type[Self]] -class c_uint(_SimpleCData[int], _SwappableCData): # can be an alias for c_ulong +class c_uint(_SimpleCData[int]): # can be an alias for c_ulong _type_: ClassVar[Literal["I", "L"]] + __ctype_be__: ClassVar[type[Self]] + __ctype_le__: ClassVar[type[Self]] -class c_longlong(_SimpleCData[int], _SwappableCData): # can be an alias for c_long +class c_longlong(_SimpleCData[int]): # can be an alias for c_long _type_: ClassVar[Literal["q", "l"]] + __ctype_be__: ClassVar[type[Self]] + __ctype_le__: ClassVar[type[Self]] -class c_ulonglong(_SimpleCData[int], _SwappableCData): # can be an alias for c_ulong +class c_ulonglong(_SimpleCData[int]): # can be an alias for c_ulong _type_: ClassVar[Literal["Q", "L"]] + __ctype_be__: ClassVar[type[Self]] + __ctype_le__: ClassVar[type[Self]] c_int8 = c_byte c_uint8 = c_ubyte -class c_int16(_SimpleCData[int], _SwappableCData): # can be an alias for c_short or c_int +class c_int16(_SimpleCData[int]): # can be an alias for c_short or c_int _type_: ClassVar[Literal["h", "i"]] + __ctype_be__: ClassVar[type[Self]] + __ctype_le__: ClassVar[type[Self]] -class c_uint16(_SimpleCData[int], _SwappableCData): # can be an alias for c_ushort or c_uint +class c_uint16(_SimpleCData[int]): # can be an alias for c_ushort or c_uint _type_: ClassVar[Literal["H", "I"]] + __ctype_be__: ClassVar[type[Self]] + __ctype_le__: ClassVar[type[Self]] -class c_int32(_SimpleCData[int], _SwappableCData): # can be an alias for c_int or c_long +class c_int32(_SimpleCData[int]): # can be an alias for c_int or c_long _type_: ClassVar[Literal["i", "l"]] + __ctype_be__: ClassVar[type[Self]] + __ctype_le__: ClassVar[type[Self]] -class c_uint32(_SimpleCData[int], _SwappableCData): # can be an alias for c_uint or c_ulong +class c_uint32(_SimpleCData[int]): # can be an alias for c_uint or c_ulong _type_: ClassVar[Literal["I", "L"]] + __ctype_be__: ClassVar[type[Self]] + __ctype_le__: ClassVar[type[Self]] -class c_int64(_SimpleCData[int], _SwappableCData): # can be an alias for c_long or c_longlong +class c_int64(_SimpleCData[int]): # can be an alias for c_long or c_longlong _type_: ClassVar[Literal["l", "q"]] + __ctype_be__: ClassVar[type[Self]] + __ctype_le__: ClassVar[type[Self]] -class c_uint64(_SimpleCData[int], _SwappableCData): # can be an alias for c_ulong or c_ulonglong +class c_uint64(_SimpleCData[int]): # can be an alias for c_ulong or c_ulonglong _type_: ClassVar[Literal["L", "Q"]] + __ctype_be__: ClassVar[type[Self]] + __ctype_le__: ClassVar[type[Self]] -class c_ssize_t(_SimpleCData[int], _SwappableCData): # alias for c_int, c_long, or c_longlong +class c_ssize_t(_SimpleCData[int]): # alias for c_int, c_long, or c_longlong _type_: ClassVar[Literal["i", "l", "q"]] + __ctype_be__: ClassVar[type[Self]] + __ctype_le__: ClassVar[type[Self]] -class c_size_t(_SimpleCData[int], _SwappableCData): # alias for c_uint, c_ulong, or c_ulonglong +class c_size_t(_SimpleCData[int]): # alias for c_uint, c_ulong, or c_ulonglong _type_: ClassVar[Literal["I", "L", "Q"]] + __ctype_be__: ClassVar[type[Self]] + __ctype_le__: ClassVar[type[Self]] -class c_float(_SimpleCData[float], _SwappableCData): +class c_float(_SimpleCData[float]): _type_: ClassVar[Literal["f"]] + __ctype_be__: ClassVar[type[Self]] + __ctype_le__: ClassVar[type[Self]] -class c_double(_SimpleCData[float], _SwappableCData): +class c_double(_SimpleCData[float]): _type_: ClassVar[Literal["d"]] + __ctype_be__: ClassVar[type[Self]] + __ctype_le__: ClassVar[type[Self]] -class c_longdouble(_SimpleCData[float], _SwappableCData): # can be an alias for c_double +class c_longdouble(_SimpleCData[float]): # can be an alias for c_double _type_: ClassVar[Literal["d", "g"]] if sys.version_info >= (3, 14) and sys.platform != "win32": # NOTE: currently (3.14.4) the `__ctype_{be,le}__` attributes of these complex types are missing at runtime: # https://github.com/python/cpython/issues/148464 - class c_double_complex(_SimpleCData[complex], _SwappableCData): + class c_double_complex(_SimpleCData[complex]): _type_: ClassVar[Literal["D"]] + __ctype_be__: ClassVar[type[Self]] + __ctype_le__: ClassVar[type[Self]] - class c_float_complex(_SimpleCData[complex], _SwappableCData): + class c_float_complex(_SimpleCData[complex]): _type_: ClassVar[Literal["F"]] + __ctype_be__: ClassVar[type[Self]] + __ctype_le__: ClassVar[type[Self]] - class c_longdouble_complex(_SimpleCData[complex], _SwappableCData): + class c_longdouble_complex(_SimpleCData[complex]): _type_: ClassVar[Literal["G"]] -class c_char(_SimpleCData[bytes], _SwappableCData): +class c_char(_SimpleCData[bytes]): _type_: ClassVar[Literal["c"]] + __ctype_be__: ClassVar[type[Self]] + __ctype_le__: ClassVar[type[Self]] def __init__(self, value: int | bytes | bytearray = ...) -> None: ... class c_char_p(_PointerLike, _SimpleCData[bytes | None]):