@@ -226,30 +226,60 @@ def callback(request):
226226
227227 responses .add_callback (responses .GET , URL , callback = callback )
228228 # Explicitly request gzip encoding
229- reader = smart_open .http .SeekableBufferedInputBase (
230- URL , headers = {'Accept-Encoding' : 'gzip' }
231- )
229+ reader = smart_open .http .SeekableBufferedInputBase (URL , headers = {'Accept-Encoding' : 'gzip' })
232230 read_bytes = reader .read ()
233231 assert read_bytes == BYTES # Should be decompressed by requests/urllib3
234232
233+ # Combining multiple read calls also works
234+ reader .seek (0 )
235+ partial = reader .read (2 ) + reader .read (1000 )
236+ assert partial == BYTES
237+
235238
236239@responses .activate
237- def test_gzip_consistency_between_read_methods ():
238- """Regression test: read() and read(size) should return same decompressed data."""
239- def callback (request ):
240- # Server returns gzipped data when client accepts it
241- if 'gzip' in request .headers .get ('Accept-Encoding' , '' ):
242- headers = HEADERS .copy ()
243- headers ['Content-Encoding' ] = 'gzip'
244- headers ['Content-Length' ] = str (len (GZIPPED_BYTES ))
245- return (200 , headers , GZIPPED_BYTES )
246- else :
247- headers = HEADERS .copy ()
248- headers ['Content-Length' ] = str (len (BYTES ))
249- return (200 , headers , BYTES )
240+ def test_read_after_read_to_eof ():
241+ """Reading after reading to EOF should return empty bytes."""
242+ responses .add_callback (responses .GET , URL , callback = request_callback )
243+ reader = smart_open .http .SeekableBufferedInputBase (URL )
250244
251- responses .add_callback (responses .GET , URL , callback = callback )
252- reader = smart_open .http .SeekableBufferedInputBase (URL , headers = {'Accept-Encoding' : 'gzip' })
253- partial = reader .read (2 ) + reader .read ()
254- assert len (partial ) == len (BYTES ), f"Expected { len (BYTES )} bytes, got { len (partial )} "
255- assert partial == BYTES
245+ # Read to EOF
246+ result = reader .read (- 1 )
247+ assert len (result ) == len (BYTES )
248+ assert reader .tell () == len (BYTES )
249+
250+ # Read should return empty bytes
251+ result = reader .read ()
252+ assert result == b""
253+
254+ # Read with size should also return empty bytes
255+ result = reader .read (10 )
256+ assert result == b""
257+
258+
259+ @responses .activate
260+ def test_read_after_seek_to_eof ():
261+ """Reading after seeking to EOF should return empty bytes."""
262+ responses .add_callback (responses .GET , URL , callback = request_callback )
263+ reader = smart_open .http .SeekableBufferedInputBase (URL )
264+
265+ # Seek to EOF
266+ reader .seek (0 , whence = smart_open .constants .WHENCE_END )
267+ assert reader .tell () == len (BYTES )
268+
269+ # Read should return empty bytes
270+ result = reader .read ()
271+ assert result == b""
272+
273+ # Read with size should also return empty bytes
274+ result = reader .read (10 )
275+ assert result == b""
276+
277+
278+ @responses .activate
279+ def test_read_with_invalid_size ():
280+ """Read with size < -1 should raise ValueError."""
281+ responses .add_callback (responses .GET , URL , callback = request_callback )
282+ reader = smart_open .http .SeekableBufferedInputBase (URL )
283+
284+ with pytest .raises (ValueError , match = 'size must be >= -1' ):
285+ reader .read (- 2 )
0 commit comments