Skip to content

Create common interface for aio response classes #1328

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 4 commits into from

Conversation

stj
Copy link
Contributor

@stj stj commented Apr 21, 2025

Having the parse method async on all parsers means the need for checking that parse is a coroutine is not needed anymore. The check for coroutine or not moved into the parser where a private method can be async or sync. This cleans up the public interface of the aio response classes.

Description of Change

Change is extracted out of pull #1323 after a review comment ask for it.

Assumptions

Replace this text with any assumptions made (if any)

Checklist for All Submissions

  • I have added change info to CHANGES.rst
  • If this is resolving an issue (needed so future developers can determine if change is still necessary and under what conditions) (can be provided via link to issue with these details):
    • Detailed description of issue
    • Alternative methods considered (if any)
    • How issue is being resolved
    • How issue can be reproduced
  • If this is providing a new feature (can be provided via link to issue with these details):
    • Detailed description of new feature
    • Why needed
    • Alternatives methods considered (if any)

Checklist when updating botocore and/or aiohttp versions

Having the `parse` method async on all parsers means
the need for checking that `parse` is a coroutine is not needed
anymore. The check for coroutine or not moved into the parser where
a private method can be async or sync. This cleans up the public
interface of the aio response classes.
@stj stj mentioned this pull request Apr 21, 2025
13 tasks
Copy link

codecov bot commented Apr 21, 2025

Codecov Report

Attention: Patch coverage is 88.00000% with 3 lines in your changes missing coverage. Please review.

Project coverage is 90.79%. Comparing base (d7c1092) to head (b490745).

Files with missing lines Patch % Lines
aiobotocore/parsers.py 90.90% 2 Missing ⚠️
aiobotocore/response.py 0.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1328      +/-   ##
==========================================
- Coverage   90.79%   90.79%   -0.01%     
==========================================
  Files          68       68              
  Lines        6553     6548       -5     
==========================================
- Hits         5950     5945       -5     
  Misses        603      603              
Flag Coverage Δ
unittests 90.79% <88.00%> (-0.01%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@jakob-keller

This comment was marked as resolved.

@jakob-keller jakob-keller self-assigned this Apr 21, 2025
@jakob-keller jakob-keller added the enhancement New feature or request label Apr 21, 2025
@jakob-keller

This comment was marked as resolved.

@stj stj requested review from thehesiod and jakob-keller April 21, 2025 16:41
@jakob-keller
Copy link
Collaborator

Looks good to me! Would you mind adding an entry to CHANGES.rst?

@stj
Copy link
Contributor Author

stj commented Apr 21, 2025

How does

refactor AioResponseParser to have a consistent async implementation of the parse method.

sound for a changelog entry? It communicates a change and where it is, though doesn't say what the implications are for aiobotocore users. Is parse a public interface?

@jakob-keller

This comment was marked as resolved.

jakob-keller
jakob-keller previously approved these changes Apr 21, 2025
@jakob-keller jakob-keller enabled auto-merge April 21, 2025 18:46
Comment on lines 207 to 209
parsed_response = await parser.parse(
response_dict, operation_model.output_shape
)
Copy link
Collaborator

Choose a reason for hiding this comment

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

have we validated across all the parsers this is now true? Are there parsers that don't inherit from our baseclass?

Copy link
Collaborator

Choose a reason for hiding this comment

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

i see everything parents to ResponseParser 👍🏼

Copy link
Collaborator

Choose a reason for hiding this comment

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

Good call!

Upstream has a number of parsers that we have not patched:

  • BaseXMLResponseParser
  • BaseJSONParser
  • BaseEventStreamParser
  • EventStreamJSONParser
  • EventStreamXMLParser
  • BaseRestParser

The Base* parsers should be fine, since we patch any relevant child parsers. But I believe the EventStream* parsers might be problematic. They are used indirectly and might need to be patched to work correctly.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I could prepare a follow-up of #1312 to fully patch the parser class hierarchy. That would be a prerequisite for this PR, IMO. Any thoughts?

Copy link
Collaborator

Choose a reason for hiding this comment

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

#1329 makes sure that EVENT_STREAM_PARSER_CLS class attributes ("indirect" uses) point to patched parsers. Once that is merged, we can continue with this one.

Copy link
Collaborator

Choose a reason for hiding this comment

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

My belief atm is that not having an async version for EventStream* is fine.

I guess it would be, as long as we continue to allow for both sync and async variants of parse(). However, this PR takes away that flexibility and we need to be careful to handle all parser classes, as @thehesiod rightfully pointed out. As far as I understand, that includes parser classes that we have not patched previously, hence #1329. I could well be on the wrong track here, though.

An alternative would be to simply keep the current implementation of parse() and move it up the AioResponseParser, but leave everything else as it is.

Copy link
Collaborator

Choose a reason for hiding this comment

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

ya that's why I was waiting to do a review of this PR when I had some time, we need to thoroughly look at how these classes are used

Copy link
Collaborator

Choose a reason for hiding this comment

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

lets report back when one of us does that

Copy link
Contributor Author

Choose a reason for hiding this comment

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

How about allowing sync parse methods but emit a deprecation warning?

Copy link
Collaborator

Choose a reason for hiding this comment

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

sounds like a plan, would be safer

CHANGES.rst Outdated
@@ -5,6 +5,7 @@ Changes
^^^^^^^^^^^^^^^^^^^
* patch `ResponseParser`
* use SPDX license identifier for project metadata
* refactor `AioResponseParser` to have a consistent async implementation of the `parse` method.
Copy link
Member

Choose a reason for hiding this comment

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

It's RST

Suggested change
* refactor `AioResponseParser` to have a consistent async implementation of the `parse` method.
* refactor ``AioResponseParser`` to have a consistent async implementation of the ``parse`` method.

To avoid a breaking change the callers of a ResponseParser.parse method
yield a deprecation warning when a non-async method is found.
parsed_response = parser.parse(
response_dict, operation_model.output_shape
warnings.deprecated(
f"The use of non-async `parse` function on {parser.__class__.__name__} is deprecated."
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why not use type(parser).__name__?

)
else:
parsed = parser.parse(response_dict, operation_model.output_shape)
parsed = await parser.parse(response_dict, operation_model.output_shape)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Apply deprecation pattern from endpoints.py

Copy link
Collaborator

Choose a reason for hiding this comment

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

That test was slightly refactored in the default branch. Please do a rebase or merge in new commits.

@jakob-keller
Copy link
Collaborator

@stj: I discovered a few more quirks with regards to event streams and decided to created #1347 which is meant to supersede this PR. I hope you don't mind and thanks again for the work!

@jakob-keller
Copy link
Collaborator

Superseded by #1347

@stj stj deleted the override-AioResponseParser-parse branch April 29, 2025 18:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants