mirror of
https://github.com/davidhalter/typeshed.git
synced 2025-12-09 21:46:42 +08:00
Move _SimpleCData and Array from ctypes/__init__.pyi to _ctypes.pyi (#10118)
This commit is contained in:
@@ -1,6 +1,16 @@
|
||||
import sys
|
||||
from ctypes import _CArgObject, _PointerLike
|
||||
from typing_extensions import TypeAlias
|
||||
from _typeshed import ReadableBuffer, WriteableBuffer
|
||||
from abc import abstractmethod
|
||||
from collections.abc import Iterable, Iterator, Mapping
|
||||
from ctypes import CDLL, _CArgObject, _PointerLike
|
||||
from typing import Any, Generic, TypeVar, overload
|
||||
from typing_extensions import Self, TypeAlias
|
||||
|
||||
if sys.version_info >= (3, 9):
|
||||
from types import GenericAlias
|
||||
|
||||
_T = TypeVar("_T")
|
||||
_CT = TypeVar("_CT", bound=_CData)
|
||||
|
||||
FUNCFLAG_CDECL: int
|
||||
FUNCFLAG_PYTHONAPI: int
|
||||
@@ -27,3 +37,76 @@ if sys.platform == "win32":
|
||||
|
||||
FUNCFLAG_HRESULT: int
|
||||
FUNCFLAG_STDCALL: int
|
||||
|
||||
class _CDataMeta(type):
|
||||
# By default mypy complains about the following two methods, because strictly speaking cls
|
||||
# might not be a Type[_CT]. However this can never actually happen, because the only class that
|
||||
# uses _CDataMeta as its metaclass is _CData. So it's safe to ignore the errors here.
|
||||
def __mul__(cls: type[_CT], other: int) -> type[Array[_CT]]: ... # type: ignore[misc] # pyright: ignore[reportGeneralTypeIssues]
|
||||
def __rmul__(cls: type[_CT], other: int) -> type[Array[_CT]]: ... # type: ignore[misc] # pyright: ignore[reportGeneralTypeIssues]
|
||||
|
||||
class _CData(metaclass=_CDataMeta):
|
||||
_b_base_: int
|
||||
_b_needsfree_: bool
|
||||
_objects: Mapping[Any, int] | None
|
||||
@classmethod
|
||||
def from_buffer(cls, source: WriteableBuffer, offset: int = ...) -> Self: ...
|
||||
@classmethod
|
||||
def from_buffer_copy(cls, source: ReadableBuffer, offset: int = ...) -> Self: ...
|
||||
@classmethod
|
||||
def from_address(cls, address: int) -> Self: ...
|
||||
@classmethod
|
||||
def from_param(cls, obj: Any) -> Self | _CArgObject: ...
|
||||
@classmethod
|
||||
def in_dll(cls, library: CDLL, name: str) -> Self: ...
|
||||
|
||||
class _SimpleCData(Generic[_T], _CData):
|
||||
value: _T
|
||||
# The TypeVar can be unsolved here,
|
||||
# but we can't use overloads without creating many, many mypy false-positive errors
|
||||
def __init__(self, value: _T = ...) -> None: ... # pyright: ignore[reportInvalidTypeVarUse]
|
||||
|
||||
class Array(Generic[_CT], _CData):
|
||||
@property
|
||||
@abstractmethod
|
||||
def _length_(self) -> int: ...
|
||||
@_length_.setter
|
||||
def _length_(self, value: int) -> None: ...
|
||||
@property
|
||||
@abstractmethod
|
||||
def _type_(self) -> type[_CT]: ...
|
||||
@_type_.setter
|
||||
def _type_(self, value: type[_CT]) -> None: ...
|
||||
# Note: only available if _CT == c_char
|
||||
@property
|
||||
def raw(self) -> bytes: ...
|
||||
@raw.setter
|
||||
def raw(self, value: ReadableBuffer) -> None: ...
|
||||
value: Any # Note: bytes if _CT == c_char, str if _CT == c_wchar, unavailable otherwise
|
||||
# TODO These methods cannot be annotated correctly at the moment.
|
||||
# All of these "Any"s stand for the array's element type, but it's not possible to use _CT
|
||||
# here, because of a special feature of ctypes.
|
||||
# By default, when accessing an element of an Array[_CT], the returned object has type _CT.
|
||||
# However, when _CT is a "simple type" like c_int, ctypes automatically "unboxes" the object
|
||||
# and converts it to the corresponding Python primitive. For example, when accessing an element
|
||||
# of an Array[c_int], a Python int object is returned, not a c_int.
|
||||
# This behavior does *not* apply to subclasses of "simple types".
|
||||
# If MyInt is a subclass of c_int, then accessing an element of an Array[MyInt] returns
|
||||
# a MyInt, not an int.
|
||||
# This special behavior is not easy to model in a stub, so for now all places where
|
||||
# the array element type would belong are annotated with Any instead.
|
||||
def __init__(self, *args: Any) -> None: ...
|
||||
@overload
|
||||
def __getitem__(self, __key: int) -> Any: ...
|
||||
@overload
|
||||
def __getitem__(self, __key: slice) -> list[Any]: ...
|
||||
@overload
|
||||
def __setitem__(self, __key: int, __value: Any) -> None: ...
|
||||
@overload
|
||||
def __setitem__(self, __key: slice, __value: Iterable[Any]) -> None: ...
|
||||
def __iter__(self) -> Iterator[Any]: ...
|
||||
# Can't inherit from Sized because the metaclass conflict between
|
||||
# Sized and _CData prevents using _CDataMeta.
|
||||
def __len__(self) -> int: ...
|
||||
if sys.version_info >= (3, 9):
|
||||
def __class_getitem__(cls, item: Any) -> GenericAlias: ...
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
import sys
|
||||
from _ctypes import RTLD_GLOBAL as RTLD_GLOBAL, RTLD_LOCAL as RTLD_LOCAL
|
||||
from _typeshed import ReadableBuffer, WriteableBuffer
|
||||
from abc import abstractmethod
|
||||
from collections.abc import Callable, Iterable, Iterator, Mapping, Sequence
|
||||
from _ctypes import (
|
||||
RTLD_GLOBAL as RTLD_GLOBAL,
|
||||
RTLD_LOCAL as RTLD_LOCAL,
|
||||
Array as Array,
|
||||
_CData as _CData,
|
||||
_CDataMeta as _CDataMeta,
|
||||
_SimpleCData as _SimpleCData,
|
||||
)
|
||||
from collections.abc import Callable, Sequence
|
||||
from typing import Any, ClassVar, Generic, TypeVar, overload
|
||||
from typing_extensions import Self, TypeAlias
|
||||
from typing_extensions import TypeAlias
|
||||
|
||||
if sys.version_info >= (3, 9):
|
||||
from types import GenericAlias
|
||||
@@ -65,28 +70,6 @@ if sys.platform == "win32":
|
||||
pydll: LibraryLoader[PyDLL]
|
||||
pythonapi: PyDLL
|
||||
|
||||
class _CDataMeta(type):
|
||||
# By default mypy complains about the following two methods, because strictly speaking cls
|
||||
# might not be a Type[_CT]. However this can never actually happen, because the only class that
|
||||
# uses _CDataMeta as its metaclass is _CData. So it's safe to ignore the errors here.
|
||||
def __mul__(cls: type[_CT], other: int) -> type[Array[_CT]]: ... # type: ignore[misc] # pyright: ignore[reportGeneralTypeIssues]
|
||||
def __rmul__(cls: type[_CT], other: int) -> type[Array[_CT]]: ... # type: ignore[misc] # pyright: ignore[reportGeneralTypeIssues]
|
||||
|
||||
class _CData(metaclass=_CDataMeta):
|
||||
_b_base_: int
|
||||
_b_needsfree_: bool
|
||||
_objects: Mapping[Any, int] | None
|
||||
@classmethod
|
||||
def from_buffer(cls, source: WriteableBuffer, offset: int = ...) -> Self: ...
|
||||
@classmethod
|
||||
def from_buffer_copy(cls, source: ReadableBuffer, offset: int = ...) -> Self: ...
|
||||
@classmethod
|
||||
def from_address(cls, address: int) -> Self: ...
|
||||
@classmethod
|
||||
def from_param(cls, obj: Any) -> Self | _CArgObject: ...
|
||||
@classmethod
|
||||
def in_dll(cls, library: CDLL, name: str) -> Self: ...
|
||||
|
||||
class _CanCastTo(_CData): ...
|
||||
class _PointerLike(_CanCastTo): ...
|
||||
|
||||
@@ -190,12 +173,6 @@ if sys.platform == "win32":
|
||||
|
||||
def wstring_at(address: _CVoidConstPLike, size: int = -1) -> str: ...
|
||||
|
||||
class _SimpleCData(Generic[_T], _CData):
|
||||
value: _T
|
||||
# The TypeVar can be unsolved here,
|
||||
# but we can't use overloads without creating many, many mypy false-positive errors
|
||||
def __init__(self, value: _T = ...) -> None: ... # pyright: ignore[reportInvalidTypeVarUse]
|
||||
|
||||
class c_byte(_SimpleCData[int]): ...
|
||||
|
||||
class c_char(_SimpleCData[bytes]):
|
||||
@@ -259,48 +236,3 @@ class Union(_StructUnionBase): ...
|
||||
class Structure(_StructUnionBase): ...
|
||||
class BigEndianStructure(Structure): ...
|
||||
class LittleEndianStructure(Structure): ...
|
||||
|
||||
class Array(Generic[_CT], _CData):
|
||||
@property
|
||||
@abstractmethod
|
||||
def _length_(self) -> int: ...
|
||||
@_length_.setter
|
||||
def _length_(self, value: int) -> None: ...
|
||||
@property
|
||||
@abstractmethod
|
||||
def _type_(self) -> type[_CT]: ...
|
||||
@_type_.setter
|
||||
def _type_(self, value: type[_CT]) -> None: ...
|
||||
# Note: only available if _CT == c_char
|
||||
@property
|
||||
def raw(self) -> bytes: ...
|
||||
@raw.setter
|
||||
def raw(self, value: ReadableBuffer) -> None: ...
|
||||
value: Any # Note: bytes if _CT == c_char, str if _CT == c_wchar, unavailable otherwise
|
||||
# TODO These methods cannot be annotated correctly at the moment.
|
||||
# All of these "Any"s stand for the array's element type, but it's not possible to use _CT
|
||||
# here, because of a special feature of ctypes.
|
||||
# By default, when accessing an element of an Array[_CT], the returned object has type _CT.
|
||||
# However, when _CT is a "simple type" like c_int, ctypes automatically "unboxes" the object
|
||||
# and converts it to the corresponding Python primitive. For example, when accessing an element
|
||||
# of an Array[c_int], a Python int object is returned, not a c_int.
|
||||
# This behavior does *not* apply to subclasses of "simple types".
|
||||
# If MyInt is a subclass of c_int, then accessing an element of an Array[MyInt] returns
|
||||
# a MyInt, not an int.
|
||||
# This special behavior is not easy to model in a stub, so for now all places where
|
||||
# the array element type would belong are annotated with Any instead.
|
||||
def __init__(self, *args: Any) -> None: ...
|
||||
@overload
|
||||
def __getitem__(self, __key: int) -> Any: ...
|
||||
@overload
|
||||
def __getitem__(self, __key: slice) -> list[Any]: ...
|
||||
@overload
|
||||
def __setitem__(self, __key: int, __value: Any) -> None: ...
|
||||
@overload
|
||||
def __setitem__(self, __key: slice, __value: Iterable[Any]) -> None: ...
|
||||
def __iter__(self) -> Iterator[Any]: ...
|
||||
# Can't inherit from Sized because the metaclass conflict between
|
||||
# Sized and _CData prevents using _CDataMeta.
|
||||
def __len__(self) -> int: ...
|
||||
if sys.version_info >= (3, 9):
|
||||
def __class_getitem__(cls, item: Any) -> GenericAlias: ...
|
||||
|
||||
@@ -78,7 +78,9 @@ csv.Dialect.skipinitialspace
|
||||
csv.DictReader.__init__ # runtime sig has *args but will error if more than 5 positional args are supplied
|
||||
csv.DictWriter.__init__ # runtime sig has *args but will error if more than 5 positional args are supplied
|
||||
ctypes.Array._type_ # _type_ and _length_ are abstract, https://github.com/python/typeshed/pull/6361
|
||||
_ctypes.Array._type_
|
||||
ctypes.Array._length_
|
||||
_ctypes.Array._length_
|
||||
ctypes.CDLL._FuncPtr # None at class level but initialized in __init__ to this value
|
||||
ctypes.memmove # CFunctionType
|
||||
ctypes.memset # CFunctionType
|
||||
@@ -332,7 +334,6 @@ turtle.ScrolledCanvas.onResize
|
||||
wave.Wave_read.initfp
|
||||
wave.Wave_write.initfp
|
||||
|
||||
_ctypes.Array
|
||||
_ctypes.CFuncPtr
|
||||
_ctypes.POINTER
|
||||
_ctypes.PyObj_FromPtr
|
||||
@@ -357,6 +358,7 @@ _ctypes.sizeof
|
||||
# ==========
|
||||
|
||||
ctypes.Array.raw # exists but stubtest can't see it; only available if _CT == c_char
|
||||
_ctypes.Array.raw
|
||||
|
||||
_collections_abc.AsyncGenerator.asend # async at runtime, deliberately not in the stub, see #7491. Pos-only differences also.
|
||||
_collections_abc.AsyncGenerator.__anext__ # async at runtime, deliberately not in the stub, see #7491
|
||||
@@ -605,6 +607,7 @@ wsgiref.handlers.BaseHandler.status
|
||||
|
||||
# Iterable classes that don't define __iter__ at runtime (usually iterable via __getitem__)
|
||||
# These would ideally be special-cased by type checkers; see https://github.com/python/mypy/issues/2220
|
||||
_ctypes.Array.__iter__
|
||||
ctypes.Array.__iter__
|
||||
mmap.mmap.__iter__
|
||||
mmap.mmap.__contains__
|
||||
|
||||
Reference in New Issue
Block a user