|
1 | 1 | import ctypes as ct |
2 | 2 | from _ctypes import CFuncPtr as PyCFuncPtr |
3 | 3 | from types import ModuleType |
4 | | -from typing import Generic, Literal, NoReturn, TypeAlias |
5 | | -from typing_extensions import CapsuleType, Never, Self, TypeVar, override |
| 4 | +from typing import ClassVar, Generic, Literal, NoReturn, Protocol, TypeAlias, final, overload, type_check_only |
| 5 | +from typing_extensions import CapsuleType as PyCapsule, Self, TypeVar, TypeVarTuple, Unpack, override |
6 | 6 |
|
7 | | -from cffi.model import FunctionPtrType as _CFFIFuncP, PointerType as _CFFIVoidP |
8 | | -from scipy._typing import Untyped |
| 7 | +# some quick interfaces for the relevant `cffi` types |
9 | 8 |
|
10 | | -_Function: TypeAlias = CapsuleType | PyCFuncPtr | _CFFIFuncP | CData |
11 | | -_UserData: TypeAlias = CapsuleType | ct.c_void_p | _CFFIVoidP |
| 9 | +@type_check_only |
| 10 | +@final |
| 11 | +class _CFFIBackendType(Protocol): |
| 12 | + cname: str |
| 13 | + kind: Literal[ |
| 14 | + "primitive", |
| 15 | + "bool", |
| 16 | + "int", |
| 17 | + "float", |
| 18 | + "char", |
| 19 | + "byte", |
| 20 | + "pointer", |
| 21 | + "charp", |
| 22 | + "bytep", |
| 23 | + "voidp", |
| 24 | + "generic", |
| 25 | + "struct", |
| 26 | + "union", |
| 27 | + "enum", |
| 28 | + "anonymous", |
| 29 | + "typedef", |
| 30 | + "function", |
| 31 | + ] |
| 32 | + |
| 33 | +_CTs = TypeVarTuple("_CTs", default=Unpack[tuple[_CFFIType, ...]]) |
| 34 | +_CT_co = TypeVar("_CT_co", covariant=True, bound=_CFFIType, default=_CFFIType) |
| 35 | + |
| 36 | +@type_check_only |
| 37 | +class _CFFIType(Protocol): |
| 38 | + is_array_type: ClassVar[bool] |
| 39 | + is_raw_function: ClassVar[bool] |
| 40 | + |
| 41 | + def is_integer_type(self, /) -> bool: ... |
| 42 | + def has_c_name(self, /) -> bool: ... |
| 43 | + def get_c_name(self, /, replace_with: str = "", context: str = "a C file", quals: int = 0) -> str: ... |
| 44 | + def get_cached_btype(self, ffi: object, finishlist: list[object], can_delay: bool = False) -> _CFFIBackendType: ... |
| 45 | + |
| 46 | + # virtual |
| 47 | + def build_backend_type(self, /, ffi: object, finishlist: list[object]) -> _CFFIBackendType: ... |
| 48 | + @property |
| 49 | + def c_name_with_marker(self, /) -> str: ... |
| 50 | + |
| 51 | +@type_check_only |
| 52 | +@final |
| 53 | +class _CFFIVoid(_CFFIType, Protocol): |
| 54 | + is_array_type: ClassVar = False |
| 55 | + is_raw_function: ClassVar = False |
| 56 | + |
| 57 | + def __init__(self, /) -> None: ... |
| 58 | + |
| 59 | +@type_check_only |
| 60 | +class _CFFIFunc(_CFFIType, Protocol[_CT_co, Unpack[_CTs]]): |
| 61 | + is_array_type: ClassVar = False |
| 62 | + |
| 63 | + @property |
| 64 | + def args(self, /) -> tuple[Unpack[_CTs]]: ... |
| 65 | + @property |
| 66 | + def result(self, /) -> _CT_co: ... |
| 67 | + @property |
| 68 | + def ellipsis(self, /) -> bool: ... |
| 69 | + @property |
| 70 | + def abi(self, /) -> int | str | None: ... |
| 71 | + def __init__(self, /, args: tuple[Unpack[_CTs]], result: _CT_co, ellipsis: bool, abi: int | None = None) -> None: ... |
| 72 | + |
| 73 | +@type_check_only |
| 74 | +@final |
| 75 | +class _CFFIFuncPtr(_CFFIFunc[_CT_co, Unpack[_CTs]], Protocol[_CT_co, Unpack[_CTs]]): |
| 76 | + is_raw_function: ClassVar = False |
| 77 | + |
| 78 | + def as_raw_function(self, /) -> _CFFIFunc[_CT_co, Unpack[_CTs]]: ... |
| 79 | + |
| 80 | +@type_check_only |
| 81 | +class _CFFIPointerType(_CFFIType, Protocol[_CT_co]): |
| 82 | + is_array_type: ClassVar = False |
| 83 | + is_raw_function: ClassVar = False |
| 84 | + |
| 85 | + @property |
| 86 | + def totype(self, /) -> _CT_co: ... |
| 87 | + @property |
| 88 | + def quals(self, /) -> int: ... |
| 89 | + def __init__(self, /, totype: _CT_co, quals: int = 0) -> None: ... |
| 90 | + |
| 91 | +_CFFIVoidP: TypeAlias = _CFFIPointerType[_CFFIVoid] |
| 92 | + |
| 93 | +# helper aliases |
| 94 | + |
| 95 | +_Function: TypeAlias = PyCapsule | PyCFuncPtr | _CFFIFuncPtr | CData |
| 96 | +_UserData: TypeAlias = PyCapsule | ct.c_void_p | _CFFIVoidP |
12 | 97 |
|
13 | 98 | _FuncT_co = TypeVar("_FuncT_co", bound=_Function, covariant=True, default=_Function) |
14 | | -_DataT_co = TypeVar("_DataT_co", bound=_UserData | None, covariant=True, default=_UserData) |
| 99 | +_DataT = TypeVar("_DataT", bound=_UserData | None) |
| 100 | +_DataT_co = TypeVar("_DataT_co", bound=_UserData | None, covariant=True, default=None) |
15 | 101 |
|
16 | 102 | ffi: Literal[False] | None |
17 | 103 |
|
| 104 | +# public api |
| 105 | + |
| 106 | +@final |
18 | 107 | class CData: ... |
19 | 108 |
|
20 | | -class LowLevelCallable(tuple[CapsuleType, _FuncT_co, _DataT_co], Generic[_FuncT_co, _DataT_co]): |
| 109 | +class LowLevelCallable(tuple[PyCapsule, _FuncT_co, _DataT_co], Generic[_FuncT_co, _DataT_co]): |
21 | 110 | @property |
22 | 111 | def function(self, /) -> _FuncT_co: ... |
23 | 112 | @property |
24 | 113 | def user_data(self, /) -> _DataT_co: ... |
25 | 114 | @property |
26 | 115 | def signature(self, /) -> str: ... |
27 | | - def __new__( |
| 116 | + @overload |
| 117 | + def __new__(cls, function: Self, user_data: _DataT_co | None = None, signature: str | None = None) -> Self: ... |
| 118 | + @overload |
| 119 | + def __new__(cls, function: _FuncT_co, user_data: _DataT_co = ..., signature: str | None = None) -> Self: ... |
| 120 | + @classmethod |
| 121 | + @overload |
| 122 | + def from_cython( |
28 | 123 | cls, |
29 | | - function: _FuncT_co | LowLevelCallable[_FuncT_co, _DataT_co], |
30 | | - user_data: Untyped | None = None, |
| 124 | + module: ModuleType, |
| 125 | + name: str, |
| 126 | + user_data: None = None, |
31 | 127 | signature: str | None = None, |
32 | | - ) -> Self: ... |
| 128 | + ) -> LowLevelCallable[PyCapsule, None]: ... |
33 | 129 | @classmethod |
| 130 | + @overload |
34 | 131 | def from_cython( |
35 | 132 | cls, |
36 | 133 | module: ModuleType, |
37 | 134 | name: str, |
38 | | - user_data: _UserData | None = None, |
| 135 | + user_data: _DataT, |
39 | 136 | signature: str | None = None, |
40 | | - ) -> Self: ... |
| 137 | + ) -> LowLevelCallable[PyCapsule, _DataT]: ... |
41 | 138 |
|
42 | 139 | # NOTE: `__getitem__` will always raise a `ValueError` |
43 | 140 | @override |
44 | | - def __getitem__(self, idx: Never, /) -> NoReturn: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] |
| 141 | + def __getitem__(self, idx: object, /) -> NoReturn: ... |
0 commit comments