diff --git a/starlette/datastructures.py b/starlette/datastructures.py index 1a8b965e8..3f32a7f23 100644 --- a/starlette/datastructures.py +++ b/starlette/datastructures.py @@ -455,11 +455,17 @@ async def read(self, size: int = -1) -> bytes: return self.file.read(size) return await run_in_threadpool(self.file.read, size) - async def seek(self, offset: int) -> None: + async def seek(self, offset: int, whence: int = 0) -> None: if self._in_memory: - self.file.seek(offset) + self.file.seek(offset, whence) else: - await run_in_threadpool(self.file.seek, offset) + await run_in_threadpool(self.file.seek, offset, whence) + + async def tell(self) -> int: + if self._in_memory: + return self.file.tell() + else: + return await run_in_threadpool(self.file.tell) async def close(self) -> None: if self._in_memory: diff --git a/tests/test_datastructures.py b/tests/test_datastructures.py index b110aa8bd..fb7549feb 100644 --- a/tests/test_datastructures.py +++ b/tests/test_datastructures.py @@ -1,4 +1,5 @@ import io +import os import pytest @@ -220,9 +221,20 @@ class BigUploadFile(UploadFile): @pytest.mark.anyio async def test_upload_file(): big_file = BigUploadFile("big-file") - await big_file.write(b"big-data" * 512) await big_file.write(b"big-data") + assert (await big_file.tell()) == 8 await big_file.seek(0) + assert (await big_file.tell()) == 0 + await big_file.seek(0, os.SEEK_END) + assert (await big_file.tell()) == 8 + await big_file.write(b"big-data" * 511) + await big_file.write(b"big-data") + pos = await big_file.tell() + assert pos > 512 * len(b"big-data") + await big_file.seek(-10, os.SEEK_CUR) + assert (await big_file.tell()) == pos - 10 + await big_file.seek(0) + assert (await big_file.tell()) == 0 assert await big_file.read(1024) == b"big-data" * 128 await big_file.close()