GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — gh-81322: support multiple separators in Stream.readuntil by bmerry · Pull Request #16429 · python/cpython

Conversation

@bmerry

@bmerry bmerry commented Sep 26, 2019 •
edited by bedevere-app Bot
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Contributor

Allow Stream.readuntil to take an iterable of separators and match any
of them. The earliest match endpoint wins (which ensures that results
are dependent on the chunking) and on ties shortest separator wins
(which only matters if the user has supplied a redundant set like
[b'\r\n', b'\n'] and the limit is reached).

It's also implemented for the deprecated StreamReader, just because the
code for the two implementations was the same except for one line and it
seemed easier to keep them in sync than leaving two different versions
to maintain.

https://bugs.python.org/issue37141

  • Issue: Allow multiple separators in Stream.readuntil #81322

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@bmerry
bmerry requested review from 1st1 and asvetlov as code owners September 26, 2019 16:02
@the-knights-who-say-ni the-knights-who-say-ni added the CLA signed label Sep 26, 2019
@bedevere-bot bedevere-bot added the awaiting review label Sep 26, 2019
@bmerry

bmerry commented Sep 26, 2019

Copy link
Copy Markdown
Contributor Author

A few questions about this:

  • I've implemented it for both StreamReader and Stream, because it seemed like having two identical (apart from _ensure_can_read) implementations is better for maintainability than two implementations that have drifted out of sync. But if one would prefer not to make any changes to StreamReader I can revert that. I suggest doing review discussion on the Stream implementation.
  • Because the existing functionality is implemented using the general case there might be a very small loss of performance. Are there any benchmarks I should run to test that?
  • For matches that end in the same position I arbitrarily decided that shortest should win for the purpose of LimitOverrunError, but it was an arbitrary choice. It could just as easily be longest-wins or first-in-list wins.
All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

bmerry
bmerry commented Sep 26, 2019
View reviewed changes
Comment thread Lib/asyncio/streams.py Outdated

@bmerry bmerry Sep 26, 2019

Copy link
Copy Markdown
Contributor Author

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I see this can make offset negative if max_seplen > min_seplen. I'll add a test to catch it and add a fix.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
brandtbucher
brandtbucher requested changes Sep 26, 2019
View reviewed changes

@brandtbucher brandtbucher left a comment

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for taking the time to draft this PR @bmerry, and welcome to CPython! 😎

I'm not super familiar with this module, but I found a couple of things that could be tidied up. Other than that, the code looks good! This will definitely need updated docs, though.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread Lib/asyncio/streams.py Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Lib/asyncio/streams.py Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Lib/asyncio/streams.py Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Lib/asyncio/streams.py Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Lib/asyncio/streams.py Outdated

@brandtbucher brandtbucher Sep 26, 2019

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See above.

Suggested change
raise ValueError('Separator list should contain at least one element')
raise ValueError('Separator should contain at least one element')

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread Lib/asyncio/streams.py Outdated

@brandtbucher brandtbucher Sep 26, 2019

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See above.

Suggested change
# where there is no occurrence of any separator.
# where there is no occurrence of any `separator`.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread Lib/asyncio/streams.py Outdated

@brandtbucher brandtbucher Sep 26, 2019

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See above.

Suggested change
# Loop until we find a separator in the buffer, exceed the buffer size,
# Loop until we find a `separator` in the buffer, exceed the buffer size,

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@bedevere-bot bedevere-bot added awaiting core review and removed awaiting review labels Sep 26, 2019
@brandtbucher brandtbucher added topic-asyncio type-feature A feature request or enhancement labels Sep 26, 2019
brandtbucher
brandtbucher reviewed Sep 26, 2019
View reviewed changes
Comment thread Lib/asyncio/streams.py Outdated

@brandtbucher brandtbucher Sep 26, 2019

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, missed one. Here too!

