From 8e27c044b5e84df3678a5ec79405b40e3e387c4b Mon Sep 17 00:00:00 2001 From: Aleksa Sarai Date: Mon, 7 Oct 2024 23:12:41 +1100 Subject: [PATCH] python bindings: make type annotations for CString and CBuffer less magical In order to avoid having magical types that only exist during type-checking, define CString and CBytes in the main _pathrs module and import them into the _libpathrs_cffi type stubs. Unfortunately, the straight-forward way of doing this (using a TypeAlias of _libpathrs_cffi.ffi.CData) doesn't work for some reason so we need to do a little bit of magic when TYPE_CHECKING to make mypy happy. But at least this is a little bit less magical than the previous version (where some variables only existed when type-checking). Signed-off-by: Aleksa Sarai --- .../python/pathrs/_libpathrs_cffi/lib.pyi | 3 +-- contrib/bindings/python/pathrs/_pathrs.py | 23 ++++++++++++++----- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/contrib/bindings/python/pathrs/_libpathrs_cffi/lib.pyi b/contrib/bindings/python/pathrs/_libpathrs_cffi/lib.pyi index 3949a856..e28521be 100644 --- a/contrib/bindings/python/pathrs/_libpathrs_cffi/lib.pyi +++ b/contrib/bindings/python/pathrs/_libpathrs_cffi/lib.pyi @@ -21,8 +21,7 @@ from typing import Optional, overload, type_check_only, Union # TODO: Remove this once we only support Python >= 3.10. from typing_extensions import TypeAlias, Literal -CBuffer: TypeAlias = cffi.FFI.CData # char[n] -CString: TypeAlias = cffi.FFI.CData # char * +from .._pathrs import CBuffer, CString # pathrs_errorinfo_t * @type_check_only diff --git a/contrib/bindings/python/pathrs/_pathrs.py b/contrib/bindings/python/pathrs/_pathrs.py index 1d07f5f8..0eff1f49 100644 --- a/contrib/bindings/python/pathrs/_pathrs.py +++ b/contrib/bindings/python/pathrs/_pathrs.py @@ -26,11 +26,22 @@ import typing from typing import Any, IO, Optional, TextIO, Union # TODO: Remove this once we only support Python >= 3.11. -from typing_extensions import Self +from typing_extensions import Self, TypeAlias -from ._libpathrs_cffi import ffi, lib as libpathrs_so if typing.TYPE_CHECKING: - from ._libpathrs_cffi.lib import CBuffer, CString # type stubs + # mypy apparently cannot handle the "ffi: cffi.api.FFI" definition in + # _libpathrs_cffi/__init__.pyi so we need to explicitly reference the type + # from cffi here. + import cffi + ffi: cffi.FFI + CString: TypeAlias = cffi.FFI.CData + CBuffer: TypeAlias = cffi.FFI.CData +else: + from ._libpathrs_cffi import ffi + CString: TypeAlias = ffi.CData + CBuffer: TypeAlias = ffi.CData + +from ._libpathrs_cffi import lib as libpathrs_so __all__ = [ # core api @@ -42,15 +53,15 @@ "Error", ] -def _cstr(pystr: str) -> "CString": +def _cstr(pystr: str) -> CString: return ffi.new("char[]", pystr.encode("utf8")) -def _pystr(cstr: "CString") -> str: +def _pystr(cstr: CString) -> str: s = ffi.string(cstr) assert isinstance(s, bytes) # typing return s.decode("utf8") -def _cbuffer(size: int) -> "CBuffer": +def _cbuffer(size: int) -> CBuffer: return ffi.new("char[%d]" % (size,))