diff --git a/newsfragments/3541.bugfix.rst b/newsfragments/3541.bugfix.rst new file mode 100644 index 000000000..cf5cb8f83 --- /dev/null +++ b/newsfragments/3541.bugfix.rst @@ -0,0 +1 @@ +Type checkers now accept the optional ``hint`` argument to asynchronous files' ``readlines()`` method, matching the underlying synchronous file API. diff --git a/src/trio/_file_io.py b/src/trio/_file_io.py index d9305ef4f..edf1c3da0 100644 --- a/src/trio/_file_io.py +++ b/src/trio/_file_io.py @@ -334,7 +334,7 @@ async def read1(self: AsyncIOWrapper[_CanRead1], size: int | None = -1, /) -> by async def readall(self: AsyncIOWrapper[_CanReadAll[AnyStr]]) -> AnyStr: ... async def readinto(self: AsyncIOWrapper[_CanReadInto], buf: Buffer, /) -> int | None: ... async def readline(self: AsyncIOWrapper[_CanReadLine[AnyStr]], size: int = -1, /) -> AnyStr: ... - async def readlines(self: AsyncIOWrapper[_CanReadLines[AnyStr]]) -> list[AnyStr]: ... + async def readlines(self: AsyncIOWrapper[_CanReadLines[AnyStr]], hint: int = -1, /) -> list[AnyStr]: ... async def seek(self: AsyncIOWrapper[_CanSeek], target: int, whence: int = 0, /) -> int: ... async def tell(self: AsyncIOWrapper[_CanTell]) -> int: ... async def truncate(self: AsyncIOWrapper[_CanTruncate], size: int | None = None, /) -> int: ... diff --git a/src/trio/_tests/test_file_io.py b/src/trio/_tests/test_file_io.py index 390a81ce6..0251b2a75 100644 --- a/src/trio/_tests/test_file_io.py +++ b/src/trio/_tests/test_file_io.py @@ -199,6 +199,16 @@ async def test_async_methods_wrap( wrapped.reset_mock() +async def test_readlines_hint() -> None: + """Readlines forwards its hint and keeps the remaining lines available.""" + async with trio.wrap_file(io.StringIO("first\nsecond\nthird\n")) as text_file: + assert await text_file.readlines(1) == ["first\n"] + assert await text_file.readlines() == ["second\n", "third\n"] + async with trio.wrap_file(io.BytesIO(b"first\nsecond\nthird\n")) as binary_file: + assert await binary_file.readlines(1) == [b"first\n"] + assert await binary_file.readlines() == [b"second\n", b"third\n"] + + def test_async_methods_match_wrapper( async_file: AsyncIOWrapper[mock.Mock], wrapped: mock.Mock, diff --git a/src/trio/_tests/type_tests/path.py b/src/trio/_tests/type_tests/path.py index 2b956c931..1db2be85a 100644 --- a/src/trio/_tests/type_tests/path.py +++ b/src/trio/_tests/type_tests/path.py @@ -138,3 +138,6 @@ async def open_results(path: trio.Path, some_int: int, some_str: str) -> None: assert_type(await file_text.write("test"), int) # TODO: report mypy bug: equiv to https://github.com/microsoft/pyright/issues/6833 assert_type(await file_text.readlines(), list[str]) + assert_type(await file_text.readlines(10), list[str]) + assert_type(await file_text.readlines(-1), list[str]) + assert_type(await file_bin.readlines(10), list[bytes])