From b7f87f5e5e87143cabb838b20240cdf884e2f00b Mon Sep 17 00:00:00 2001 From: Aleksander Maksimeniuk <78569692+alexhook@users.noreply.github.com> Date: Tue, 9 Jan 2024 11:36:20 +0300 Subject: [PATCH] fix: wrote bytes to csv file to avoid utf-8 decode error (#441) --- pybotx/async_buffer.py | 5 ----- pybotx/bot/bot.py | 25 ++++++++++++++++++------- pybotx/client/users_api/users_as_csv.py | 14 ++++---------- pyproject.toml | 2 +- 4 files changed, 23 insertions(+), 23 deletions(-) diff --git a/pybotx/async_buffer.py b/pybotx/async_buffer.py index d43d0593..d5e8a8a5 100644 --- a/pybotx/async_buffer.py +++ b/pybotx/async_buffer.py @@ -20,11 +20,6 @@ async def write(self, content: bytes) -> int: ... # noqa: WPS428 -class AsyncBufferUnicodeWritable(AsyncBufferBase): - async def write(self, content: str) -> int: - ... # noqa: WPS428 - - class AsyncBufferReadable(AsyncBufferBase): async def read(self, bytes_to_read: Optional[int] = None) -> bytes: ... # noqa: WPS428 diff --git a/pybotx/bot/bot.py b/pybotx/bot/bot.py index c7f40da3..79f9f332 100644 --- a/pybotx/bot/bot.py +++ b/pybotx/bot/bot.py @@ -16,8 +16,10 @@ ) from uuid import UUID +import aiofiles import httpx -from aiofiles.tempfile import SpooledTemporaryFile +from aiocsv.readers import AsyncDictReader +from aiofiles.tempfile import NamedTemporaryFile, TemporaryDirectory from pydantic import ValidationError, parse_obj_as from pybotx.async_buffer import AsyncBufferReadable, AsyncBufferWritable @@ -198,7 +200,7 @@ BotXAPIUsersAsCSVRequestPayload, UsersAsCSVMethod, ) -from pybotx.constants import BOTX_DEFAULT_TIMEOUT, CHUNK_SIZE, STICKER_PACKS_PER_PAGE +from pybotx.constants import BOTX_DEFAULT_TIMEOUT, STICKER_PACKS_PER_PAGE from pybotx.converters import optional_sequence_to_list from pybotx.image_validators import ( ensure_file_content_is_png, @@ -1348,11 +1350,20 @@ async def users_as_csv( botx=botx, ) - async with SpooledTemporaryFile(max_size=CHUNK_SIZE, mode="w+") as async_buffer: - yield ( - BotXAPIUserFromCSVResult(**row).to_domain() - async for row in await method.execute(payload, async_buffer) - ) + async with TemporaryDirectory() as tmpdir: + async with NamedTemporaryFile( + mode="wb", + dir=tmpdir, + delete=False, + ) as write_buffer: + write_buffer_path = write_buffer.name + await method.execute(payload, write_buffer) + + async with aiofiles.open(write_buffer_path, mode="r") as read_buffer: + yield ( + BotXAPIUserFromCSVResult(**row).to_domain() + async for row in AsyncDictReader(read_buffer) + ) # - SmartApps API - async def send_smartapp_event( diff --git a/pybotx/client/users_api/users_as_csv.py b/pybotx/client/users_api/users_as_csv.py index 2054d38f..1393a91e 100644 --- a/pybotx/client/users_api/users_as_csv.py +++ b/pybotx/client/users_api/users_as_csv.py @@ -1,6 +1,4 @@ -from aiocsv.readers import AsyncDictReader - -from pybotx.async_buffer import AsyncBufferUnicodeWritable +from pybotx.async_buffer import AsyncBufferWritable from pybotx.client.authorized_botx_method import AuthorizedBotXMethod from pybotx.client.botx_method import response_exception_thrower from pybotx.client.exceptions.users import NoUserKindSelectedError @@ -35,8 +33,8 @@ class UsersAsCSVMethod(AuthorizedBotXMethod): async def execute( self, payload: BotXAPIUsersAsCSVRequestPayload, - async_buffer: AsyncBufferUnicodeWritable, - ) -> AsyncDictReader: + async_buffer: AsyncBufferWritable, + ) -> None: path = "/api/v3/botx/users/users_as_csv" async with self._botx_method_stream( @@ -46,8 +44,4 @@ async def execute( ) as response: # https://github.com/nedbat/coveragepy/issues/1223 async for chunk in response.aiter_bytes(): # pragma: no cover - await async_buffer.write(chunk.decode()) - - await async_buffer.seek(0) - - return AsyncDictReader(async_buffer) # type: ignore[arg-type] + await async_buffer.write(chunk) diff --git a/pyproject.toml b/pyproject.toml index 2ac7ebf8..aade9513 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "pybotx" -version = "0.61.1" +version = "0.61.2" description = "A python library for interacting with eXpress BotX API" authors = [ "Sidnev Nikolay ",