Various ctypes improvements (#11186)

Mostly more attention paid to which classes are actually the same class
This commit is contained in:
Stephen Morton
2024-01-30 22:18:00 -08:00
committed by GitHub
parent 8010e9fef0
commit 9877ed8092
4 changed files with 153 additions and 67 deletions

View File

@@ -2,7 +2,7 @@ import sys
from _typeshed import ReadableBuffer, WriteableBuffer
from abc import abstractmethod
from collections.abc import Callable, Iterable, Iterator, Mapping, Sequence
from ctypes import CDLL
from ctypes import CDLL, ArgumentError as ArgumentError
from typing import Any, ClassVar, Generic, TypeVar, overload
from typing_extensions import Self, TypeAlias
@@ -201,8 +201,6 @@ class Array(_CData, Generic[_CT]):
if sys.version_info >= (3, 9):
def __class_getitem__(cls, item: Any) -> GenericAlias: ...
class ArgumentError(Exception): ...
def addressof(obj: _CData) -> int: ...
def alignment(obj_or_type: _CData | type[_CData]) -> int: ...
def get_errno() -> int: ...

View File

@@ -3,7 +3,6 @@ from _ctypes import (
POINTER as POINTER,
RTLD_GLOBAL as RTLD_GLOBAL,
RTLD_LOCAL as RTLD_LOCAL,
ArgumentError as ArgumentError,
Array as Array,
CFuncPtr as _CFuncPtr,
Structure as Structure,
@@ -27,12 +26,16 @@ from _ctypes import (
set_errno as set_errno,
sizeof as sizeof,
)
from ctypes._endian import BigEndianStructure as BigEndianStructure, LittleEndianStructure as LittleEndianStructure
from typing import Any, ClassVar, Generic, TypeVar
from typing_extensions import TypeAlias
if sys.platform == "win32":
from _ctypes import FormatError as FormatError, get_last_error as get_last_error, set_last_error as set_last_error
if sys.version_info >= (3, 11):
from ctypes._endian import BigEndianUnion as BigEndianUnion, LittleEndianUnion as LittleEndianUnion
if sys.version_info >= (3, 9):
from types import GenericAlias
@@ -41,6 +44,8 @@ _DLLT = TypeVar("_DLLT", bound=CDLL)
DEFAULT_MODE: int
class ArgumentError(Exception): ...
class CDLL:
_func_flags_: ClassVar[int]
_func_restype_: ClassVar[_CData]
@@ -137,30 +142,36 @@ class c_char_p(_PointerLike, _SimpleCData[bytes | None]):
def __init__(self, value: int | bytes | None = ...) -> None: ...
class c_double(_SimpleCData[float]): ...
class c_longdouble(_SimpleCData[float]): ...
class c_longdouble(_SimpleCData[float]): ... # can be an alias for c_double
class c_float(_SimpleCData[float]): ...
class c_int(_SimpleCData[int]): ...
class c_int8(_SimpleCData[int]): ...
class c_int16(_SimpleCData[int]): ...
class c_int32(_SimpleCData[int]): ...
class c_int64(_SimpleCData[int]): ...
class c_int(_SimpleCData[int]): ... # can be an alias for c_long
class c_long(_SimpleCData[int]): ...
class c_longlong(_SimpleCData[int]): ...
class c_longlong(_SimpleCData[int]): ... # can be an alias for c_long
class c_short(_SimpleCData[int]): ...
class c_size_t(_SimpleCData[int]): ...
class c_ssize_t(_SimpleCData[int]): ...
class c_size_t(_SimpleCData[int]): ... # alias for c_uint, c_ulong, or c_ulonglong
class c_ssize_t(_SimpleCData[int]): ... # alias for c_int, c_long, or c_longlong
class c_ubyte(_SimpleCData[int]): ...
class c_uint(_SimpleCData[int]): ...
class c_uint8(_SimpleCData[int]): ...
class c_uint16(_SimpleCData[int]): ...
class c_uint32(_SimpleCData[int]): ...
class c_uint64(_SimpleCData[int]): ...
class c_uint(_SimpleCData[int]): ... # can be an alias for c_ulong
class c_ulong(_SimpleCData[int]): ...
class c_ulonglong(_SimpleCData[int]): ...
class c_ulonglong(_SimpleCData[int]): ... # can be an alias for c_ulong
class c_ushort(_SimpleCData[int]): ...
class c_void_p(_PointerLike, _SimpleCData[int | None]): ...
class c_wchar(_SimpleCData[str]): ...
c_int8 = c_byte
# these are actually dynamic aliases for c_short, c_int, c_long, or c_longlong
class c_int16(_SimpleCData[int]): ...
class c_int32(_SimpleCData[int]): ...
class c_int64(_SimpleCData[int]): ...
c_uint8 = c_ubyte
# these are actually dynamic aliases for c_ushort, c_uint, c_ulong, or c_ulonglong
class c_uint16(_SimpleCData[int]): ...
class c_uint32(_SimpleCData[int]): ...
class c_uint64(_SimpleCData[int]): ...
class c_wchar_p(_PointerLike, _SimpleCData[str | None]):
def __init__(self, value: int | str | None = ...) -> None: ...
@@ -171,8 +182,6 @@ if sys.platform == "win32":
class HRESULT(_SimpleCData[int]): ... # TODO undocumented
if sys.version_info >= (3, 12):
c_time_t: type[c_int32 | c_int64]
c_time_t: type[c_int32 | c_int64] # alias for one or the other at runtime
class py_object(_CanCastTo, _SimpleCData[_T]): ...
class BigEndianStructure(Structure): ...
class LittleEndianStructure(Structure): ...

19
stdlib/ctypes/_endian.pyi Normal file
View File

@@ -0,0 +1,19 @@
import sys
from _ctypes import RTLD_GLOBAL as RTLD_GLOBAL, RTLD_LOCAL as RTLD_LOCAL, Structure, Union
from ctypes import DEFAULT_MODE as DEFAULT_MODE, cdll as cdll, pydll as pydll, pythonapi as pythonapi
if sys.version_info >= (3, 12):
from _ctypes import SIZEOF_TIME_T as SIZEOF_TIME_T
if sys.platform == "win32":
from ctypes import oledll as oledll, windll as windll
# At runtime, the native endianness is an alias for Structure,
# while the other is a subclass with a metaclass added in.
class BigEndianStructure(Structure): ...
class LittleEndianStructure(Structure): ...
# Same thing for these: one is an alias of Union at runtime
if sys.version_info >= (3, 11):
class BigEndianUnion(Union): ...
class LittleEndianUnion(Union): ...

View File

@@ -186,53 +186,113 @@ class WIN32_FIND_DATAW(Structure):
cFileName: _CField[Array[WCHAR], str, str]
cAlternateFileName: _CField[Array[WCHAR], str, str]
class PBOOL(_Pointer[BOOL]): ...
class LPBOOL(_Pointer[BOOL]): ...
class PBOOLEAN(_Pointer[BOOLEAN]): ...
class PBYTE(_Pointer[BYTE]): ...
class LPBYTE(_Pointer[BYTE]): ...
class PCHAR(_Pointer[CHAR]): ...
class LPCOLORREF(_Pointer[COLORREF]): ...
class PDWORD(_Pointer[DWORD]): ...
class LPDWORD(_Pointer[DWORD]): ...
class PFILETIME(_Pointer[FILETIME]): ...
class LPFILETIME(_Pointer[FILETIME]): ...
class PFLOAT(_Pointer[FLOAT]): ...
class PHANDLE(_Pointer[HANDLE]): ...
class LPHANDLE(_Pointer[HANDLE]): ...
class PHKEY(_Pointer[HKEY]): ...
class LPHKL(_Pointer[HKL]): ...
class PINT(_Pointer[INT]): ...
class LPINT(_Pointer[INT]): ...
class PLARGE_INTEGER(_Pointer[LARGE_INTEGER]): ...
class PLCID(_Pointer[LCID]): ...
class PLONG(_Pointer[LONG]): ...
class LPLONG(_Pointer[LONG]): ...
class PMSG(_Pointer[MSG]): ...
class LPMSG(_Pointer[MSG]): ...
class PPOINT(_Pointer[POINT]): ...
class LPPOINT(_Pointer[POINT]): ...
class PPOINTL(_Pointer[POINTL]): ...
class PRECT(_Pointer[RECT]): ...
class LPRECT(_Pointer[RECT]): ...
class PRECTL(_Pointer[RECTL]): ...
class LPRECTL(_Pointer[RECTL]): ...
class LPSC_HANDLE(_Pointer[SC_HANDLE]): ...
# These are all defined with the POINTER() function, which keeps a cache and will
# return a previously created class if it can. The self-reported __name__
# of these classes is f"LP_{typ.__name__}", where typ is the original class
# passed in to the POINTER() function.
# LP_c_short
class PSHORT(_Pointer[SHORT]): ...
class PSIZE(_Pointer[SIZE]): ...
class LPSIZE(_Pointer[SIZE]): ...
class PSIZEL(_Pointer[SIZEL]): ...
class LPSIZEL(_Pointer[SIZEL]): ...
class PSMALL_RECT(_Pointer[SMALL_RECT]): ...
class PUINT(_Pointer[UINT]): ...
class LPUINT(_Pointer[UINT]): ...
class PULARGE_INTEGER(_Pointer[ULARGE_INTEGER]): ...
class PULONG(_Pointer[ULONG]): ...
# LP_c_ushort
class PUSHORT(_Pointer[USHORT]): ...
PWORD = PUSHORT
LPWORD = PUSHORT
# LP_c_long
class PLONG(_Pointer[LONG]): ...
LPLONG = PLONG
PBOOL = PLONG
LPBOOL = PLONG
# LP_c_ulong
class PULONG(_Pointer[ULONG]): ...
PDWORD = PULONG
LPDWORD = PDWORD
LPCOLORREF = PDWORD
PLCID = PDWORD
# LP_c_int (or LP_c_long if int and long have the same size)
class PINT(_Pointer[INT]): ...
LPINT = PINT
# LP_c_uint (or LP_c_ulong if int and long have the same size)
class PUINT(_Pointer[UINT]): ...
LPUINT = PUINT
# LP_c_float
class PFLOAT(_Pointer[FLOAT]): ...
# LP_c_longlong (or LP_c_long if long and long long have the same size)
class PLARGE_INTEGER(_Pointer[LARGE_INTEGER]): ...
# LP_c_ulonglong (or LP_c_ulong if long and long long have the same size)
class PULARGE_INTEGER(_Pointer[ULARGE_INTEGER]): ...
# LP_c_byte types
class PBYTE(_Pointer[BYTE]): ...
LPBYTE = PBYTE
PBOOLEAN = PBYTE
# LP_c_char
class PCHAR(_Pointer[CHAR]): ...
# LP_c_wchar
class PWCHAR(_Pointer[WCHAR]): ...
# LP_c_void_p
class PHANDLE(_Pointer[HANDLE]): ...
LPHANDLE = PHANDLE
PHKEY = PHANDLE
LPHKL = PHANDLE
LPSC_HANDLE = PHANDLE
# LP_FILETIME
class PFILETIME(_Pointer[FILETIME]): ...
LPFILETIME = PFILETIME
# LP_MSG
class PMSG(_Pointer[MSG]): ...
LPMSG = PMSG
# LP_POINT
class PPOINT(_Pointer[POINT]): ...
LPPOINT = PPOINT
PPOINTL = PPOINT
# LP_RECT
class PRECT(_Pointer[RECT]): ...
LPRECT = PRECT
PRECTL = PRECT
LPRECTL = PRECT
# LP_SIZE
class PSIZE(_Pointer[SIZE]): ...
LPSIZE = PSIZE
PSIZEL = PSIZE
LPSIZEL = PSIZE
# LP__SMALL_RECT
class PSMALL_RECT(_Pointer[SMALL_RECT]): ...
# LP_WIN32_FIND_DATAA
class PWIN32_FIND_DATAA(_Pointer[WIN32_FIND_DATAA]): ...
class LPWIN32_FIND_DATAA(_Pointer[WIN32_FIND_DATAA]): ...
LPWIN32_FIND_DATAA = PWIN32_FIND_DATAA
# LP_WIN32_FIND_DATAW
class PWIN32_FIND_DATAW(_Pointer[WIN32_FIND_DATAW]): ...
class LPWIN32_FIND_DATAW(_Pointer[WIN32_FIND_DATAW]): ...
class PWORD(_Pointer[WORD]): ...
class LPWORD(_Pointer[WORD]): ...
LPWIN32_FIND_DATAW = PWIN32_FIND_DATAW