Skip to content

Commit 205901e

Browse files
Add type stubs for cffi (#8736)
Co-authored-by: Alex Waygood <[email protected]>
1 parent 42c044e commit 205901e

20 files changed

+944
-0
lines changed

pyrightconfig.stricter.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
"stubs/beautifulsoup4",
3737
"stubs/braintree",
3838
"stubs/caldav",
39+
"stubs/cffi",
3940
"stubs/commonmark",
4041
"stubs/cryptography",
4142
"stubs/dateparser",
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# technically exists on all OSs, but crashes on all but windows
2+
cffi.(api.)?FFI.getwinerror
3+
4+
# added dynamically and not detected by stubtest
5+
cffi.(api.)?FFI.CData
6+
cffi.(api.)?FFI.CType
7+
cffi.(api.)?FFI.buffer
8+
9+
# Exists at runtime, but missing from stubs
10+
cffi.vengine_cpy.__warningregistry__
11+
12+
# Alias to io.StringIO, which has the same allowlist
13+
cffi.recompiler.NativeIO.seek
14+
cffi.recompiler.NativeIO.truncate
15+
cffi.verifier.NativeIO.seek
16+
cffi.verifier.NativeIO.truncate
17+
18+
# Unnecessary re-exports
19+
cffi.cparser.COMMON_TYPES
20+
cffi.verifier.__version_verifier_modules__

stubs/cffi/METADATA.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
version = "1.15.*"
2+
3+
[tool.stubtest]
4+
ignore_missing_stub = false

stubs/cffi/_cffi_backend.pyi

Lines changed: 265 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,265 @@
1+
import sys
2+
import types
3+
from _typeshed import Incomplete, ReadableBuffer, WriteableBuffer
4+
from collections.abc import Callable, Hashable
5+
from typing import Any, ClassVar, Protocol, TypeVar, overload
6+
from typing_extensions import Literal, TypeAlias, final
7+
8+
_T = TypeVar("_T")
9+
10+
class _Allocator(Protocol):
11+
def __call__(self, cdecl: str | CType, init: Any = ...) -> _CDataBase: ...
12+
13+
__version__: str
14+
15+
FFI_CDECL: int
16+
FFI_DEFAULT_ABI: int
17+
RTLD_GLOBAL: int
18+
RTLD_LAZY: int
19+
RTLD_LOCAL: int
20+
RTLD_NOW: int
21+
if sys.platform != "win32":
22+
RTLD_DEEPBIND: int
23+
RTLD_NODELETE: int
24+
RTLD_NOLOAD: int
25+
26+
@final
27+
class CField:
28+
bitshift: Incomplete
29+
bitsize: Incomplete
30+
flags: Incomplete
31+
offset: Incomplete
32+
type: Incomplete
33+
34+
@final
35+
class CLibrary:
36+
def close_lib(self, *args, **kwargs): ...
37+
def load_function(self, *args, **kwargs): ...
38+
def read_variable(self, *args, **kwargs): ...
39+
def write_variable(self, *args, **kwargs): ...
40+
41+
@final
42+
class CType:
43+
abi: Incomplete
44+
args: Incomplete
45+
cname: Incomplete
46+
elements: Incomplete
47+
ellipsis: Incomplete
48+
fields: Incomplete
49+
item: Incomplete
50+
kind: Incomplete
51+
length: Incomplete
52+
relements: Incomplete
53+
result: Incomplete
54+
def __dir__(self): ...
55+
56+
@final
57+
class Lib:
58+
def __dir__(self): ...
59+
60+
@final
61+
class _CDataBase:
62+
__name__: ClassVar[str]
63+
def __add__(self, other): ...
64+
def __bool__(self): ...
65+
def __call__(self, *args, **kwargs): ...
66+
def __complex__(self): ...
67+
def __delitem__(self, other): ...
68+
def __dir__(self): ...
69+
def __enter__(self): ...
70+
def __eq__(self, other): ...
71+
def __exit__(self, type, value, traceback): ...
72+
def __float__(self): ...
73+
def __ge__(self, other): ...
74+
def __getitem__(self, index): ...
75+
def __gt__(self, other): ...
76+
def __hash__(self): ...
77+
def __int__(self): ...
78+
def __iter__(self): ...
79+
def __le__(self, other): ...
80+
def __len__(self): ...
81+
def __lt__(self, other): ...
82+
def __ne__(self, other): ...
83+
def __radd__(self, other): ...
84+
def __rsub__(self, other): ...
85+
def __setitem__(self, index, object): ...
86+
def __sub__(self, other): ...
87+
88+
@final
89+
class buffer:
90+
__hash__: ClassVar[None] # type: ignore[assignment]
91+
def __init__(self, *args, **kwargs) -> None: ...
92+
def __delitem__(self, other): ...
93+
def __eq__(self, other): ...
94+
def __ge__(self, other): ...
95+
def __getitem__(self, index): ...
96+
def __gt__(self, other): ...
97+
def __le__(self, other): ...
98+
def __len__(self): ...
99+
def __lt__(self, other): ...
100+
def __ne__(self, other): ...
101+
def __setitem__(self, index, object): ...
102+
103+
# These aliases are to work around pyright complaints.
104+
# Pyright doesn't like it when a class object is defined as an alias
105+
# of a global object with the same name.
106+
_tmp_CType = CType
107+
_tmp_buffer = buffer
108+
109+
class FFI:
110+
CData: TypeAlias = _CDataBase
111+
CType: TypeAlias = _tmp_CType
112+
buffer: TypeAlias = _tmp_buffer # noqa: Y042
113+
114+
class error(Exception): ...
115+
NULL: ClassVar[CData]
116+
RTLD_GLOBAL: ClassVar[int]
117+
RTLD_LAZY: ClassVar[int]
118+
RTLD_LOCAL: ClassVar[int]
119+
RTLD_NOW: ClassVar[int]
120+
if sys.platform != "win32":
121+
RTLD_DEEPBIND: ClassVar[int]
122+
RTLD_NODELETE: ClassVar[int]
123+
RTLD_NOLOAD: ClassVar[int]
124+
125+
errno: int
126+
127+
def __init__(
128+
self,
129+
module_name: str = ...,
130+
_version: int = ...,
131+
_types: str = ...,
132+
_globals: tuple[str | int, ...] = ...,
133+
_struct_unions: tuple[tuple[str, ...], ...] = ...,
134+
_enums: tuple[str, ...] = ...,
135+
_typenames: tuple[str, ...] = ...,
136+
_includes: tuple[FFI, ...] = ...,
137+
) -> None: ...
138+
@overload
139+
def addressof(self, __cdata: CData, *field_or_index: str | int) -> CData: ...
140+
@overload
141+
def addressof(self, __library: Lib, __name: str) -> CData: ...
142+
def alignof(self, __cdecl: str | CType | CData) -> int: ...
143+
@overload
144+
def callback(
145+
self,
146+
cdecl: str | CType,
147+
python_callable: None = ...,
148+
error: Any = ...,
149+
onerror: Callable[[Exception, Any, Any], None] | None = ...,
150+
) -> Callable[[Callable[..., _T]], Callable[..., _T]]: ...
151+
@overload
152+
def callback(
153+
self,
154+
cdecl: str | CType,
155+
python_callable: Callable[..., _T],
156+
error: Any = ...,
157+
onerror: Callable[[Exception, Any, Any], None] | None = ...,
158+
) -> Callable[..., _T]: ...
159+
def cast(self, cdecl: str | CType, value: CData) -> CData: ...
160+
def def_extern(
161+
self, name: str = ..., error: Any = ..., onerror: Callable[[Exception, Any, types.TracebackType], Any] = ...
162+
) -> Callable[[Callable[..., _T]], Callable[..., _T]]: ...
163+
def dlclose(self, __lib: Lib) -> None: ...
164+
if sys.platform == "win32":
165+
def dlopen(self, __libpath: str | CData, __flags: int = ...) -> Lib: ...
166+
else:
167+
def dlopen(self, __libpath: str | CData | None = ..., __flags: int = ...) -> Lib: ...
168+
169+
@overload
170+
def from_buffer(self, cdecl: ReadableBuffer, require_writable: Literal[False] = ...) -> CData: ...
171+
@overload
172+
def from_buffer(self, cdecl: WriteableBuffer, require_writable: Literal[True]) -> CData: ...
173+
@overload
174+
def from_buffer(self, cdecl: str | CType, python_buffer: ReadableBuffer, require_writable: Literal[False] = ...) -> CData: ...
175+
@overload
176+
def from_buffer(self, cdecl: str | CType, python_buffer: WriteableBuffer, require_writable: Literal[True]) -> CData: ...
177+
def from_handle(self, __x: CData) -> Any: ...
178+
@overload
179+
def gc(self, cdata: CData, destructor: Callable[[CData], Any], size: int = ...) -> CData: ...
180+
@overload
181+
def gc(self, cdata: CData, destructor: None, size: int = ...) -> None: ...
182+
def getctype(self, cdecl: str | CType, replace_with: str = ...) -> str: ...
183+
if sys.platform == "win32":
184+
def getwinerror(self, code: int = ...) -> tuple[int, str]: ...
185+
186+
def init_once(self, func: Callable[[], Any], tag: Hashable) -> Any: ...
187+
def integer_const(self, name: str) -> int: ...
188+
def list_types(self) -> tuple[list[str], list[str], list[str]]: ...
189+
def memmove(self, dest: CData | WriteableBuffer, src: CData | ReadableBuffer, n: int) -> None: ...
190+
def new(self, cdecl: str | CType, init: Any = ...) -> CData: ...
191+
@overload
192+
def new_allocator(self, alloc: None = ..., free: None = ..., should_clear_after_alloc: bool = ...) -> _Allocator: ...
193+
@overload
194+
def new_allocator(
195+
self, alloc: Callable[[int], CData], free: None = ..., should_clear_after_alloc: bool = ...
196+
) -> _Allocator: ...
197+
@overload
198+
def new_allocator(
199+
self, alloc: Callable[[int], CData], free: Callable[[CData], Any], should_clear_after_alloc: bool = ...
200+
) -> _Allocator: ...
201+
def new_handle(self, __x: Any) -> CData: ...
202+
def offsetof(self, __cdecl: str | CType, __field_or_index: str | int, *__fields_or_indexes: str | int) -> int: ...
203+
def release(self, __cdata: CData) -> None: ...
204+
def sizeof(self, __cdecl: str | CType | CData) -> int: ...
205+
def string(self, cdata: CData, maxlen: int) -> bytes | str: ...
206+
def typeof(self, cdecl: str | CData) -> CType: ...
207+
def unpack(self, cdata: CData, length: int) -> bytes | str | list[Any]: ...
208+
209+
def alignof(__cdecl: CType) -> int: ...
210+
def callback(
211+
__cdecl: CType,
212+
__python_callable: Callable[..., _T],
213+
__error: Any = ...,
214+
__onerror: Callable[[Exception, Any, Any], None] | None = ...,
215+
) -> Callable[..., _T]: ...
216+
def cast(__cdecl: CType, __value: _CDataBase) -> _CDataBase: ...
217+
def complete_struct_or_union(
218+
__cdecl: CType,
219+
__fields: list[tuple[str, CType, int, int]],
220+
__ignored: Any,
221+
__total_size: int,
222+
__total_alignment: int,
223+
__sflags: int,
224+
__pack: int,
225+
) -> None: ...
226+
@overload
227+
def from_buffer(__cdecl: CType, __python_buffer: ReadableBuffer, require_writable: Literal[False] = ...) -> _CDataBase: ...
228+
@overload
229+
def from_buffer(__cdecl: CType, __python_buffer: WriteableBuffer, require_writable: Literal[True]) -> _CDataBase: ...
230+
def from_handle(__x: _CDataBase) -> Any: ...
231+
@overload
232+
def gcp(cdata: _CDataBase, destructor: Callable[[_CDataBase], Any], size: int = ...) -> _CDataBase: ...
233+
@overload
234+
def gcp(cdata: _CDataBase, destructor: None, size: int = ...) -> None: ...
235+
def get_errno() -> int: ...
236+
def getcname(__cdecl: CType, __replace_with: str) -> str: ...
237+
238+
if sys.platform == "win32":
239+
def getwinerror(code: int = ...) -> tuple[int, str]: ...
240+
241+
if sys.platform == "win32":
242+
def load_library(__libpath: str | _CDataBase, __flags: int = ...) -> CLibrary: ...
243+
244+
else:
245+
def load_library(__libpath: str | _CDataBase | None = ..., __flags: int = ...) -> CLibrary: ...
246+
247+
def memmove(dest: _CDataBase | WriteableBuffer, src: _CDataBase | ReadableBuffer, n: int) -> None: ...
248+
def new_array_type(__cdecl: CType, __length: int | None) -> CType: ...
249+
def new_enum_type(__name: str, __enumerators: tuple[str, ...], __enumvalues: tuple[Any, ...], __basetype: CType) -> CType: ...
250+
def new_function_type(__args: tuple[CType, ...], __result: CType, __ellipsis: int, __abi: int) -> CType: ...
251+
def new_pointer_type(__cdecl: CType) -> CType: ...
252+
def new_primitive_type(__name: str) -> CType: ...
253+
def new_struct_type(__name: str) -> CType: ...
254+
def new_union_type(__name: str) -> CType: ...
255+
def new_void_type() -> CType: ...
256+
def newp(__cdecl: CType, __init: Any = ...) -> _CDataBase: ...
257+
def newp_handle(__cdecl: CType, __x: Any) -> _CDataBase: ...
258+
def rawaddressof(__cdecl: CType, __cdata: _CDataBase, __offset: int) -> _CDataBase: ...
259+
def release(__cdata: _CDataBase) -> None: ...
260+
def set_errno(__errno: int) -> None: ...
261+
def sizeof(__cdecl: CType | _CDataBase) -> int: ...
262+
def string(cdata: _CDataBase, maxlen: int) -> bytes | str: ...
263+
def typeof(__cdata: _CDataBase) -> CType: ...
264+
def typeoffsetof(__cdecl: CType, __fieldname: str | int, __following: bool = ...) -> tuple[CType, int]: ...
265+
def unpack(cdata: _CDataBase, length: int) -> bytes | str | list[Any]: ...

stubs/cffi/cffi/__init__.pyi

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
from .api import FFI as FFI
2+
from .error import (
3+
CDefError as CDefError,
4+
FFIError as FFIError,
5+
VerificationError as VerificationError,
6+
VerificationMissing as VerificationMissing,
7+
)
8+
9+
__version__: str
10+
__version_info__: tuple[int, int, int]
11+
__version_verifier_modules__: str

0 commit comments

Comments
 (0)