disnake icon indicating copy to clipboard operation
disnake copied to clipboard

typing: add `io.StringIO` as supported file-like object to `disnake.File`

Open Enegg opened this issue 2 years ago • 9 comments

Summary

Adds support for passing io.StringIO to disnake.File Closes #765

Checklist

  • [ ] If code changes were made, then they have been tested
    • [ ] I have updated the documentation to reflect the changes
    • [x] I have formatted the code properly by running task lint
    • [ ] I have type-checked the code by running task pyright
  • [ ] This PR fixes an issue
  • [x] This PR adds something new (e.g. new method or parameters)
  • [ ] This PR is a breaking change (e.g. methods or parameters removed/renamed)
  • [ ] This PR is not a code change (e.g. documentation, README, ...)

Enegg avatar Sep 26 '22 13:09 Enegg

Might be worth considering replacing the union of Union[io.TextIOBase, io.BufferedIOBase] with io.IOBase.

Enegg avatar Sep 26 '22 13:09 Enegg

I don't know about this - as pyright already complains, this breaks a few places that expect bytes but now receive bytes | str. Making disnake.File generic over the self.fp type could fix typing issues but still doesn't really help enforce it at runtime.

For the io.StringIO case in particular: aiohttp effectively handles that using stream.read().encode() (code), arguably something that's easy to do in user code as well.

shiftinv avatar Oct 03 '22 23:10 shiftinv

I don't know about this - as pyright already complains, this breaks a few places that expect bytes but now receive bytes | str. Making disnake.File generic over the self.fp type could fix typing issues but still doesn't really help enforce it at runtime.

For the io.StringIO case in particular: aiohttp effectively handles that using stream.read().encode() (code), arguably something that's easy to do in user code as well.

So you suggest not to change the typing, and instead have the user do something like disnake.File(BytesIO(text_file.read().encode()))?

Enegg avatar Oct 04 '22 15:10 Enegg

So you suggest not to change the typing, and instead have the user do something like disnake.File(BytesIO(text_file.read().encode()))?

I can't think of many scenarios where one can get a string stream but not a bytes stream, in the simplest case it's a matter of changing open(..., "r") to open(..., "rb"). From the looks of it, this is primarily a typing issue and supporting string streams in disnake.File isn't trivial, and there's a tradeoff to be made between library complexity and usability :/ Perhaps @onerandomusername or @EQUENOS can chip in, there might be other ideas for resolving this.

shiftinv avatar Oct 05 '22 23:10 shiftinv

I can't think of many scenarios where one can get a string stream but not a bytes stream

My primary use case is creating an in-memory text file from a string with io.StringIO; It's useful when message length surpasses 2000 char limit

Enegg avatar Oct 08 '22 16:10 Enegg

Just commenting for the record, I'd also plus 1 this feature as something I use within bots to save arbitrary writes to disk

Skelmis avatar Feb 22 '23 20:02 Skelmis

@shiftinv I forgot about this PR; how about we special-case io.StringIO as acceptable fp to File, and encode the contents to BytesIO

Enegg avatar Mar 27 '23 08:03 Enegg

Since this topic came up again yesterday, I looked into this more; somehow missed the last comment here, sorry. I've partially implemented both approaches (generic file/encode bytes->str) here, and the Generic one is pretty jank, to say the least.

how about we special-case io.StringIO as acceptable fp to File, and encode the contents to BytesIO

Yeah, this seems like the better option. aiohttp ends up doing almost the same thing internally if you pass StringIO directly, so this should be fine?

shiftinv avatar Aug 26 '23 16:08 shiftinv

Do we have anything further on this PR? Seems like a usable resolution is fairly close

Skelmis avatar May 10 '24 08:05 Skelmis