You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Allow multiple separators in Stream.readuntil #81322
Text-based protocols sometimes allow a choice of newline separator - I work with one that allows either \r or \n. Unfortunately that doesn't work with StreamReader.readuntil, which only accepts a single separator, so I've had to do some hacky things to obtain lines without having to
From discussion in bpo-32052, it sounded like extending StreamReader.readuntil to support a tuple of separators would be feasible.
Docs will be updated soon.
The change has landed a week ago, I had no time for docs update before 3.8 beta. Sorry for that.
The idea is: StreamReader and StreamWriter are merged into just Stream, open_connection() is replaced with connect() etc.
bmerry commented on Jun 3, 2019
bmerrymannequin
MannequinAuthor
More actions
Ok. Does the new Stream still have a similar interface for readuntil i.e. is this still a relevant request against the new API? I'm happy to let deprecated APIs stay as-is.
Yes, Stream supports all StreamReader and StreamWriter methods
bmerry commented on Jun 3, 2019
bmerrymannequin
MannequinAuthor
More actions
Ok, I've changed the issue title to refer to Stream. Since this would be a new feature, I assume it's off the table for 3.8, but I'll see if I get time to implement a PR in time for 3.9 (and get someone at work to sign off on the contributor agreement, which might be the harder part).
I finally have permission from my employer to sign the contributors agreement, so I'll take a stab at this when I have some free time (unless nobody else gets to it first).
There's one detail in a different repo that you may want to get ahead of. There's a declaration for this method in typeshed; ideally we should update this conditionally with a check for sys.version_info.
There's one detail in a different repo that you may want to get ahead of. There's a declaration for this method in typeshed; ideally we should update this conditionally with a check for sys.version_info.
Thanks for the reminder - I'd meant to ask about typeshed but forgot. I'll sort out a PR there when I get a chance.
Looking at the typeshed entry for readuntil is giving me second thoughts about this PR. In typeshed, it's written like this:
# Can be any buffer that supports len(); consider changing to a Protocol if PEP 688 is acceptedasyncdefreaduntil(self, separator: bytes|bytearray|memoryview=b"\n") ->bytes: ...
On the other hand, in this PR the new use case is detected like this:
ifisinstance(separator, bytes):
separator= [separator]
else:
# Makes sure shortest matches wins, and supports arbitrary iterablesseparator=sorted(separator, key=len)
So I think this PR will actually break the existing use case of passing a bytearray (or memoryview), because it would be incorrectly interpreted as an iterable of separators rather than a single separator.
@gvanrossum any thoughts on how to better decide whether we've been passed a single separator or an iterable of them? Perhaps instead of isinstance(separator, bytes), one could test hasattr(separator, "__buffer__")isinstance(separator, collections.abc.Buffer)? Or would it be better to introduce a new parameter (or new method) to make the user tell us the intention instead of guessing?
@gvanrossum any thoughts on how to better decide whether we've been passed a single separator or an iterable of them? Perhaps instead of isinstance(separator, bytes), one could test hasattr(separator, "__buffer__")isinstance(separator, collections.abc.Buffer)? Or would it be better to introduce a new parameter (or new method) to make the user tell us the intention instead of guessing?
Well, my intuition would be to only allow tuples -- this follows the lead of e.g. str.startswith():
Well, my intuition would be to only allow tuples -- this follows the lead of e.g. str.startswith():
I can see the appeal in that. It's also consistent with isinstance which takes tuples and not lists.
If someone does pass a list, they're probably going to get a cryptic error message; so it would be nice if we could detect incorrect usage. So maybe if it's not a tuple AND it's not a collections.abc.Buffer, raise a helpful TypeError?
If someone does pass a list, they're probably going to get a cryptic error message; so it would be nice if we could detect incorrect usage. So maybe if it's not a tuple AND it's not a collections.abc.Buffer, raise a helpful TypeError?
Maybe, though I worry about overthinking this. If they pass something incorrect they already get a cryptic error message (e.g. what if they pass a string?). Do we care? Probably not, as long as it doesn't silently do the wrong thing.
There's one detail in a different repo that you may want to get ahead of. There's a declaration for this method in typeshed; ideally we should update this conditionally with a check for sys.version_info.
Activity
bmerry commentedon Jun 3, 2019
Text-based protocols sometimes allow a choice of newline separator - I work with one that allows either \r or \n. Unfortunately that doesn't work with StreamReader.readuntil, which only accepts a single separator, so I've had to do some hacky things to obtain lines without having to
From discussion in bpo-32052, it sounded like extending StreamReader.readuntil to support a tuple of separators would be feasible.
asvetlov commentedon Jun 3, 2019
Would you make a PR?
I guess to modify Stream.readuntil()
StreamReader is deprecated, I'm not sure if we should add new functionality to this class.
bmerry commentedon Jun 3, 2019
I wasn't aware of that deprecation - it doesn't seem to be mentioned at https://docs.python.org/3.8/library/asyncio-stream.html. What is the replacement?
asvetlov commentedon Jun 3, 2019
Docs will be updated soon.
The change has landed a week ago, I had no time for docs update before 3.8 beta. Sorry for that.
The idea is: StreamReader and StreamWriter are merged into just Stream, open_connection() is replaced with connect() etc.
bmerry commentedon Jun 3, 2019
Ok. Does the new Stream still have a similar interface for readuntil i.e. is this still a relevant request against the new API? I'm happy to let deprecated APIs stay as-is.
asvetlov commentedon Jun 3, 2019
Yes, Stream supports all StreamReader and StreamWriter methods
bmerry commentedon Jun 3, 2019
Ok, I've changed the issue title to refer to Stream. Since this would be a new feature, I assume it's off the table for 3.8, but I'll see if I get time to implement a PR in time for 3.9 (and get someone at work to sign off on the contributor agreement, which might be the harder part).
Thanks for the quick and helpful responses.
[-]Allow multiple separators in StreamReader.readuntil[/-][+]Allow multiple separators in Stream.readuntil[/+]bmerry commentedon Sep 12, 2019
I finally have permission from my employer to sign the contributors agreement, so I'll take a stab at this when I have some free time (unless nobody else gets to it first).
asvetlov commentedon Sep 12, 2019
please do
12 remaining items
gh-81322: support multiple separators in StreamReader.readuntil (#16429)
gvanrossum commentedon Apr 8, 2024
Thanks again!
There's one detail in a different repo that you may want to get ahead of. There's a declaration for this method in typeshed; ideally we should update this conditionally with a check for
sys.version_info.bmerry commentedon Apr 8, 2024
Thanks for the reminder - I'd meant to ask about typeshed but forgot. I'll sort out a PR there when I get a chance.
bmerry commentedon Apr 8, 2024
Looking at the typeshed entry for
readuntilis giving me second thoughts about this PR. In typeshed, it's written like this:On the other hand, in this PR the new use case is detected like this:
So I think this PR will actually break the existing use case of passing a bytearray (or memoryview), because it would be incorrectly interpreted as an iterable of separators rather than a single separator.
@gvanrossum any thoughts on how to better decide whether we've been passed a single separator or an iterable of them? Perhaps instead of
isinstance(separator, bytes), one could testhasattr(separator, "__buffer__")isinstance(separator, collections.abc.Buffer)? Or would it be better to introduce a new parameter (or new method) to make the user tell us the intention instead of guessing?Fix Stream.readuntil with non-bytes buffer objects
bmerry commentedon Apr 8, 2024
I've opened #117653 to use
collections.abc.Bufferinstead ofbytesto decide the behaviour.gvanrossum commentedon Apr 8, 2024
Well, my intuition would be to only allow tuples -- this follows the lead of e.g.
str.startswith():bmerry commentedon Apr 8, 2024
I can see the appeal in that. It's also consistent with
isinstancewhich takes tuples and not lists.If someone does pass a list, they're probably going to get a cryptic error message; so it would be nice if we could detect incorrect usage. So maybe if it's not a tuple AND it's not a collections.abc.Buffer, raise a helpful TypeError?
gvanrossum commentedon Apr 8, 2024
Maybe, though I worry about overthinking this. If they pass something incorrect they already get a cryptic error message (e.g. what if they pass a string?). Do we care? Probably not, as long as it doesn't silently do the wrong thing.
bmerry commentedon Apr 10, 2024
I've created a patch to accept only tuples in #117723.
Add pythongh-81322 to Doc/whatsnew/3.13.rst
bmerry commentedon Apr 14, 2024
I've opened python/typeshed#11755
pythongh-81322: support multiple separators in StreamReader.readuntil (…