From acb456f17ca47361662238fbbf0c82de53e64b04 Mon Sep 17 00:00:00 2001 From: dgelessus Date: Tue, 20 Feb 2018 16:19:56 +0100 Subject: [PATCH 01/32] Revert "Delete ctypes. It is not yet ready for prime time, alas." This reverts commit 73bdb705bfa8a5701f62032f4ec925f061918715. --- stdlib/2and3/ctypes/__init__.pyi | 246 +++++++++++++++++++++++++++++++ stdlib/2and3/ctypes/util.pyi | 8 + 2 files changed, 254 insertions(+) create mode 100644 stdlib/2and3/ctypes/__init__.pyi create mode 100644 stdlib/2and3/ctypes/util.pyi diff --git a/stdlib/2and3/ctypes/__init__.pyi b/stdlib/2and3/ctypes/__init__.pyi new file mode 100644 index 000000000000..f50bf8779f78 --- /dev/null +++ b/stdlib/2and3/ctypes/__init__.pyi @@ -0,0 +1,246 @@ +# Stubs for ctypes + +from typing import ( + Any, Callable, Iterable, Mapping, Optional, Sequence, Sized, Tuple, Type, + Generic, TypeVar, overload, +) +from typing import Union as UnionT +import sys + +_T = TypeVar('_T') +if sys.platform == 'win32': + _DLLT = TypeVar('_DLLT', CDLL, OleDLL, WinDLL, PyDLL) +else: + _DLLT = TypeVar('_DLLT', CDLL, PyDLL) +_CT = TypeVar('_CT', _CData) + + +RTLD_GLOBAL = ... # type: int +RTLD_LOCAL = ... # type: int +DEFAULT_MODE = ... # type: int + + +class _DLL: + def __init__(self, name: str, mode: int = ..., handle: Optional[int] = ..., + use_errno: bool = ..., use_last_error: bool = ...) -> None: ... + def __getattr__(self, name: str) -> Any: ... +class CDLL(_DLL): ... +if sys.platform == 'win32': + class OleDLL(_DLL): ... + class WinDLL(_DLL): ... +class PyDLL(_DLL): + _handle = ... # type: int + _name = ... # type: str + def __init__(self, name: str, mode: int = ..., + handle: Optional[int] = ...) -> None: ... + +class LibraryLoader(Generic[_DLLT]): + def __init__(self, dlltype: Type[_DLLT]) -> None: ... + def LoadLibrary(self, name: str) -> _DLLT: ... + +cdll = ... # type: LibraryLoader[CDLL] +if sys.platform == 'win32': + windll = ... # type: LibraryLoader[WinDLL] + oledll = ... # type: LibraryLoader[OleDLL] +pydll = ... # type: LibraryLoader[PyDLL] +pythonapi = ... # type: PyDLL + + +_ECT = Callable[[Optional[Type[_CData]], + _FuncPtr, + Tuple[_CData, ...]], + _CData] +class _FuncPtr: + restype = ... # type: UnionT[Type[_CData], Callable[[int], None], None] + argtypes = ... # type: Tuple[Type[_CData], ...] + errcheck = ... # type: _ECT + 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[_FuncProto]: ... +if sys.platform == 'win32': + def WINFUNCTYPE(restype: Type[_CData], + *argtypes: Type[_CData], + use_errno: bool = ..., + use_last_error: bool = ...) -> Type[_FuncProto]: ... +def PYFUNCTYPE(restype: Type[_CData], + *argtypes: Type[_CData]) -> Type[_FuncProto]: ... + +_PF = UnionT[ + Tuple[int], + Tuple[int, str], + Tuple[int, str, Any] +] + +class _FuncProto(_FuncPtr): + @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], _DLL], + paramflags: Tuple[_PF, ...] = ...) -> None: ... + @overload + def __init__(self, vtlb_index: int, name: str, + paramflags: Tuple[_PF, ...] = ..., + iid: _Pointer[c_int] = ...) -> None: ... + +class _cparam: ... + +def addressof(obj: _CData) -> int: ... +def alignment(obj_or_type: UnionT[_CData, Type[_CData]]) -> int: ... +def byref(obj: _CData, offset: int = ...) -> _cparam: ... +def cast(obj: _CData, type: Type[_Pointer[Any]]) -> _CData: ... +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, str], + 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 _CData: + _b_base = ... # type: int + _b_needsfree_ = ... # type: bool + _objects = ... # type: Optional[Mapping[Any, int]] + def from_buffer(self, source: bytearray, offset: int) -> _CData: ... + def from_buffer_copy(self, source: bytearray, offset: int) -> _CData: ... + def from_address(self, address: int) -> _CData: ... + def from_param(self, obj: Any) -> UnionT[_CData, _cparam]: ... + def in_dll(self, library: str, name: _DLL) -> _CData: ... + + +class _SimpleCData(Generic[_T], _CData): + value = ... # type: _T + def __init__(self, value: _T = ...) -> None: ... + +class c_byte(_SimpleCData[int]): ... + +class c_char(_SimpleCData[bytes]): ... +class c_char_p(_SimpleCData[Optional[bytes]]): + def __init__(self, value: 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(_SimpleCData[Optional[int]]): ... + +class c_wchar(_SimpleCData[str]): ... +class c_wchar_p(_SimpleCData[Optional[str]]): + def __init__(self, value: UnionT[int, str] = ...) -> 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(Generic[_T], _SimpleCData[_T]): ... + + +class Union: + def __init__(self, *args: Any, **kw: Any) -> None: ... + +class BigEndianStructure: + def __init__(self, *args: Any, **kw: Any) -> None: ... + +class LittleEndianStructure: + def __init__(self, *args: Any, **kw: Any) -> None: ... + +class Structure(_CData): + _fields_ = ... # type: Sequence[UnionT[Tuple[str, Type[_CData]], Tuple[str, Type[_CData], int]]] + _pack_ = ... # type: int + _anonymous_ = ... # type: Sequence[str] + def __init__(self, *args: Any, **kw: Any) -> None: ... + def __getattr__(self, name: str) -> Any: ... # TODO should be a classmethod + def __setattr__(self, name: str, value: Any) -> None: ... + + +class Array(Generic[_T], Sized, _CData): + _length_ = ... # type: int + _type_ = ... # type: Type[_T] + raw = ... # type: bytes # TODO only available with _T == c_char + value = ... # type: 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], _CData): + _type_ = ... # type: Type[_T] + contents = ... # type: _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: ... diff --git a/stdlib/2and3/ctypes/util.pyi b/stdlib/2and3/ctypes/util.pyi new file mode 100644 index 000000000000..7077d9d2f1e9 --- /dev/null +++ b/stdlib/2and3/ctypes/util.pyi @@ -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]: ... From acb3758e4091ce843aeff3ef3ab97ec86bac5eb4 Mon Sep 17 00:00:00 2001 From: dgelessus Date: Tue, 20 Feb 2018 16:27:46 +0100 Subject: [PATCH 02/32] Convert type comments to variable annotations in ctypes.__init__ --- stdlib/2and3/ctypes/__init__.pyi | 53 ++++++++++++++++---------------- 1 file changed, 26 insertions(+), 27 deletions(-) diff --git a/stdlib/2and3/ctypes/__init__.pyi b/stdlib/2and3/ctypes/__init__.pyi index f50bf8779f78..d0edc00afb94 100644 --- a/stdlib/2and3/ctypes/__init__.pyi +++ b/stdlib/2and3/ctypes/__init__.pyi @@ -15,9 +15,9 @@ else: _CT = TypeVar('_CT', _CData) -RTLD_GLOBAL = ... # type: int -RTLD_LOCAL = ... # type: int -DEFAULT_MODE = ... # type: int +RTLD_GLOBAL: int = ... +RTLD_LOCAL: int = ... +DEFAULT_MODE: int = ... class _DLL: @@ -29,8 +29,8 @@ if sys.platform == 'win32': class OleDLL(_DLL): ... class WinDLL(_DLL): ... class PyDLL(_DLL): - _handle = ... # type: int - _name = ... # type: str + _handle: int = ... + _name: str = ... def __init__(self, name: str, mode: int = ..., handle: Optional[int] = ...) -> None: ... @@ -38,22 +38,21 @@ class LibraryLoader(Generic[_DLLT]): def __init__(self, dlltype: Type[_DLLT]) -> None: ... def LoadLibrary(self, name: str) -> _DLLT: ... -cdll = ... # type: LibraryLoader[CDLL] +cdll: LibraryLoader[CDLL] = ... if sys.platform == 'win32': - windll = ... # type: LibraryLoader[WinDLL] - oledll = ... # type: LibraryLoader[OleDLL] -pydll = ... # type: LibraryLoader[PyDLL] -pythonapi = ... # type: PyDLL - + windll: LibraryLoader[WinDLL] = ... + oledll: LibraryLoader[OleDLL] = ... +pydll: LibraryLoader[PyDLL] = ... +pythonapi: PyDLL = ... _ECT = Callable[[Optional[Type[_CData]], _FuncPtr, Tuple[_CData, ...]], _CData] class _FuncPtr: - restype = ... # type: UnionT[Type[_CData], Callable[[int], None], None] - argtypes = ... # type: Tuple[Type[_CData], ...] - errcheck = ... # type: _ECT + restype: UnionT[Type[_CData], Callable[[int], None], None] = ... + argtypes: Tuple[Type[_CData], ...] = ... + errcheck: _ECT = ... def __call__(self, *args: Any, **kwargs: Any) -> Any: ... class ArgumentError(Exception): ... @@ -131,9 +130,9 @@ def wstring_at(address: int, size: int = ...) -> str: ... class _CData: - _b_base = ... # type: int - _b_needsfree_ = ... # type: bool - _objects = ... # type: Optional[Mapping[Any, int]] + _b_base: int = ... + _b_needsfree_: bool = ... + _objects: Optional[Mapping[Any, int]] = ... def from_buffer(self, source: bytearray, offset: int) -> _CData: ... def from_buffer_copy(self, source: bytearray, offset: int) -> _CData: ... def from_address(self, address: int) -> _CData: ... @@ -142,7 +141,7 @@ class _CData: class _SimpleCData(Generic[_T], _CData): - value = ... # type: _T + value: _T = ... def __init__(self, value: _T = ...) -> None: ... class c_byte(_SimpleCData[int]): ... @@ -207,19 +206,19 @@ class LittleEndianStructure: def __init__(self, *args: Any, **kw: Any) -> None: ... class Structure(_CData): - _fields_ = ... # type: Sequence[UnionT[Tuple[str, Type[_CData]], Tuple[str, Type[_CData], int]]] - _pack_ = ... # type: int - _anonymous_ = ... # type: Sequence[str] + _fields_: Sequence[UnionT[Tuple[str, Type[_CData]], Tuple[str, Type[_CData], int]]] = ... + _pack_: int = ... + _anonymous_: Sequence[str] = ... def __init__(self, *args: Any, **kw: Any) -> None: ... def __getattr__(self, name: str) -> Any: ... # TODO should be a classmethod def __setattr__(self, name: str, value: Any) -> None: ... class Array(Generic[_T], Sized, _CData): - _length_ = ... # type: int - _type_ = ... # type: Type[_T] - raw = ... # type: bytes # TODO only available with _T == c_char - value = ... # type: bytes # TODO only available with _T == c_char + _length_: int = ... + _type_: 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: ... @@ -233,8 +232,8 @@ class Array(Generic[_T], Sized, _CData): class _Pointer(Generic[_T], _CData): - _type_ = ... # type: Type[_T] - contents = ... # type: _T + _type_: Type[_T] = ... + contents: _T = ... def __init__(self, arg: _T = ...) -> None: ... @overload def __getitem__(self, i: int) -> _T: ... From 45ac1a7b1dc84287dfa03814508c2f376a7bcd32 Mon Sep 17 00:00:00 2001 From: dgelessus Date: Tue, 20 Feb 2018 16:28:23 +0100 Subject: [PATCH 03/32] Add missing List import in ctypes.__init__ --- stdlib/2and3/ctypes/__init__.pyi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/2and3/ctypes/__init__.pyi b/stdlib/2and3/ctypes/__init__.pyi index d0edc00afb94..f4c46e0c42e5 100644 --- a/stdlib/2and3/ctypes/__init__.pyi +++ b/stdlib/2and3/ctypes/__init__.pyi @@ -1,7 +1,7 @@ # Stubs for ctypes from typing import ( - Any, Callable, Iterable, Mapping, Optional, Sequence, Sized, Tuple, Type, + Any, Callable, Iterable, List, Mapping, Optional, Sequence, Sized, Tuple, Type, Generic, TypeVar, overload, ) from typing import Union as UnionT From 38fabd0d0cb857c5487baba41608bd5cfa559a44 Mon Sep 17 00:00:00 2001 From: dgelessus Date: Tue, 20 Feb 2018 16:31:47 +0100 Subject: [PATCH 04/32] Add missing bound kwarg to _CT TypeVar in ctypes.__init__ --- stdlib/2and3/ctypes/__init__.pyi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/2and3/ctypes/__init__.pyi b/stdlib/2and3/ctypes/__init__.pyi index f4c46e0c42e5..ec302872828f 100644 --- a/stdlib/2and3/ctypes/__init__.pyi +++ b/stdlib/2and3/ctypes/__init__.pyi @@ -12,7 +12,7 @@ if sys.platform == 'win32': _DLLT = TypeVar('_DLLT', CDLL, OleDLL, WinDLL, PyDLL) else: _DLLT = TypeVar('_DLLT', CDLL, PyDLL) -_CT = TypeVar('_CT', _CData) +_CT = TypeVar('_CT', bound=_CData) RTLD_GLOBAL: int = ... From 265a831df3d4872c7be0cbfadd6187c54da6ea79 Mon Sep 17 00:00:00 2001 From: dgelessus Date: Tue, 20 Feb 2018 16:50:06 +0100 Subject: [PATCH 05/32] Fix ctypes._CData classmethod definitions --- stdlib/2and3/ctypes/__init__.pyi | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/stdlib/2and3/ctypes/__init__.pyi b/stdlib/2and3/ctypes/__init__.pyi index ec302872828f..7caf35e18f96 100644 --- a/stdlib/2and3/ctypes/__init__.pyi +++ b/stdlib/2and3/ctypes/__init__.pyi @@ -13,6 +13,7 @@ if sys.platform == 'win32': else: _DLLT = TypeVar('_DLLT', CDLL, PyDLL) _CT = TypeVar('_CT', bound=_CData) +_CTT = TypeVar('_CTT', bound=Type[_CData]) RTLD_GLOBAL: int = ... @@ -133,11 +134,16 @@ class _CData: _b_base: int = ... _b_needsfree_: bool = ... _objects: Optional[Mapping[Any, int]] = ... - def from_buffer(self, source: bytearray, offset: int) -> _CData: ... - def from_buffer_copy(self, source: bytearray, offset: int) -> _CData: ... - def from_address(self, address: int) -> _CData: ... - def from_param(self, obj: Any) -> UnionT[_CData, _cparam]: ... - def in_dll(self, library: str, name: _DLL) -> _CData: ... + @classmethod + def from_buffer(cls: _CTT, source: bytearray, offset: int) -> _CTT: ... + @classmethod + def from_buffer_copy(cls: _CTT, source: bytearray, offset: int) -> _CTT: ... + @classmethod + def from_address(cls: _CTT, address: int) -> _CTT: ... + @classmethod + def from_param(cls: _CTT, obj: Any) -> UnionT[_CTT, _cparam]: ... + @classmethod + def in_dll(cls: _CTT, library: str, name: _DLL) -> _CTT: ... class _SimpleCData(Generic[_T], _CData): From 2bb0fe9015e05f0bc58d21db33e83d632b4c92be Mon Sep 17 00:00:00 2001 From: dgelessus Date: Tue, 20 Feb 2018 16:59:34 +0100 Subject: [PATCH 06/32] Fix ctypes Structure/Union __getattr__ definitions Both Structure's metaclass and Structure itself define a __getattr__. The former returns field objects (each representing a field definition in the Structure), while the latter can return anything (the value of the field in a specific Structure instance). Structure also defines a __setattr__, while Structure's metaclass does not. BigEndianStructure, LittleEndianStructure and Union support the same operations as Structure does, but the semantics obviously differ. Depending on the system endianness, exactly one of the EndianStructures is an alias for Structure, and the other one is a special Structure subclass. For simplicity, both EndianStructures are considered subclasses of Structure here, even though this is technically not always accurate. --- stdlib/2and3/ctypes/__init__.pyi | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/stdlib/2and3/ctypes/__init__.pyi b/stdlib/2and3/ctypes/__init__.pyi index 7caf35e18f96..e98445e7d625 100644 --- a/stdlib/2and3/ctypes/__init__.pyi +++ b/stdlib/2and3/ctypes/__init__.pyi @@ -201,24 +201,23 @@ if sys.platform == 'win32': class py_object(Generic[_T], _SimpleCData[_T]): ... - -class Union: - def __init__(self, *args: Any, **kw: Any) -> None: ... - -class BigEndianStructure: - def __init__(self, *args: Any, **kw: Any) -> None: ... - -class LittleEndianStructure: - def __init__(self, *args: Any, **kw: Any) -> None: ... - -class Structure(_CData): +class _CField: + offset: int = ... + size: int = ... +class _StructUnionMeta(type): _fields_: Sequence[UnionT[Tuple[str, Type[_CData]], Tuple[str, Type[_CData], int]]] = ... _pack_: int = ... - _anonymous_: Sequence[str] = ... + _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: ... # TODO should be a classmethod + 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_: int = ... From a73cd5e47a0890519539fefc09fbfdd65bcdec35 Mon Sep 17 00:00:00 2001 From: dgelessus Date: Tue, 20 Feb 2018 19:23:36 +0100 Subject: [PATCH 07/32] Fix ctypes._CData classmethod definitions properly this time The classmethods return *instances* of the class of course, not the class itself. --- stdlib/2and3/ctypes/__init__.pyi | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/stdlib/2and3/ctypes/__init__.pyi b/stdlib/2and3/ctypes/__init__.pyi index e98445e7d625..e963185ac814 100644 --- a/stdlib/2and3/ctypes/__init__.pyi +++ b/stdlib/2and3/ctypes/__init__.pyi @@ -13,7 +13,6 @@ if sys.platform == 'win32': else: _DLLT = TypeVar('_DLLT', CDLL, PyDLL) _CT = TypeVar('_CT', bound=_CData) -_CTT = TypeVar('_CTT', bound=Type[_CData]) RTLD_GLOBAL: int = ... @@ -135,15 +134,15 @@ class _CData: _b_needsfree_: bool = ... _objects: Optional[Mapping[Any, int]] = ... @classmethod - def from_buffer(cls: _CTT, source: bytearray, offset: int) -> _CTT: ... + def from_buffer(cls: Type[_CT], source: bytearray, offset: int) -> _CT: ... @classmethod - def from_buffer_copy(cls: _CTT, source: bytearray, offset: int) -> _CTT: ... + def from_buffer_copy(cls: Type[_CT], source: bytearray, offset: int) -> _CT: ... @classmethod - def from_address(cls: _CTT, address: int) -> _CTT: ... + def from_address(cls: Type[_CT], address: int) -> _CT: ... @classmethod - def from_param(cls: _CTT, obj: Any) -> UnionT[_CTT, _cparam]: ... + def from_param(cls: Type[_CT], obj: Any) -> UnionT[_CT, _cparam]: ... @classmethod - def in_dll(cls: _CTT, library: str, name: _DLL) -> _CTT: ... + def in_dll(cls: Type[_CT], library: str, name: _DLL) -> _CT: ... class _SimpleCData(Generic[_T], _CData): From 891982300ab00da937d2c03e561d6da7f709dc59 Mon Sep 17 00:00:00 2001 From: dgelessus Date: Tue, 20 Feb 2018 19:25:04 +0100 Subject: [PATCH 08/32] Fix swapped parameter types in ctypes._CData.in_dll --- stdlib/2and3/ctypes/__init__.pyi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/2and3/ctypes/__init__.pyi b/stdlib/2and3/ctypes/__init__.pyi index e963185ac814..e4970a165a4f 100644 --- a/stdlib/2and3/ctypes/__init__.pyi +++ b/stdlib/2and3/ctypes/__init__.pyi @@ -142,7 +142,7 @@ class _CData: @classmethod def from_param(cls: Type[_CT], obj: Any) -> UnionT[_CT, _cparam]: ... @classmethod - def in_dll(cls: Type[_CT], library: str, name: _DLL) -> _CT: ... + def in_dll(cls: Type[_CT], library: _DLL, name: str) -> _CT: ... class _SimpleCData(Generic[_T], _CData): From 0dc881afe3cc613e2af9f5b2c1582e484486f3de Mon Sep 17 00:00:00 2001 From: dgelessus Date: Tue, 20 Feb 2018 19:54:50 +0100 Subject: [PATCH 09/32] Add limited support for ctypes._CData.__class__.__mul__ It's not possible to specify the correct return type for __mul__ and __rmul__ here - see comments for explanation. --- stdlib/2and3/ctypes/__init__.pyi | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/stdlib/2and3/ctypes/__init__.pyi b/stdlib/2and3/ctypes/__init__.pyi index e4970a165a4f..111bde3b2a41 100644 --- a/stdlib/2and3/ctypes/__init__.pyi +++ b/stdlib/2and3/ctypes/__init__.pyi @@ -129,7 +129,14 @@ if sys.platform == 'win32': def wstring_at(address: int, size: int = ...) -> str: ... -class _CData: +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]] = ... @@ -203,7 +210,7 @@ class py_object(Generic[_T], _SimpleCData[_T]): ... class _CField: offset: int = ... size: int = ... -class _StructUnionMeta(type): +class _StructUnionMeta(_CDataMeta): _fields_: Sequence[UnionT[Tuple[str, Type[_CData]], Tuple[str, Type[_CData], int]]] = ... _pack_: int = ... _anonymous_: Sequence[str] = ... From ba2a9e5ff3a5e7b799b2511a1e0416e09899f883 Mon Sep 17 00:00:00 2001 From: dgelessus Date: Tue, 20 Feb 2018 21:42:02 +0100 Subject: [PATCH 10/32] Make ctypes._FuncPtr extend ctypes._CData --- stdlib/2and3/ctypes/__init__.pyi | 48 +++++++++++++++----------------- 1 file changed, 23 insertions(+), 25 deletions(-) diff --git a/stdlib/2and3/ctypes/__init__.pyi b/stdlib/2and3/ctypes/__init__.pyi index 111bde3b2a41..e648b8aff282 100644 --- a/stdlib/2and3/ctypes/__init__.pyi +++ b/stdlib/2and3/ctypes/__init__.pyi @@ -45,11 +45,33 @@ if sys.platform == 'win32': 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: _DLL, name: str) -> _CT: ... + _ECT = Callable[[Optional[Type[_CData]], _FuncPtr, Tuple[_CData, ...]], _CData] -class _FuncPtr: +class _FuncPtr(_CData): restype: UnionT[Type[_CData], Callable[[int], None], None] = ... argtypes: Tuple[Type[_CData], ...] = ... errcheck: _ECT = ... @@ -128,30 +150,6 @@ if sys.platform == 'win32': desc: Optional[str] = ...) -> OSError: ... def wstring_at(address: int, size: int = ...) -> str: ... - -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: _DLL, name: str) -> _CT: ... - - class _SimpleCData(Generic[_T], _CData): value: _T = ... def __init__(self, value: _T = ...) -> None: ... From aabc54639a544e321b6ab0b900de1fff324e3ddd Mon Sep 17 00:00:00 2001 From: dgelessus Date: Tue, 20 Feb 2018 22:01:05 +0100 Subject: [PATCH 11/32] Improve typing of ctypes.cast --- stdlib/2and3/ctypes/__init__.pyi | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/stdlib/2and3/ctypes/__init__.pyi b/stdlib/2and3/ctypes/__init__.pyi index e648b8aff282..13a9b950595c 100644 --- a/stdlib/2and3/ctypes/__init__.pyi +++ b/stdlib/2and3/ctypes/__init__.pyi @@ -67,11 +67,13 @@ class _CData(metaclass=_CDataMeta): @classmethod def in_dll(cls: Type[_CT], library: _DLL, name: str) -> _CT: ... +class _PointerLike(_CData): pass + _ECT = Callable[[Optional[Type[_CData]], _FuncPtr, Tuple[_CData, ...]], _CData] -class _FuncPtr(_CData): +class _FuncPtr(_PointerLike, _CData): restype: UnionT[Type[_CData], Callable[[int], None], None] = ... argtypes: Tuple[Type[_CData], ...] = ... errcheck: _ECT = ... @@ -116,7 +118,8 @@ class _cparam: ... def addressof(obj: _CData) -> int: ... def alignment(obj_or_type: UnionT[_CData, Type[_CData]]) -> int: ... def byref(obj: _CData, offset: int = ...) -> _cparam: ... -def cast(obj: _CData, type: Type[_Pointer[Any]]) -> _CData: ... +_PT = TypeVar('_PT', bound=_PointerLike) +def cast(obj: _CData, 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 @@ -157,7 +160,7 @@ class _SimpleCData(Generic[_T], _CData): class c_byte(_SimpleCData[int]): ... class c_char(_SimpleCData[bytes]): ... -class c_char_p(_SimpleCData[Optional[bytes]]): +class c_char_p(_PointerLike, _SimpleCData[Optional[bytes]]): def __init__(self, value: UnionT[int, bytes] = ...) -> None: ... class c_double(_SimpleCData[float]): ... @@ -191,10 +194,10 @@ class c_ulonglong(_SimpleCData[int]): ... class c_ushort(_SimpleCData[int]): ... -class c_void_p(_SimpleCData[Optional[int]]): ... +class c_void_p(_PointerLike, _SimpleCData[Optional[int]]): ... class c_wchar(_SimpleCData[str]): ... -class c_wchar_p(_SimpleCData[Optional[str]]): +class c_wchar_p(_PointerLike, _SimpleCData[Optional[str]]): def __init__(self, value: UnionT[int, str] = ...) -> None: ... class c_bool(_SimpleCData[bool]): @@ -240,7 +243,7 @@ class Array(Generic[_T], Sized, _CData): def __iter__(self) -> Iterable[_T]: ... -class _Pointer(Generic[_T], _CData): +class _Pointer(Generic[_T], _PointerLike, _CData): _type_: Type[_T] = ... contents: _T = ... def __init__(self, arg: _T = ...) -> None: ... From 88411852cd2c5b5a91cee7a319715978c386c750 Mon Sep 17 00:00:00 2001 From: dgelessus Date: Tue, 20 Feb 2018 23:12:15 +0100 Subject: [PATCH 12/32] Mark class attributes with ClassVar in ctypes.__init__ --- stdlib/2and3/ctypes/__init__.pyi | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/stdlib/2and3/ctypes/__init__.pyi b/stdlib/2and3/ctypes/__init__.pyi index 13a9b950595c..5a7a757efa03 100644 --- a/stdlib/2and3/ctypes/__init__.pyi +++ b/stdlib/2and3/ctypes/__init__.pyi @@ -1,7 +1,7 @@ # Stubs for ctypes from typing import ( - Any, Callable, Iterable, List, Mapping, Optional, Sequence, Sized, Tuple, Type, + Any, Callable, ClassVar, Iterable, List, Mapping, Optional, Sequence, Sized, Tuple, Type, Generic, TypeVar, overload, ) from typing import Union as UnionT @@ -227,8 +227,8 @@ class BigEndianStructure(Structure): pass class LittleEndianStructure(Structure): pass class Array(Generic[_T], Sized, _CData): - _length_: int = ... - _type_: Type[_T] = ... + _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: ... @@ -244,7 +244,7 @@ class Array(Generic[_T], Sized, _CData): class _Pointer(Generic[_T], _PointerLike, _CData): - _type_: Type[_T] = ... + _type_: ClassVar[Type[_T]] = ... contents: _T = ... def __init__(self, arg: _T = ...) -> None: ... @overload From 041398276d8d0bd3b1f505971fecff6783820c0a Mon Sep 17 00:00:00 2001 From: dgelessus Date: Tue, 20 Feb 2018 23:27:12 +0100 Subject: [PATCH 13/32] Mark ctypes._CData.from_buffer[_copy] offset arg as optional --- stdlib/2and3/ctypes/__init__.pyi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stdlib/2and3/ctypes/__init__.pyi b/stdlib/2and3/ctypes/__init__.pyi index 5a7a757efa03..6d460ec47342 100644 --- a/stdlib/2and3/ctypes/__init__.pyi +++ b/stdlib/2and3/ctypes/__init__.pyi @@ -57,9 +57,9 @@ class _CData(metaclass=_CDataMeta): _b_needsfree_: bool = ... _objects: Optional[Mapping[Any, int]] = ... @classmethod - def from_buffer(cls: Type[_CT], source: bytearray, offset: int) -> _CT: ... + def from_buffer(cls: Type[_CT], source: bytearray, offset: int = ...) -> _CT: ... @classmethod - def from_buffer_copy(cls: Type[_CT], source: bytearray, offset: int) -> _CT: ... + def from_buffer_copy(cls: Type[_CT], source: bytearray, offset: int = ...) -> _CT: ... @classmethod def from_address(cls: Type[_CT], address: int) -> _CT: ... @classmethod From 50e44c9959105803f65991ec64d42659eaae1f1f Mon Sep 17 00:00:00 2001 From: dgelessus Date: Wed, 21 Feb 2018 00:26:07 +0100 Subject: [PATCH 14/32] Remove trailing whitespace in ctypes.__init__ --- stdlib/2and3/ctypes/__init__.pyi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stdlib/2and3/ctypes/__init__.pyi b/stdlib/2and3/ctypes/__init__.pyi index 6d460ec47342..3e9de00d3b61 100644 --- a/stdlib/2and3/ctypes/__init__.pyi +++ b/stdlib/2and3/ctypes/__init__.pyi @@ -154,7 +154,7 @@ if sys.platform == 'win32': def wstring_at(address: int, size: int = ...) -> str: ... class _SimpleCData(Generic[_T], _CData): - value: _T = ... + value: _T = ... def __init__(self, value: _T = ...) -> None: ... class c_byte(_SimpleCData[int]): ... @@ -245,7 +245,7 @@ class Array(Generic[_T], Sized, _CData): class _Pointer(Generic[_T], _PointerLike, _CData): _type_: ClassVar[Type[_T]] = ... - contents: _T = ... + contents: _T = ... def __init__(self, arg: _T = ...) -> None: ... @overload def __getitem__(self, i: int) -> _T: ... From 535a0085b0c71dff6d56e5ddae88edb8add32b5d Mon Sep 17 00:00:00 2001 From: dgelessus Date: Tue, 6 Mar 2018 11:32:02 +0100 Subject: [PATCH 15/32] Don't export ctypes.UnionT --- stdlib/2and3/ctypes/__init__.pyi | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/stdlib/2and3/ctypes/__init__.pyi b/stdlib/2and3/ctypes/__init__.pyi index 3e9de00d3b61..d9f9ba9f8e2c 100644 --- a/stdlib/2and3/ctypes/__init__.pyi +++ b/stdlib/2and3/ctypes/__init__.pyi @@ -4,7 +4,7 @@ from typing import ( Any, Callable, ClassVar, Iterable, List, Mapping, Optional, Sequence, Sized, Tuple, Type, Generic, TypeVar, overload, ) -from typing import Union as UnionT +from typing import Union as _UnionT import sys _T = TypeVar('_T') @@ -63,7 +63,7 @@ class _CData(metaclass=_CDataMeta): @classmethod def from_address(cls: Type[_CT], address: int) -> _CT: ... @classmethod - def from_param(cls: Type[_CT], obj: Any) -> UnionT[_CT, _cparam]: ... + def from_param(cls: Type[_CT], obj: Any) -> _UnionT[_CT, _cparam]: ... @classmethod def in_dll(cls: Type[_CT], library: _DLL, name: str) -> _CT: ... @@ -74,7 +74,7 @@ _ECT = Callable[[Optional[Type[_CData]], Tuple[_CData, ...]], _CData] class _FuncPtr(_PointerLike, _CData): - restype: UnionT[Type[_CData], Callable[[int], None], None] = ... + restype: _UnionT[Type[_CData], Callable[[int], None], None] = ... argtypes: Tuple[Type[_CData], ...] = ... errcheck: _ECT = ... def __call__(self, *args: Any, **kwargs: Any) -> Any: ... @@ -94,7 +94,7 @@ if sys.platform == 'win32': def PYFUNCTYPE(restype: Type[_CData], *argtypes: Type[_CData]) -> Type[_FuncProto]: ... -_PF = UnionT[ +_PF = _UnionT[ Tuple[int], Tuple[int, str], Tuple[int, str, Any] @@ -106,7 +106,7 @@ class _FuncProto(_FuncPtr): @overload def __init__(self, callable: Callable[..., Any]) -> None: ... @overload - def __init__(self, func_spec: Tuple[UnionT[str, int], _DLL], + def __init__(self, func_spec: Tuple[_UnionT[str, int], _DLL], paramflags: Tuple[_PF, ...] = ...) -> None: ... @overload def __init__(self, vtlb_index: int, name: str, @@ -116,14 +116,14 @@ class _FuncProto(_FuncPtr): class _cparam: ... def addressof(obj: _CData) -> int: ... -def alignment(obj_or_type: UnionT[_CData, Type[_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: _CData, type: Type[_PT]) -> _PT: ... -def create_string_buffer(init_or_size: UnionT[int, bytes], +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, str], +def create_unicode_buffer(init_or_size: _UnionT[int, str], size: Optional[int] = ...) -> Array[c_wchar]: ... if sys.platform == 'win32': def DllCanUnloadNow() -> int: ... @@ -133,10 +133,10 @@ if sys.platform == 'win32': def get_errno() -> int: ... if sys.platform == 'win32': def get_last_error() -> int: ... -def memmove(dst: UnionT[int, _CData], - src: UnionT[int, _CData], +def memmove(dst: _UnionT[int, _CData], + src: _UnionT[int, _CData], count: int) -> None: ... -def memset(dst: UnionT[int, _CData], +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]: ... @@ -146,7 +146,7 @@ if sys.version_info < (3,): 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 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] = ..., @@ -161,7 +161,7 @@ class c_byte(_SimpleCData[int]): ... class c_char(_SimpleCData[bytes]): ... class c_char_p(_PointerLike, _SimpleCData[Optional[bytes]]): - def __init__(self, value: UnionT[int, bytes] = ...) -> None: ... + def __init__(self, value: _UnionT[int, bytes] = ...) -> None: ... class c_double(_SimpleCData[float]): ... class c_longdouble(_SimpleCData[float]): ... @@ -198,7 +198,7 @@ class c_void_p(_PointerLike, _SimpleCData[Optional[int]]): ... class c_wchar(_SimpleCData[str]): ... class c_wchar_p(_PointerLike, _SimpleCData[Optional[str]]): - def __init__(self, value: UnionT[int, str] = ...) -> None: ... + def __init__(self, value: _UnionT[int, str] = ...) -> None: ... class c_bool(_SimpleCData[bool]): def __init__(self, value: bool) -> None: ... @@ -212,7 +212,7 @@ class _CField: offset: int = ... size: int = ... class _StructUnionMeta(_CDataMeta): - _fields_: Sequence[UnionT[Tuple[str, Type[_CData]], Tuple[str, Type[_CData], int]]] = ... + _fields_: Sequence[_UnionT[Tuple[str, Type[_CData]], Tuple[str, Type[_CData], int]]] = ... _pack_: int = ... _anonymous_: Sequence[str] = ... def __getattr__(self, name: str) -> _CField: ... From aedd0d920cc4f51137945883ef11a9a29e52eb8c Mon Sep 17 00:00:00 2001 From: dgelessus Date: Tue, 6 Mar 2018 11:39:35 +0100 Subject: [PATCH 16/32] Add ctypes._DLL.__getitem__ --- stdlib/2and3/ctypes/__init__.pyi | 1 + 1 file changed, 1 insertion(+) diff --git a/stdlib/2and3/ctypes/__init__.pyi b/stdlib/2and3/ctypes/__init__.pyi index d9f9ba9f8e2c..29476f26d813 100644 --- a/stdlib/2and3/ctypes/__init__.pyi +++ b/stdlib/2and3/ctypes/__init__.pyi @@ -24,6 +24,7 @@ class _DLL: def __init__(self, name: str, mode: int = ..., handle: Optional[int] = ..., use_errno: bool = ..., use_last_error: bool = ...) -> None: ... def __getattr__(self, name: str) -> Any: ... + def __getitem__(self, name: str) -> Any: ... class CDLL(_DLL): ... if sys.platform == 'win32': class OleDLL(_DLL): ... From 2311ced308ba66f542fc161f336aff40303e1cc9 Mon Sep 17 00:00:00 2001 From: dgelessus Date: Tue, 6 Mar 2018 11:40:54 +0100 Subject: [PATCH 17/32] Make ctypes._DLL.__get(attr|item)__ return _FuncPtr instead of Any --- stdlib/2and3/ctypes/__init__.pyi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stdlib/2and3/ctypes/__init__.pyi b/stdlib/2and3/ctypes/__init__.pyi index 29476f26d813..2a5f6a56bde6 100644 --- a/stdlib/2and3/ctypes/__init__.pyi +++ b/stdlib/2and3/ctypes/__init__.pyi @@ -23,8 +23,8 @@ DEFAULT_MODE: int = ... class _DLL: def __init__(self, name: str, mode: int = ..., handle: Optional[int] = ..., use_errno: bool = ..., use_last_error: bool = ...) -> None: ... - def __getattr__(self, name: str) -> Any: ... - def __getitem__(self, name: str) -> Any: ... + def __getattr__(self, name: str) -> _FuncPtr: ... + def __getitem__(self, name: str) -> _FuncPtr: ... class CDLL(_DLL): ... if sys.platform == 'win32': class OleDLL(_DLL): ... From 854e22ebd3d5006a9bd0e76525e9a53c1e8532f4 Mon Sep 17 00:00:00 2001 From: dgelessus Date: Tue, 6 Mar 2018 11:43:11 +0100 Subject: [PATCH 18/32] Change ctypes DLL inheritance hierarchy to match the real one better --- stdlib/2and3/ctypes/__init__.pyi | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/stdlib/2and3/ctypes/__init__.pyi b/stdlib/2and3/ctypes/__init__.pyi index 2a5f6a56bde6..a395d6403db3 100644 --- a/stdlib/2and3/ctypes/__init__.pyi +++ b/stdlib/2and3/ctypes/__init__.pyi @@ -20,16 +20,15 @@ RTLD_LOCAL: int = ... DEFAULT_MODE: int = ... -class _DLL: +class CDLL(object): def __init__(self, name: str, mode: int = ..., handle: Optional[int] = ..., use_errno: bool = ..., use_last_error: bool = ...) -> None: ... def __getattr__(self, name: str) -> _FuncPtr: ... def __getitem__(self, name: str) -> _FuncPtr: ... -class CDLL(_DLL): ... if sys.platform == 'win32': - class OleDLL(_DLL): ... - class WinDLL(_DLL): ... -class PyDLL(_DLL): + class OleDLL(CDLL): ... + class WinDLL(CDLL): ... +class PyDLL(CDLL): _handle: int = ... _name: str = ... def __init__(self, name: str, mode: int = ..., From e765dec75bc59aa25e97d62a605e1dbcd6e3b701 Mon Sep 17 00:00:00 2001 From: dgelessus Date: Tue, 6 Mar 2018 11:52:08 +0100 Subject: [PATCH 19/32] Add some missing attributes to ctypes.CDLL --- stdlib/2and3/ctypes/__init__.pyi | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/stdlib/2and3/ctypes/__init__.pyi b/stdlib/2and3/ctypes/__init__.pyi index a395d6403db3..5753ccd0803d 100644 --- a/stdlib/2and3/ctypes/__init__.pyi +++ b/stdlib/2and3/ctypes/__init__.pyi @@ -21,6 +21,11 @@ DEFAULT_MODE: int = ... class CDLL(object): + _func_flags_: ClassVar[int] = ... + _func_restype_: ClassVar[_CData] = ... + _name: str = ... + _handle: int = ... + _FuncPtr: _FuncPtr = ... def __init__(self, name: str, mode: int = ..., handle: Optional[int] = ..., use_errno: bool = ..., use_last_error: bool = ...) -> None: ... def __getattr__(self, name: str) -> _FuncPtr: ... @@ -29,8 +34,6 @@ if sys.platform == 'win32': class OleDLL(CDLL): ... class WinDLL(CDLL): ... class PyDLL(CDLL): - _handle: int = ... - _name: str = ... def __init__(self, name: str, mode: int = ..., handle: Optional[int] = ...) -> None: ... From 7a34b64bea114ea652e3fa01940caa6e30e642ce Mon Sep 17 00:00:00 2001 From: dgelessus Date: Tue, 6 Mar 2018 11:54:59 +0100 Subject: [PATCH 20/32] Rename ctypes._FuncPtr so it doesn't conflict with CDLL._FuncPtr --- stdlib/2and3/ctypes/__init__.pyi | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/stdlib/2and3/ctypes/__init__.pyi b/stdlib/2and3/ctypes/__init__.pyi index 5753ccd0803d..0769ae652db7 100644 --- a/stdlib/2and3/ctypes/__init__.pyi +++ b/stdlib/2and3/ctypes/__init__.pyi @@ -25,11 +25,11 @@ class CDLL(object): _func_restype_: ClassVar[_CData] = ... _name: str = ... _handle: int = ... - _FuncPtr: _FuncPtr = ... + _FuncPtr: _FuncPointer = ... def __init__(self, name: str, mode: int = ..., handle: Optional[int] = ..., use_errno: bool = ..., use_last_error: bool = ...) -> None: ... - def __getattr__(self, name: str) -> _FuncPtr: ... - def __getitem__(self, name: str) -> _FuncPtr: ... + def __getattr__(self, name: str) -> _FuncPointer: ... + def __getitem__(self, name: str) -> _FuncPointer: ... if sys.platform == 'win32': class OleDLL(CDLL): ... class WinDLL(CDLL): ... @@ -73,10 +73,10 @@ class _CData(metaclass=_CDataMeta): class _PointerLike(_CData): pass _ECT = Callable[[Optional[Type[_CData]], - _FuncPtr, + _FuncPointer, Tuple[_CData, ...]], _CData] -class _FuncPtr(_PointerLike, _CData): +class _FuncPointer(_PointerLike, _CData): restype: _UnionT[Type[_CData], Callable[[int], None], None] = ... argtypes: Tuple[Type[_CData], ...] = ... errcheck: _ECT = ... @@ -103,7 +103,7 @@ _PF = _UnionT[ Tuple[int, str, Any] ] -class _FuncProto(_FuncPtr): +class _FuncProto(_FuncPointer): @overload def __init__(self, address: int) -> None: ... @overload From 0619771e7b376ebccdc52149a6c700b12b76211d Mon Sep 17 00:00:00 2001 From: dgelessus Date: Tue, 6 Mar 2018 11:55:19 +0100 Subject: [PATCH 21/32] Fix type of ctypes.CDLL._FuncPtr --- stdlib/2and3/ctypes/__init__.pyi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/2and3/ctypes/__init__.pyi b/stdlib/2and3/ctypes/__init__.pyi index 0769ae652db7..df51bb309f49 100644 --- a/stdlib/2and3/ctypes/__init__.pyi +++ b/stdlib/2and3/ctypes/__init__.pyi @@ -25,7 +25,7 @@ class CDLL(object): _func_restype_: ClassVar[_CData] = ... _name: str = ... _handle: int = ... - _FuncPtr: _FuncPointer = ... + _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: ... From 94a985357da8a4e3f684f61248321abc40906b16 Mon Sep 17 00:00:00 2001 From: dgelessus Date: Tue, 6 Mar 2018 12:01:58 +0100 Subject: [PATCH 22/32] Merge _FuncProto into _FuncPointer The function pointer types returned by CFUNCTYPE and friends are the same as those encountered elsewhere, so there's no need to treat them differently. --- stdlib/2and3/ctypes/__init__.pyi | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/stdlib/2and3/ctypes/__init__.pyi b/stdlib/2and3/ctypes/__init__.pyi index df51bb309f49..2be2385fc204 100644 --- a/stdlib/2and3/ctypes/__init__.pyi +++ b/stdlib/2and3/ctypes/__init__.pyi @@ -80,6 +80,17 @@ 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], _DLL], + 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): ... @@ -88,14 +99,14 @@ class ArgumentError(Exception): ... def CFUNCTYPE(restype: Type[_CData], *argtypes: Type[_CData], use_errno: bool = ..., - use_last_error: bool = ...) -> Type[_FuncProto]: ... + 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[_FuncProto]: ... + use_last_error: bool = ...) -> Type[_FuncPointer]: ... def PYFUNCTYPE(restype: Type[_CData], - *argtypes: Type[_CData]) -> Type[_FuncProto]: ... + *argtypes: Type[_CData]) -> Type[_FuncPointer]: ... _PF = _UnionT[ Tuple[int], @@ -103,19 +114,6 @@ _PF = _UnionT[ Tuple[int, str, Any] ] -class _FuncProto(_FuncPointer): - @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], _DLL], - paramflags: Tuple[_PF, ...] = ...) -> None: ... - @overload - def __init__(self, vtlb_index: int, name: str, - paramflags: Tuple[_PF, ...] = ..., - iid: _Pointer[c_int] = ...) -> None: ... - class _cparam: ... def addressof(obj: _CData) -> int: ... From 1091074699255b92be5866db7509c683541a0ceb Mon Sep 17 00:00:00 2001 From: dgelessus Date: Tue, 6 Mar 2018 12:02:56 +0100 Subject: [PATCH 23/32] Fix some leftover references to ctypes._DLL --- stdlib/2and3/ctypes/__init__.pyi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stdlib/2and3/ctypes/__init__.pyi b/stdlib/2and3/ctypes/__init__.pyi index 2be2385fc204..c5e45e552eb1 100644 --- a/stdlib/2and3/ctypes/__init__.pyi +++ b/stdlib/2and3/ctypes/__init__.pyi @@ -68,7 +68,7 @@ class _CData(metaclass=_CDataMeta): @classmethod def from_param(cls: Type[_CT], obj: Any) -> _UnionT[_CT, _cparam]: ... @classmethod - def in_dll(cls: Type[_CT], library: _DLL, name: str) -> _CT: ... + def in_dll(cls: Type[_CT], library: CDLL, name: str) -> _CT: ... class _PointerLike(_CData): pass @@ -85,7 +85,7 @@ class _FuncPointer(_PointerLike, _CData): @overload def __init__(self, callable: Callable[..., Any]) -> None: ... @overload - def __init__(self, func_spec: Tuple[_UnionT[str, int], _DLL], + def __init__(self, func_spec: Tuple[_UnionT[str, int], CDLL], paramflags: Tuple[_PF, ...] = ...) -> None: ... @overload def __init__(self, vtlb_index: int, name: str, From 253fc4a7f16895373ef712cd16d90fd4a44397fc Mon Sep 17 00:00:00 2001 From: dgelessus Date: Tue, 6 Mar 2018 12:04:18 +0100 Subject: [PATCH 24/32] Simplify definition of ctypes._DLLT --- stdlib/2and3/ctypes/__init__.pyi | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/stdlib/2and3/ctypes/__init__.pyi b/stdlib/2and3/ctypes/__init__.pyi index c5e45e552eb1..e7a6dc3511d6 100644 --- a/stdlib/2and3/ctypes/__init__.pyi +++ b/stdlib/2and3/ctypes/__init__.pyi @@ -8,10 +8,7 @@ from typing import Union as _UnionT import sys _T = TypeVar('_T') -if sys.platform == 'win32': - _DLLT = TypeVar('_DLLT', CDLL, OleDLL, WinDLL, PyDLL) -else: - _DLLT = TypeVar('_DLLT', CDLL, PyDLL) +_DLLT = TypeVar('_DLLT', bound=CDLL) _CT = TypeVar('_CT', bound=_CData) From cc3f49a2a78b591ccbcb48c57f9fcf146ec9df0b Mon Sep 17 00:00:00 2001 From: dgelessus Date: Tue, 6 Mar 2018 12:05:14 +0100 Subject: [PATCH 25/32] Add ctypes.LibraryLoader.__get(attr|item)__ --- stdlib/2and3/ctypes/__init__.pyi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/stdlib/2and3/ctypes/__init__.pyi b/stdlib/2and3/ctypes/__init__.pyi index e7a6dc3511d6..5f5afe505ea4 100644 --- a/stdlib/2and3/ctypes/__init__.pyi +++ b/stdlib/2and3/ctypes/__init__.pyi @@ -36,6 +36,8 @@ 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] = ... From 7ff6017f6805843c733374afe3e3fb7f746e4125 Mon Sep 17 00:00:00 2001 From: dgelessus Date: Tue, 6 Mar 2018 12:08:00 +0100 Subject: [PATCH 26/32] Use Text instead of str where appropriate in ctypes.__init__ --- stdlib/2and3/ctypes/__init__.pyi | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/stdlib/2and3/ctypes/__init__.pyi b/stdlib/2and3/ctypes/__init__.pyi index 5f5afe505ea4..2563e5ab6e81 100644 --- a/stdlib/2and3/ctypes/__init__.pyi +++ b/stdlib/2and3/ctypes/__init__.pyi @@ -1,7 +1,7 @@ # Stubs for ctypes from typing import ( - Any, Callable, ClassVar, Iterable, List, Mapping, Optional, Sequence, Sized, Tuple, Type, + Any, Callable, ClassVar, Iterable, List, Mapping, Optional, Sequence, Sized, Text, Tuple, Type, Generic, TypeVar, overload, ) from typing import Union as _UnionT @@ -123,7 +123,7 @@ def cast(obj: _CData, 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, str], +def create_unicode_buffer(init_or_size: _UnionT[int, Text], size: Optional[int] = ...) -> Array[c_wchar]: ... if sys.platform == 'win32': def DllCanUnloadNow() -> int: ... @@ -196,9 +196,9 @@ class c_ushort(_SimpleCData[int]): ... class c_void_p(_PointerLike, _SimpleCData[Optional[int]]): ... -class c_wchar(_SimpleCData[str]): ... -class c_wchar_p(_PointerLike, _SimpleCData[Optional[str]]): - def __init__(self, value: _UnionT[int, str] = ...) -> None: ... +class c_wchar(_SimpleCData[Text]): ... +class c_wchar_p(_PointerLike, _SimpleCData[Optional[Text]]): + def __init__(self, value: _UnionT[int, Text] = ...) -> None: ... class c_bool(_SimpleCData[bool]): def __init__(self, value: bool) -> None: ... From 66a74a821e2dd4e910001eb5f06f6011a4580179 Mon Sep 17 00:00:00 2001 From: dgelessus Date: Tue, 6 Mar 2018 12:09:46 +0100 Subject: [PATCH 27/32] Make ctypes.c_char accept ints --- stdlib/2and3/ctypes/__init__.pyi | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/stdlib/2and3/ctypes/__init__.pyi b/stdlib/2and3/ctypes/__init__.pyi index 2563e5ab6e81..a0f8ebc97cd4 100644 --- a/stdlib/2and3/ctypes/__init__.pyi +++ b/stdlib/2and3/ctypes/__init__.pyi @@ -159,7 +159,8 @@ class _SimpleCData(Generic[_T], _CData): class c_byte(_SimpleCData[int]): ... -class c_char(_SimpleCData[bytes]): ... +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: _UnionT[int, bytes] = ...) -> None: ... From e5d164238a98cd4ffd95b9905baf63309433bd41 Mon Sep 17 00:00:00 2001 From: dgelessus Date: Tue, 6 Mar 2018 12:11:14 +0100 Subject: [PATCH 28/32] Make ctypes.c_[w]char_p accept None --- stdlib/2and3/ctypes/__init__.pyi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stdlib/2and3/ctypes/__init__.pyi b/stdlib/2and3/ctypes/__init__.pyi index a0f8ebc97cd4..412ca4050283 100644 --- a/stdlib/2and3/ctypes/__init__.pyi +++ b/stdlib/2and3/ctypes/__init__.pyi @@ -162,7 +162,7 @@ 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: _UnionT[int, bytes] = ...) -> None: ... + def __init__(self, value: Optional[_UnionT[int, bytes]] = ...) -> None: ... class c_double(_SimpleCData[float]): ... class c_longdouble(_SimpleCData[float]): ... @@ -199,7 +199,7 @@ 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: _UnionT[int, Text] = ...) -> None: ... + def __init__(self, value: Optional[_UnionT[int, Text]] = ...) -> None: ... class c_bool(_SimpleCData[bool]): def __init__(self, value: bool) -> None: ... From b81de47acefef9b59a9b6ce0dd86036f33415058 Mon Sep 17 00:00:00 2001 From: dgelessus Date: Tue, 6 Mar 2018 12:15:23 +0100 Subject: [PATCH 29/32] Remove unneeded Generic base from ctypes.py_object --- stdlib/2and3/ctypes/__init__.pyi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/2and3/ctypes/__init__.pyi b/stdlib/2and3/ctypes/__init__.pyi index 412ca4050283..377871447493 100644 --- a/stdlib/2and3/ctypes/__init__.pyi +++ b/stdlib/2and3/ctypes/__init__.pyi @@ -207,7 +207,7 @@ class c_bool(_SimpleCData[bool]): if sys.platform == 'win32': class HRESULT(_SimpleCData[Any]): ... # TODO undocumented -class py_object(Generic[_T], _SimpleCData[_T]): ... +class py_object(_SimpleCData[_T]): ... class _CField: offset: int = ... From a7507ea7906616c1e2cc5977f2d84e5ea2e0b046 Mon Sep 17 00:00:00 2001 From: dgelessus Date: Tue, 6 Mar 2018 12:16:47 +0100 Subject: [PATCH 30/32] Make ctypes.cast accept _cparam --- stdlib/2and3/ctypes/__init__.pyi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/2and3/ctypes/__init__.pyi b/stdlib/2and3/ctypes/__init__.pyi index 377871447493..63b9bee6e635 100644 --- a/stdlib/2and3/ctypes/__init__.pyi +++ b/stdlib/2and3/ctypes/__init__.pyi @@ -119,7 +119,7 @@ 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: _CData, type: Type[_PT]) -> _PT: ... +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 From d8d431e7f07079e2dfe6ab4a10a3bde938fcd120 Mon Sep 17 00:00:00 2001 From: dgelessus Date: Tue, 6 Mar 2018 13:41:15 +0100 Subject: [PATCH 31/32] Fix ctypes._PF being declared too late --- stdlib/2and3/ctypes/__init__.pyi | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/stdlib/2and3/ctypes/__init__.pyi b/stdlib/2and3/ctypes/__init__.pyi index 63b9bee6e635..86d55e00c032 100644 --- a/stdlib/2and3/ctypes/__init__.pyi +++ b/stdlib/2and3/ctypes/__init__.pyi @@ -75,6 +75,11 @@ _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], ...] = ... @@ -107,12 +112,6 @@ if sys.platform == 'win32': def PYFUNCTYPE(restype: Type[_CData], *argtypes: Type[_CData]) -> Type[_FuncPointer]: ... -_PF = _UnionT[ - Tuple[int], - Tuple[int, str], - Tuple[int, str, Any] -] - class _cparam: ... def addressof(obj: _CData) -> int: ... From a38f5790ae4d9306c4a6d9e102fdbcf1a2a02358 Mon Sep 17 00:00:00 2001 From: dgelessus Date: Wed, 7 Mar 2018 10:40:15 +0100 Subject: [PATCH 32/32] Remove incorrect ctypes.PyDLL.__init__ override --- stdlib/2and3/ctypes/__init__.pyi | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/stdlib/2and3/ctypes/__init__.pyi b/stdlib/2and3/ctypes/__init__.pyi index 86d55e00c032..b82f6f490ba0 100644 --- a/stdlib/2and3/ctypes/__init__.pyi +++ b/stdlib/2and3/ctypes/__init__.pyi @@ -30,9 +30,7 @@ class CDLL(object): if sys.platform == 'win32': class OleDLL(CDLL): ... class WinDLL(CDLL): ... -class PyDLL(CDLL): - def __init__(self, name: str, mode: int = ..., - handle: Optional[int] = ...) -> None: ... +class PyDLL(CDLL): ... class LibraryLoader(Generic[_DLLT]): def __init__(self, dlltype: Type[_DLLT]) -> None: ...