Skip to content

Commit 12f358d

Browse files
authored
Add test for seek to end + defer_seek (#901)
* Add test for seek to end + defer_seek * Disable helptext * Fix test * Re-enable helptext * Add upper pin for google-api-core
1 parent 5208ec4 commit 12f358d

File tree

4 files changed

+24
-6
lines changed

4 files changed

+24
-6
lines changed

.github/workflows/python-package.yml

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,7 @@ jobs:
2323
- {python-version: '3.9', os: windows-2025}
2424
- {python-version: '3.14', os: windows-2025}
2525

26-
# deprecate macos-15-intel when python 3.9 becomes the minimum supported version
27-
# ref https://github.blog/changelog/2025-09-19-github-actions-macos-13-runner-image-is-closing-down/
28-
# ref https://github.com/actions/python-versions/blob/d026dedcb/versions-manifest.json#L9969-L10016
29-
- {python-version: '3.9', os: macos-15-intel}
26+
- {python-version: '3.9', os: macos-15}
3027
- {python-version: '3.14', os: macos-15}
3128

3229
steps:

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ dependencies = ["wrapt"]
3434

3535
[project.optional-dependencies]
3636
s3 = ["boto3>=1.9.17"]
37-
gcs = ["google-cloud-storage>=2.6.0"]
37+
gcs = ["google-cloud-storage>=2.6.0", "google-api-core<2.28;python_version<'3.10'"] # https://github.com/googleapis/python-api-core/pull/832#issuecomment-3470137771
3838
azure = ["azure-storage-blob", "azure-common", "azure-core"]
3939
http = ["requests"]
4040
webhdfs = ["requests"]

smart_open/s3.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -531,7 +531,12 @@ def seek(self, offset, whence=constants.WHENCE_START):
531531
# If we can figure out that we've read past the EOF, then we can save
532532
# an extra API call.
533533
#
534-
if self._content_length is None:
534+
if start is None and stop == 0 and self._content_length is None:
535+
# seek(0, WHENCE_END) seeks straight to EOF: make a minimal request to populate _content_length
536+
self._open_body(start=0, stop=0)
537+
self.close()
538+
reached_eof = True
539+
elif self._content_length is None:
535540
reached_eof = False
536541
elif start is not None and start >= self._content_length:
537542
reached_eof = True

tests/test_s3.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,22 @@ def test_seek_end(self):
313313
self.assertEqual(seek, len(self.body) - 4)
314314
self.assertEqual(fin.read(), b'you?')
315315

316+
def test_seek_end_tell_without_defer_seek(self):
317+
"""Does seek(0, SEEK_END) + tell() work correctly without defer_seek?"""
318+
with self.assertApiCalls(GetObject=1): # One call during __init__
319+
fin = smart_open.s3.Reader(BUCKET_NAME, KEY_NAME, defer_seek=False)
320+
pos = fin.seek(0, whence=smart_open.constants.WHENCE_END)
321+
self.assertEqual(pos, len(self.body))
322+
self.assertEqual(fin.tell(), len(self.body))
323+
324+
def test_seek_end_tell_with_defer_seek(self):
325+
"""Does seek(0, SEEK_END) + tell() work correctly with defer_seek=True?"""
326+
with self.assertApiCalls(GetObject=1): # One call on first seek
327+
fin = smart_open.s3.Reader(BUCKET_NAME, KEY_NAME, defer_seek=True)
328+
pos = fin.seek(0, whence=smart_open.constants.WHENCE_END)
329+
self.assertEqual(pos, len(self.body))
330+
self.assertEqual(fin.tell(), len(self.body))
331+
316332
def test_seek_past_end(self):
317333
with self.assertApiCalls(GetObject=1), patch_invalid_range_response(str(len(self.body))):
318334
fin = smart_open.s3.Reader(BUCKET_NAME, KEY_NAME, defer_seek=True)

0 commit comments

Comments
 (0)