from pathlib import Path from typing import Union import pytest from _pytest.fixtures import SubRequest from _pytest.tmpdir import TempPathFactory from anyio import ClosedResourceError, EndOfStream from anyio.abc import ByteReceiveStream from anyio.streams.file import FileReadStream, FileStreamAttribute, FileWriteStream pytestmark = pytest.mark.anyio class TestFileReadStream: @pytest.fixture(scope='class') def file_path(self, tmp_path_factory: TempPathFactory) -> Path: path = tmp_path_factory.mktemp('filestream') / 'data.txt' path.write_text('Hello') return path @pytest.fixture(params=[False, True], ids=["str", "path"]) def file_path_or_str(self, request: SubRequest, file_path: Path) -> Union[Path, str]: return file_path if request.param else str(file_path) async def _run_filestream_test(self, stream: ByteReceiveStream) -> None: assert await stream.receive(3) == b'Hel' assert await stream.receive(3) == b'lo' with pytest.raises(EndOfStream): await stream.receive(1) async def test_read_file_as_path(self, file_path_or_str: Union[Path, str]) -> None: async with await FileReadStream.from_path(file_path_or_str) as stream: await self._run_filestream_test(stream) async def test_read_file(self, file_path: Path) -> None: with file_path.open('rb') as file: async with FileReadStream(file) as stream: await self._run_filestream_test(stream) async def test_read_after_close(self, file_path: Path) -> None: async with await FileReadStream.from_path(file_path) as stream: pass with pytest.raises(ClosedResourceError): await stream.receive() async def test_seek(self, file_path: Path) -> None: with file_path.open('rb') as file: async with FileReadStream(file) as stream: await stream.seek(2) assert await stream.tell() == 2 data = await stream.receive() assert data == b'llo' assert await stream.tell() == 5 async def test_extra_attributes(self, file_path: Path) -> None: async with await FileReadStream.from_path(file_path) as stream: path = stream.extra(FileStreamAttribute.path) assert path == file_path fileno = stream.extra(FileStreamAttribute.fileno) assert fileno > 2 file = stream.extra(FileStreamAttribute.file) assert file.fileno() == fileno class TestFileWriteStream: @pytest.fixture def file_path(self, tmp_path: Path) -> Path: return tmp_path / 'written_data.txt' async def test_write_file(self, file_path: Path) -> None: async with await FileWriteStream.from_path(file_path) as stream: await stream.send(b'Hel') await stream.send(b'lo') assert file_path.read_text() == 'Hello' async def test_append_file(self, file_path: Path) -> None: file_path.write_text('Hello') async with await FileWriteStream.from_path(file_path, True) as stream: await stream.send(b', World!') assert file_path.read_text() == 'Hello, World!' async def test_write_after_close(self, file_path: Path) -> None: async with await FileWriteStream.from_path(file_path, True) as stream: pass with pytest.raises(ClosedResourceError): await stream.send(b'foo') async def test_extra_attributes(self, file_path: Path) -> None: async with await FileWriteStream.from_path(file_path) as stream: path = stream.extra(FileStreamAttribute.path) assert path == file_path fileno = stream.extra(FileStreamAttribute.fileno) assert fileno > 2 file = stream.extra(FileStreamAttribute.file) assert file.fileno() == fileno