22import io
33import socket
44from io import SEEK_END
5- from typing import Optional , Union
5+ from typing import Optional
66
77from ..exceptions import ConnectionError , TimeoutError
88from ..utils import SSL_AVAILABLE
99
10- NONBLOCKING_EXCEPTION_ERROR_NUMBERS = {BlockingIOError : errno .EWOULDBLOCK }
10+ NONBLOCKING_EXCEPTION_ERROR_NUMBERS : dict [type [OSError ], int ] = {
11+ BlockingIOError : errno .EWOULDBLOCK
12+ }
1113
1214if SSL_AVAILABLE :
1315 import ssl
2123NONBLOCKING_EXCEPTIONS = tuple (NONBLOCKING_EXCEPTION_ERROR_NUMBERS .keys ())
2224
2325SERVER_CLOSED_CONNECTION_ERROR = "Connection closed by server."
24- SENTINEL = object ()
2526
2627SYM_CRLF = b"\r \n "
2728
2829
2930class SocketBuffer :
3031 def __init__ (
31- self , socket : socket .socket , socket_read_size : int , socket_timeout : float
32+ self , sock : socket .socket , socket_read_size : int , socket_timeout : float
3233 ):
33- self ._sock = socket
34+ self ._sock = sock
3435 self .socket_read_size = socket_read_size
3536 self .socket_timeout = socket_timeout
3637 self ._buffer = io .BytesIO ()
38+ self ._closed = False
3739
3840 def unread_bytes (self ) -> int :
3941 """
@@ -47,13 +49,13 @@ def unread_bytes(self) -> int:
4749 def _read_from_socket (
4850 self ,
4951 length : Optional [int ] = None ,
50- timeout : Union [float , object ] = SENTINEL ,
52+ timeout : Optional [float ] = None ,
5153 raise_on_timeout : Optional [bool ] = True ,
5254 ) -> bool :
5355 sock = self ._sock
5456 socket_read_size = self .socket_read_size
5557 marker = 0
56- custom_timeout = timeout is not SENTINEL
58+ custom_timeout = timeout is not None
5759
5860 buf = self ._buffer
5961 current_pos = buf .tell ()
@@ -92,11 +94,14 @@ def _read_from_socket(
9294 sock .settimeout (self .socket_timeout )
9395
9496 def can_read (self , timeout : float ) -> bool :
95- return bool (self .unread_bytes ()) or self ._read_from_socket (
96- timeout = timeout , raise_on_timeout = False
97+ return not self ._closed and (
98+ bool (self .unread_bytes ())
99+ or self ._read_from_socket (timeout = timeout , raise_on_timeout = False )
97100 )
98101
99102 def read (self , length : int ) -> bytes :
103+ if self ._closed :
104+ raise ConnectionError ("Socket is closed" )
100105 length = length + 2 # make sure to read the \r\n terminator
101106 # BufferIO will return less than requested if buffer is short
102107 data = self ._buffer .read (length )
@@ -108,6 +113,8 @@ def read(self, length: int) -> bytes:
108113 return data [:- 2 ]
109114
110115 def readline (self ) -> bytes :
116+ if self ._closed :
117+ raise ConnectionError ("Socket is closed" )
111118 buf = self ._buffer
112119 data = buf .readline ()
113120 while not data .endswith (SYM_CRLF ):
@@ -151,12 +158,12 @@ def purge(self) -> None:
151158 def close (self ) -> None :
152159 try :
153160 self ._buffer .close ()
161+ self ._sock .close ()
154162 except Exception :
155163 # issue #633 suggests the purge/close somehow raised a
156164 # BadFileDescriptor error. Perhaps the client ran out of
157165 # memory or something else? It's probably OK to ignore
158166 # any error being raised from purge/close since we're
159167 # removing the reference to the instance below.
160168 pass
161- self ._buffer = None
162- self ._sock = None
169+ self ._closed = True
0 commit comments