Suggested change
separator = sorted(separator, key=lambda sep: len(sep))
separator = sorted(separator, key=len)

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
1st1
1st1 requested changes Sep 26, 2019
View reviewed changes

@1st1 1st1 left a comment

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately it was decided to revert the current streams implementation from 3.8. See https://bugs.python.org/issue38242 for more details. I'm really sorry, but we'll need to rebase this work on the new API we later add to 3.9 :(

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@bedevere-bot bedevere-bot removed the awaiting core review label Sep 26, 2019
@bedevere-bot

bedevere-bot commented Sep 26, 2019

Copy link
Copy Markdown

A Python core developer has requested some changes be made to your pull request before we can consider merging it. If you could please address their requests along with any other requests in other reviews from core developers that would be appreciated.

Once you have made the requested changes, please leave a comment on this pull request containing the phrase I have made the requested changes; please review again. I will then notify any core developers who have left a review that you're ready for them to take another look at this pull request.

And if you don't make the requested changes, you will be poked with soft cushions!

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@bedevere-bot bedevere-bot added the awaiting changes label Sep 26, 2019
@bmerry

bmerry commented Sep 26, 2019

Copy link
Copy Markdown
Contributor Author

@1st1 not a problem - definitely worth getting things right before they go into stdlib. Do you think the revert of the new stream API will conflict much with my changes to the old StreamReader class? If not, perhaps the way forward is for me to remove my changes to Stream, address the PR comments on StreamReader and then hopefully it shouldn't need much work to rebase after Stream is removed?

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@1st1

1st1 commented Sep 26, 2019

Copy link
Copy Markdown
Member

@bmerry I'm not yet sure. I'll be working on a revert later today or tomorrow and will probably know more. I'd keep everything as is as it's not going to be an easy revert anyways.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@bmerry

bmerry commented Oct 3, 2019

Copy link
Copy Markdown
Contributor Author

@1st1 it looks like you've done the Streams reversion now, and I've merged that into my branch. So hopefully this is ready for review now.

@brandtbucher thanks for the suggestions. I've applied all the ones that Github was still showing after the merge from master - let me know if anything got lost along the way.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

brandtbucher
brandtbucher requested changes Oct 3, 2019
View reviewed changes

@brandtbucher brandtbucher left a comment •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One more tiny clarification from me, otherwise this looks good. Still needs updated docs though!

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread Misc/NEWS.d/next/Library/2019-09-26-17-52-52.bpo-37141.onYY2-.rst Resolved

Uh oh!

There was an error while loading. Please reload this page.

@bmerry

bmerry commented Oct 7, 2019

Copy link
Copy Markdown
Contributor Author

Still needs updated docs though!

@brandtbucher which docs need updating?

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@bmerry
bmerry requested a review from 1st1 October 7, 2019 15:51
@brandtbucher

brandtbucher commented Oct 8, 2019

Copy link
Copy Markdown
Member

Sorry about the delay @bmerry. The docs I'm referring to are located in Doc/library/asyncio-stream.rst. Specifically, here:

   .. coroutinemethod:: readuntil(separator=b'\\n')

      Read data from the stream until *separator* is found.

      On success, the data and separator will be removed from the
      internal buffer (consumed). Returned data will include the
      separator at the end.

      If the amount of data read exceeds the configured stream limit, a
      :exc:`LimitOverrunError` exception is raised, and the data
      is left in the internal buffer and can be read again.

      If EOF is reached before the complete separator is found,
      an :exc:`IncompleteReadError` exception is raised, and the internal
      buffer is reset.  The :attr:`IncompleteReadError.partial` attribute
      may contain a portion of the separator.

      .. versionadded:: 3.5.2

The signature and description should be updated. Also, something like this should be included below the .. versionadded:: 3.5.2 bit:

      .. versionchanged:: 3.9

         The *separator* parameter may now be an :term:`iterable` of separators.
All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

brandtbucher
brandtbucher requested changes Oct 8, 2019
View reviewed changes

