28
28
import contextlib
29
29
import os
30
30
from types import TracebackType
31
- from typing import TYPE_CHECKING , Any , Generic , TypeVar , cast
31
+ from typing import TYPE_CHECKING , Any , Generic , TypeAlias , TypeVar , cast , overload
32
32
33
33
# Import from pygit2
34
34
from .ffi import C , ffi
35
35
36
36
if TYPE_CHECKING :
37
+ from _cffi_backend import _CDataBase as CData
37
38
from _typeshed import SupportsLenAndGetItem
38
39
39
40
_T = TypeVar ('_T' )
41
+ StrOrBytesOrPathLike : TypeAlias = str | bytes | os .PathLike [str ] | os .PathLike [bytes ]
40
42
41
43
42
- def maybe_string (ptr : Any ) -> str | None :
44
+ def maybe_string (ptr : CData | Any ) -> str | None :
43
45
if not ptr :
44
46
return None
45
47
@@ -49,20 +51,33 @@ def maybe_string(ptr: Any) -> str | None:
49
51
return out
50
52
51
53
52
- def to_bytes (s : Any , encoding : str = 'utf-8' , errors : str = 'strict' ) -> bytes | Any :
54
+ # Cannot describe ffi.NULL, so using CData
55
+
56
+
57
+ @overload
58
+ def to_bytes (s : CData | None ) -> CData : ...
59
+ @overload
60
+ def to_bytes (s : StrOrBytesOrPathLike ) -> bytes : ...
61
+
62
+
63
+ def to_bytes (
64
+ s : StrOrBytesOrPathLike | CData | None ,
65
+ encoding : str = 'utf-8' ,
66
+ errors : str = 'strict' ,
67
+ ) -> bytes | CData :
53
68
if s == ffi .NULL or s is None :
54
69
return ffi .NULL
55
70
56
- if hasattr (s , '__fspath__' ):
71
+ if isinstance (s , os . PathLike ):
57
72
s = os .fspath (s )
58
73
59
74
if isinstance (s , bytes ):
60
75
return s
61
76
62
- return s .encode (encoding , errors )
77
+ return cast ( str , s ) .encode (encoding , errors )
63
78
64
79
65
- def to_str (s : Any ) -> str :
80
+ def to_str (s : StrOrBytesOrPathLike ) -> str :
66
81
if hasattr (s , '__fspath__' ):
67
82
s = os .fspath (s )
68
83
@@ -75,14 +90,18 @@ def to_str(s: Any) -> str:
75
90
raise TypeError (f'unexpected type "{ repr (s )} "' )
76
91
77
92
93
+ def buffer_to_bytes (cdata : CData ) -> bytes :
94
+ buf = ffi .buffer (cdata )
95
+ return cast (bytes , buf [:])
96
+
97
+
78
98
def ptr_to_bytes (ptr_cdata : Any ) -> bytes :
79
99
"""
80
100
Convert a pointer coming from C code (<cdata 'some_type *'>)
81
101
to a byte buffer containing the address that the pointer refers to.
82
102
"""
83
103
84
- pp = ffi .new ('void **' , ptr_cdata )
85
- return bytes (ffi .buffer (pp )[:]) # type: ignore
104
+ return buffer_to_bytes (ffi .new ('void **' , ptr_cdata ))
86
105
87
106
88
107
@contextlib .contextmanager
0 commit comments