-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Try to re-add stubs for ctypes #1906
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
+263
−0
Merged
Changes from all commits
Commits
Show all changes
32 commits
Select commit
Hold shift + click to select a range
acb456f
Revert "Delete ctypes. It is not yet ready for prime time, alas."
dgelessus acb3758
Convert type comments to variable annotations in ctypes.__init__
dgelessus 45ac1a7
Add missing List import in ctypes.__init__
dgelessus 38fabd0
Add missing bound kwarg to _CT TypeVar in ctypes.__init__
dgelessus 265a831
Fix ctypes._CData classmethod definitions
dgelessus 2bb0fe9
Fix ctypes Structure/Union __getattr__ definitions
dgelessus a73cd5e
Fix ctypes._CData classmethod definitions properly this time
dgelessus 8919823
Fix swapped parameter types in ctypes._CData.in_dll
dgelessus 0dc881a
Add limited support for ctypes._CData.__class__.__mul__
dgelessus ba2a9e5
Make ctypes._FuncPtr extend ctypes._CData
dgelessus aabc546
Improve typing of ctypes.cast
dgelessus 8841185
Mark class attributes with ClassVar in ctypes.__init__
dgelessus 0413982
Mark ctypes._CData.from_buffer[_copy] offset arg as optional
dgelessus 50e44c9
Remove trailing whitespace in ctypes.__init__
dgelessus 535a008
Don't export ctypes.UnionT
dgelessus aedd0d9
Add ctypes._DLL.__getitem__
dgelessus 2311ced
Make ctypes._DLL.__get(attr|item)__ return _FuncPtr instead of Any
dgelessus 854e22e
Change ctypes DLL inheritance hierarchy to match the real one better
dgelessus e765dec
Add some missing attributes to ctypes.CDLL
dgelessus 7a34b64
Rename ctypes._FuncPtr so it doesn't conflict with CDLL._FuncPtr
dgelessus 0619771
Fix type of ctypes.CDLL._FuncPtr
dgelessus 94a9853
Merge _FuncProto into _FuncPointer
dgelessus 1091074
Fix some leftover references to ctypes._DLL
dgelessus 253fc4a
Simplify definition of ctypes._DLLT
dgelessus cc3f49a
Add ctypes.LibraryLoader.__get(attr|item)__
dgelessus 7ff6017
Use Text instead of str where appropriate in ctypes.__init__
dgelessus 66a74a8
Make ctypes.c_char accept ints
dgelessus e5d1642
Make ctypes.c_[w]char_p accept None
dgelessus b81de47
Remove unneeded Generic base from ctypes.py_object
dgelessus a7507ea
Make ctypes.cast accept _cparam
dgelessus d8d431e
Fix ctypes._PF being declared too late
dgelessus a38f579
Remove incorrect ctypes.PyDLL.__init__ override
dgelessus File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,255 @@ | ||
# Stubs for ctypes | ||
|
||
from typing import ( | ||
Any, Callable, ClassVar, Iterable, List, Mapping, Optional, Sequence, Sized, Text, Tuple, Type, | ||
Generic, TypeVar, overload, | ||
) | ||
from typing import Union as _UnionT | ||
import sys | ||
|
||
_T = TypeVar('_T') | ||
_DLLT = TypeVar('_DLLT', bound=CDLL) | ||
_CT = TypeVar('_CT', bound=_CData) | ||
|
||
|
||
RTLD_GLOBAL: int = ... | ||
RTLD_LOCAL: int = ... | ||
DEFAULT_MODE: int = ... | ||
|
||
|
||
class CDLL(object): | ||
_func_flags_: ClassVar[int] = ... | ||
_func_restype_: ClassVar[_CData] = ... | ||
_name: str = ... | ||
_handle: int = ... | ||
_FuncPtr: Type[_FuncPointer] = ... | ||
def __init__(self, name: str, mode: int = ..., handle: Optional[int] = ..., | ||
use_errno: bool = ..., use_last_error: bool = ...) -> None: ... | ||
def __getattr__(self, name: str) -> _FuncPointer: ... | ||
def __getitem__(self, name: str) -> _FuncPointer: ... | ||
if sys.platform == 'win32': | ||
class OleDLL(CDLL): ... | ||
class WinDLL(CDLL): ... | ||
class PyDLL(CDLL): ... | ||
|
||
class LibraryLoader(Generic[_DLLT]): | ||
def __init__(self, dlltype: Type[_DLLT]) -> None: ... | ||
def __getattr__(self, name: str) -> _DLLT: ... | ||
def __getitem__(self, name: str) -> _DLLT: ... | ||
def LoadLibrary(self, name: str) -> _DLLT: ... | ||
|
||
cdll: LibraryLoader[CDLL] = ... | ||
if sys.platform == 'win32': | ||
windll: LibraryLoader[WinDLL] = ... | ||
oledll: LibraryLoader[OleDLL] = ... | ||
pydll: LibraryLoader[PyDLL] = ... | ||
pythonapi: PyDLL = ... | ||
|
||
class _CDataMeta(type): | ||
# TODO The return type is not accurate. The method definition *should* look like this: | ||
# def __mul__(cls: Type[_CT], other: int) -> Type[Array[_CT]]: ... | ||
# but that is not valid, because technically a _CDataMeta might not be a Type[_CT]. | ||
# This can never actually happen, because all _CDataMeta instances are _CData subclasses, but a typechecker doesn't know that. | ||
def __mul__(cls: _CDataMeta, other: int) -> Type[Array[_CT]]: ... | ||
def __rmul__(cls: _CDataMeta, other: int) -> Type[Array[_CT]]: ... | ||
class _CData(metaclass=_CDataMeta): | ||
_b_base: int = ... | ||
_b_needsfree_: bool = ... | ||
_objects: Optional[Mapping[Any, int]] = ... | ||
@classmethod | ||
def from_buffer(cls: Type[_CT], source: bytearray, offset: int = ...) -> _CT: ... | ||
@classmethod | ||
def from_buffer_copy(cls: Type[_CT], source: bytearray, offset: int = ...) -> _CT: ... | ||
@classmethod | ||
def from_address(cls: Type[_CT], address: int) -> _CT: ... | ||
@classmethod | ||
def from_param(cls: Type[_CT], obj: Any) -> _UnionT[_CT, _cparam]: ... | ||
@classmethod | ||
def in_dll(cls: Type[_CT], library: CDLL, name: str) -> _CT: ... | ||
|
||
class _PointerLike(_CData): pass | ||
|
||
_ECT = Callable[[Optional[Type[_CData]], | ||
_FuncPointer, | ||
Tuple[_CData, ...]], | ||
_CData] | ||
_PF = _UnionT[ | ||
Tuple[int], | ||
Tuple[int, str], | ||
Tuple[int, str, Any] | ||
] | ||
class _FuncPointer(_PointerLike, _CData): | ||
restype: _UnionT[Type[_CData], Callable[[int], None], None] = ... | ||
argtypes: Tuple[Type[_CData], ...] = ... | ||
errcheck: _ECT = ... | ||
@overload | ||
def __init__(self, address: int) -> None: ... | ||
@overload | ||
def __init__(self, callable: Callable[..., Any]) -> None: ... | ||
@overload | ||
def __init__(self, func_spec: Tuple[_UnionT[str, int], CDLL], | ||
paramflags: Tuple[_PF, ...] = ...) -> None: ... | ||
@overload | ||
def __init__(self, vtlb_index: int, name: str, | ||
paramflags: Tuple[_PF, ...] = ..., | ||
iid: _Pointer[c_int] = ...) -> None: ... | ||
def __call__(self, *args: Any, **kwargs: Any) -> Any: ... | ||
|
||
class ArgumentError(Exception): ... | ||
|
||
|
||
def CFUNCTYPE(restype: Type[_CData], | ||
*argtypes: Type[_CData], | ||
use_errno: bool = ..., | ||
use_last_error: bool = ...) -> Type[_FuncPointer]: ... | ||
if sys.platform == 'win32': | ||
def WINFUNCTYPE(restype: Type[_CData], | ||
*argtypes: Type[_CData], | ||
use_errno: bool = ..., | ||
use_last_error: bool = ...) -> Type[_FuncPointer]: ... | ||
def PYFUNCTYPE(restype: Type[_CData], | ||
*argtypes: Type[_CData]) -> Type[_FuncPointer]: ... | ||
|
||
class _cparam: ... | ||
|
||
def addressof(obj: _CData) -> int: ... | ||
def alignment(obj_or_type: _UnionT[_CData, Type[_CData]]) -> int: ... | ||
def byref(obj: _CData, offset: int = ...) -> _cparam: ... | ||
_PT = TypeVar('_PT', bound=_PointerLike) | ||
def cast(obj: _UnionT[_CData, _cparam], type: Type[_PT]) -> _PT: ... | ||
def create_string_buffer(init_or_size: _UnionT[int, bytes], | ||
size: Optional[int] = ...) -> Array[c_char]: ... | ||
c_buffer = create_string_buffer | ||
def create_unicode_buffer(init_or_size: _UnionT[int, Text], | ||
size: Optional[int] = ...) -> Array[c_wchar]: ... | ||
if sys.platform == 'win32': | ||
def DllCanUnloadNow() -> int: ... | ||
def DllGetClassObject(rclsid: Any, riid: Any, ppv: Any) -> int: ... # TODO not documented | ||
def FormatError(code: int) -> str: ... | ||
def GetLastError() -> int: ... | ||
def get_errno() -> int: ... | ||
if sys.platform == 'win32': | ||
def get_last_error() -> int: ... | ||
def memmove(dst: _UnionT[int, _CData], | ||
src: _UnionT[int, _CData], | ||
count: int) -> None: ... | ||
def memset(dst: _UnionT[int, _CData], | ||
c: int, count: int) -> None: ... | ||
def POINTER(type: Type[_CT]) -> Type[_Pointer[_CT]]: ... | ||
def pointer(obj: _CT) -> _Pointer[_CT]: ... | ||
def resize(obj: _CData, size: int) -> None: ... | ||
if sys.version_info < (3,): | ||
def set_conversion_mode(encoding: str, errors: str) -> Tuple[str, str]: ... | ||
def set_errno(value: int) -> int: ... | ||
if sys.platform == 'win32': | ||
def set_last_error(value: int) -> int: ... | ||
def sizeof(obj_or_type: _UnionT[_CData, Type[_CData]]) -> int: ... | ||
def string_at(address: int, size: int = ...) -> bytes: ... | ||
if sys.platform == 'win32': | ||
def WinError(code: Optional[int] = ..., | ||
desc: Optional[str] = ...) -> OSError: ... | ||
def wstring_at(address: int, size: int = ...) -> str: ... | ||
|
||
class _SimpleCData(Generic[_T], _CData): | ||
value: _T = ... | ||
def __init__(self, value: _T = ...) -> None: ... | ||
|
||
class c_byte(_SimpleCData[int]): ... | ||
|
||
class c_char(_SimpleCData[bytes]): | ||
def __init__(self, value: _UnionT[int, bytes] = ...) -> None: ... | ||
class c_char_p(_PointerLike, _SimpleCData[Optional[bytes]]): | ||
def __init__(self, value: Optional[_UnionT[int, bytes]] = ...) -> None: ... | ||
|
||
class c_double(_SimpleCData[float]): ... | ||
class c_longdouble(_SimpleCData[float]): ... | ||
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_long(_SimpleCData[int]): ... | ||
class c_longlong(_SimpleCData[int]): ... | ||
|
||
class c_short(_SimpleCData[int]): ... | ||
|
||
class c_size_t(_SimpleCData[int]): ... | ||
class c_ssize_t(_SimpleCData[int]): ... | ||
|
||
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_ulong(_SimpleCData[int]): ... | ||
class c_ulonglong(_SimpleCData[int]): ... | ||
|
||
class c_ushort(_SimpleCData[int]): ... | ||
|
||
class c_void_p(_PointerLike, _SimpleCData[Optional[int]]): ... | ||
|
||
class c_wchar(_SimpleCData[Text]): ... | ||
class c_wchar_p(_PointerLike, _SimpleCData[Optional[Text]]): | ||
def __init__(self, value: Optional[_UnionT[int, Text]] = ...) -> None: ... | ||
|
||
class c_bool(_SimpleCData[bool]): | ||
def __init__(self, value: bool) -> None: ... | ||
|
||
if sys.platform == 'win32': | ||
class HRESULT(_SimpleCData[Any]): ... # TODO undocumented | ||
|
||
class py_object(_SimpleCData[_T]): ... | ||
|
||
class _CField: | ||
offset: int = ... | ||
size: int = ... | ||
class _StructUnionMeta(_CDataMeta): | ||
_fields_: Sequence[_UnionT[Tuple[str, Type[_CData]], Tuple[str, Type[_CData], int]]] = ... | ||
_pack_: int = ... | ||
_anonymous_: Sequence[str] = ... | ||
def __getattr__(self, name: str) -> _CField: ... | ||
class _StructUnionBase(_CData, metaclass=_StructUnionMeta): | ||
def __init__(self, *args: Any, **kw: Any) -> None: ... | ||
def __getattr__(self, name: str) -> Any: ... | ||
def __setattr__(self, name: str, value: Any) -> None: ... | ||
|
||
class Union(_StructUnionBase): pass | ||
class Structure(_StructUnionBase): pass | ||
class BigEndianStructure(Structure): pass | ||
class LittleEndianStructure(Structure): pass | ||
|
||
class Array(Generic[_T], Sized, _CData): | ||
_length_: ClassVar[int] = ... | ||
_type_: ClassVar[Type[_T]] = ... | ||
raw: bytes = ... # TODO only available with _T == c_char | ||
value: bytes = ... # TODO only available with _T == c_char | ||
def __init__(self, *args: _T) -> None: ... | ||
@overload | ||
def __getitem__(self, i: int) -> _T: ... | ||
@overload | ||
def __getitem__(self, s: slice) -> List[_T]: ... | ||
@overload | ||
def __setitem__(self, i: int, o: _T) -> None: ... | ||
@overload | ||
def __setitem__(self, s: slice, o: Iterable[_T]) -> None: ... | ||
def __iter__(self) -> Iterable[_T]: ... | ||
|
||
|
||
class _Pointer(Generic[_T], _PointerLike, _CData): | ||
_type_: ClassVar[Type[_T]] = ... | ||
contents: _T = ... | ||
def __init__(self, arg: _T = ...) -> None: ... | ||
@overload | ||
def __getitem__(self, i: int) -> _T: ... | ||
@overload | ||
def __getitem__(self, s: slice) -> List[_T]: ... | ||
@overload | ||
def __setitem__(self, i: int, o: _T) -> None: ... | ||
@overload | ||
def __setitem__(self, s: slice, o: Iterable[_T]) -> None: ... |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
# Stubs for ctypes.util | ||
|
||
from typing import Optional | ||
import sys | ||
|
||
def find_library(name: str) -> Optional[str]: ... | ||
if sys.platform == 'win32': | ||
def find_msvcrt() -> Optional[str]: ... |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this be
bytes
notbytearray
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Both of the
bytearray
types are inadequate actually -from_buffer_copy
accepts any object that implements the buffer protocol, and similarlyfrom_buffer
accepts any writable buffer.bytearray
andbytes
are common examples of read-write and read-only buffer objects, but there are others likememoryview
andarray.array
. Allctypes
data objects (_CData
subclasses) are writable buffers as well.Does typeshed/
typing
have a type for "anything implementing the buffer protocol"? If not, we probably need to useUnion
s and list the most common stdlib buffer types.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can define a new protocol. I think there are already many examples in typeshed (grep for
Protocol
).There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, it is C-level, in this case looks like a big union is the only option.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't
bytes
already treated by mypy as anything implementing the buffer protocol?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is what the typing documentation says:
This should probably be added to PEP 484.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix here: #2610