@brandtbucher brandtbucher left a comment

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One tiny change to the NEWS entry due to the API revert:

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
brandtbucher
brandtbucher reviewed Oct 8, 2019
View reviewed changes
Comment thread Misc/NEWS.d/next/Library/2019-09-26-17-52-52.bpo-37141.onYY2-.rst Resolved

Uh oh!

There was an error while loading. Please reload this page.

@bmerry

bmerry commented Oct 9, 2019

Copy link
Copy Markdown
Contributor Author

The docs I'm referring to are located in Doc/library/asyncio-stream.rst

Thanks. I'd assumed the library docs were generated from the docstring, which is why I missed this. I'll update it.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@bmerry
bmerry requested a review from brandtbucher October 9, 2019 18:09
brandtbucher
brandtbucher approved these changes Oct 9, 2019
View reviewed changes
@brandtbucher

brandtbucher commented Oct 9, 2019

Copy link
Copy Markdown
Member

Looks good to me! @1st1?

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@1st1

1st1 commented Oct 9, 2019

Copy link
Copy Markdown
Member

We will soon start a discussion about the new streaming API for 3.9. I'll update this issue with a link when that happens; please give us some time before making a decision on this one -- Python 3.9 is still relatively far away.

brandtbucher reacted with thumbs up emoji
All reactions
  • 👍 1 reaction

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@ezio-melotti ezio-melotti removed the CLA signed label Jul 13, 2022
@bmerry bmerry mannequin mentioned this pull request Apr 10, 2022
Allow multiple separators in Stream.readuntil #81322
Closed
bmerry added 2 commits April 7, 2024 16:56
@bmerry
Merge remote-tracking branch 'origin/main' into multi-separator
d6e3508
@bmerry
Update version at which readuntil with separate list is supported
99e4fe2
@bmerry
bmerry requested review from gvanrossum, kumaraditya303 and willingc as code owners April 7, 2024 15:09
@gvanrossum
gvanrossum removed request for 1st1, aeros, asvetlov and kumaraditya303 April 7, 2024 15:42
@gvanrossum gvanrossum changed the title bpo-37141: support multiple separators in Stream.readuntil gh-81322: support multiple separators in Stream.readuntil Apr 7, 2024
@gvanrossum

gvanrossum commented Apr 7, 2024

Copy link
Copy Markdown
Member

Thanks, I will review in the coming week!

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

bmerry
bmerry commented Apr 8, 2024
View reviewed changes
Comment thread Misc/NEWS.d/next/Library/2019-09-26-17-52-52.bpo-37141.onYY2-.rst Resolved

Uh oh!

There was an error while loading. Please reload this page.

gvanrossum
gvanrossum approved these changes Apr 8, 2024
View reviewed changes

@gvanrossum gvanrossum left a comment

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One comment nit, I'll merge that myself and then land it. Thanks for your contribution, and on behalf of the asyncio maintainers I apologize for the delay!

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread Lib/asyncio/streams.py Resolved

Uh oh!

There was an error while loading. Please reload this page.

@bedevere-app bedevere-app Bot added awaiting merge and removed awaiting changes labels Apr 8, 2024
@gvanrossum
Fix comment
bee5ebe
len(separator) would be the number of separators, which makes no sense.
@gvanrossum
gvanrossum merged commit 775912a into python:main Apr 8, 2024
@bedevere-app bedevere-app Bot removed the awaiting merge label Apr 8, 2024
bmerry added a commit to bmerry/cpython that referenced this pull request Apr 8, 2024
@bmerry
Fix Stream.readuntil with non-bytes buffer objects
c364ee8
PR python#16429 introduced support for an iterable of separators in
Stream.readuntil. Since bytes-like types are themselves iterable, this
can introduce ambiguities in deciding whether the argument is an
iterator of separators or a singleton separator. In python#16429, only 'bytes'
was considered a singleton, but this will break code that passes other
buffer object types.

