Skip to content

Commit

Permalink
fix: wrote bytes to csv file to avoid utf-8 decode error (#441)
Browse files Browse the repository at this point in the history
  • Loading branch information
alexhook committed Jan 9, 2024
1 parent d11b47e commit b7f87f5
Show file tree
Hide file tree
Showing 4 changed files with 23 additions and 23 deletions.
5 changes: 0 additions & 5 deletions pybotx/async_buffer.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
25 changes: 18 additions & 7 deletions pybotx/bot/bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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(
Expand Down
14 changes: 4 additions & 10 deletions pybotx/client/users_api/users_as_csv.py
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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(
Expand All @@ -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)
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -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 <nsidnev@ccsteam.ru>",
Expand Down

0 comments on commit b7f87f5

Please sign in to comment.