1
+ from __future__ import annotations
2
+
1
3
import io
2
4
import threading
3
5
import time
4
6
from contextlib import AbstractContextManager
5
7
from queue import Queue
6
- from typing import Optional
8
+ from types import TracebackType
9
+ from typing import TYPE_CHECKING , Any , Optional , overload
7
10
8
11
from ._pygit2 import Blob , Oid
9
12
from .enums import BlobFilter
10
13
14
+ if TYPE_CHECKING :
15
+ from _typeshed import WriteableBuffer
16
+
11
17
12
18
class _BlobIO (io .RawIOBase ):
13
19
"""Low-level wrapper for streaming blob content.
@@ -26,7 +32,7 @@ def __init__(
26
32
):
27
33
super ().__init__ ()
28
34
self ._blob = blob
29
- self ._queue = Queue (maxsize = 1 )
35
+ self ._queue : Queue [ bytes | None ] | None = Queue (maxsize = 1 )
30
36
self ._ready = threading .Event ()
31
37
self ._writer_closed = threading .Event ()
32
38
self ._chunk : Optional [bytes ] = None
@@ -42,10 +48,15 @@ def __init__(
42
48
)
43
49
self ._thread .start ()
44
50
45
- def __exit__ (self , exc_type , exc_value , traceback ):
51
+ def __exit__ (
52
+ self ,
53
+ exc_type : type [BaseException ] | None ,
54
+ exc_value : BaseException | None ,
55
+ traceback : TracebackType | None ,
56
+ ) -> None :
46
57
self .close ()
47
58
48
- def isatty ():
59
+ def isatty (self ):
49
60
return False
50
61
51
62
def readable (self ):
@@ -57,7 +68,14 @@ def writable(self):
57
68
def seekable (self ):
58
69
return False
59
70
60
- def readinto (self , b , / ):
71
+ # workaround for type checking
72
+ if TYPE_CHECKING :
73
+ @overload
74
+ def readinto (self , b : WriteableBuffer , / ) -> int : ... # type: ignore
75
+
76
+ def readinto (self , b : Any , / ) -> int :
77
+ if not self ._queue :
78
+ raise RuntimeError ('Blob I/O is closed' )
61
79
try :
62
80
while self ._chunk is None :
63
81
self ._ready .wait ()
@@ -96,7 +114,7 @@ def close(self):
96
114
self ._queue = None
97
115
98
116
99
- class BlobIO (io .BufferedReader , AbstractContextManager ):
117
+ class BlobIO (io .BufferedReader , AbstractContextManager [ 'BlobIO' ] ):
100
118
"""Read-only wrapper for streaming blob content.
101
119
102
120
Supports reading both raw and filtered blob content.
@@ -147,7 +165,12 @@ def __init__(
147
165
raw = _BlobIO (blob , as_path = as_path , flags = flags , commit_id = commit_id )
148
166
super ().__init__ (raw )
149
167
150
- def __exit__ (self , exc_type , exc_value , traceback ):
168
+ def __exit__ (
169
+ self ,
170
+ exc_type : type [BaseException ] | None ,
171
+ exc_value : BaseException | None ,
172
+ traceback : TracebackType | None ,
173
+ ) -> None :
151
174
self .close ()
152
175
153
176
0 commit comments