The Python library docs don't indicate what separator types were
permitted in Python <=3.12, but comments in typeshed indicate that it
would work with types that implement the buffer protocol and provide a
len(). To keep those cases working the way they did before, I've changed
the detection logic to consider any instance of collections.abc.Buffer
as a singleton separator.

There may still be corner cases where this doesn't do what the user
wants e.g. a numpy array of byte strings will implement the buffer
protocol and hence be treated as a singleton; but at least those corner
cases should behave the same in 3.13 as they did in 3.12.

Relates to python#81322.
@bmerry bmerry mentioned this pull request Apr 8, 2024
Fix Stream.readuntil with non-bytes buffer objects #117653
Closed
@bmerry
bmerry deleted the multi-separator branch April 8, 2024 19:09
@bmerry bmerry mentioned this pull request Apr 10, 2024
3.13.0a6 breaks asyncio.Stream.readuntil with bytearray separator #117722
Closed
bmerry added a commit to bmerry/cpython that referenced this pull request Apr 10, 2024
@bmerry
Fix Stream.readuntil with non-bytes buffer objects
0bac378
PR python#16429 introduced support for an iterable of separators in
Stream.readuntil. Since bytes-like types are themselves iterable, this
can introduce ambiguities in deciding whether the argument is an
iterator of separators or a singleton separator. In python#16429, only 'bytes'
was considered a singleton, but this will break code that passes other
buffer object types.

Fix it by only supporting tuples rather than arbitrary iterables.

Closes python#117722.
@bmerry bmerry mentioned this pull request Apr 10, 2024
gh-117722: Fix Stream.readuntil with non-bytes buffer objects #117723
Merged
gvanrossum pushed a commit that referenced this pull request Apr 11, 2024
@bmerry
gh-117722: Fix Stream.readuntil with non-bytes buffer objects (#117723)
01a51f9
gh-16429 introduced support for an iterable of separators in
Stream.readuntil. Since bytes-like types are themselves iterable, this
can introduce ambiguities in deciding whether the argument is an
iterator of separators or a singleton separator. In gh-16429, only 'bytes'
was considered a singleton, but this will break code that passes other
buffer object types.

Fix it by only supporting tuples rather than arbitrary iterables.

Closes gh-117722.
@bmerry bmerry mentioned this pull request Apr 14, 2024
Update asyncio.Stream.readuntil python/typeshed#11755
Merged
diegorusso pushed a commit to diegorusso/cpython that referenced this pull request Apr 17, 2024
@bmerry @diegorusso
pythongh-81322: support multiple separators in StreamReader.readuntil (…
23d0d4d
…python#16429)
diegorusso pushed a commit to diegorusso/cpython that referenced this pull request Apr 17, 2024
@bmerry @diegorusso
pythongh-117722: Fix Stream.readuntil with non-bytes buffer objects (p…
df40665
…ython#117723)

pythongh-16429 introduced support for an iterable of separators in
Stream.readuntil. Since bytes-like types are themselves iterable, this
can introduce ambiguities in deciding whether the argument is an
iterator of separators or a singleton separator. In pythongh-16429, only 'bytes'
was considered a singleton, but this will break code that passes other
buffer object types.

Fix it by only supporting tuples rather than arbitrary iterables.

Closes pythongh-117722.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

@1st1 1st1 1st1 requested changes
@gvanrossum gvanrossum gvanrossum approved these changes
@brandtbucher brandtbucher brandtbucher approved these changes
@willingc willingc Awaiting requested review from willingc willingc is a code owner

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

topic-asyncio type-feature A feature request or enhancement

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Uh oh!

There was an error while loading. Please reload this page.

8 participants

@bmerry @bedevere-bot @1st1 @brandtbucher @aeros @gvanrossum @the-knights-who-say-ni @ezio-melotti
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.