Skip to content
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

work around the changes in 3.11, eg asyncio.TimeoutError is an OSError, and IsolatedAsyncioTestCase calls set_event_loop differently #6877

Merged
merged 7 commits into from
Aug 22, 2022

Conversation

graingert
Copy link
Contributor

@graingert graingert commented Aug 9, 2022

What do these changes do?

Fixes #6757

Are there changes in behavior for the user?

yeah, if someone overrides asyncSetUp/asyncTearDown in their tests it could cause confusion

Related issue number

Checklist

  • I think the code is well written
  • Unit tests for the changes exist
  • Documentation reflects the changes
  • If you provide code modification, please add yourself to CONTRIBUTORS.txt
    • The format is <Name> <Surname>.
    • Please keep alphabetical order, the file is sorted by names.
  • Add a new news fragment into the CHANGES folder
    • name it <issue_id>.<type> for example (588.bugfix)
    • if you don't have an issue_id change it to the pr id after creating the pr
    • ensure type is one of the following:
      • .feature: Signifying a new feature.
      • .bugfix: Signifying a bug fix.
      • .doc: Signifying a documentation improvement.
      • .removal: Signifying a deprecation or removal of public API.
      • .misc: A ticket has been closed, but it is not of interest to users.
    • Make sure to use full sentences with correct case and punctuation, for example: "Fix issue with non-ascii contents in doctest text files."

@graingert
Copy link
Contributor Author

might break it for 3.7, but probably possible to fix with a sys.version_info condition

aiohttp/test_utils.py Outdated Show resolved Hide resolved
@codecov

This comment was marked as outdated.

@graingert
Copy link
Contributor Author

@webknjaz I think this fixes the issue with TestCase, but now there's a TimeoutError problem instead

@graingert graingert marked this pull request as ready for review August 9, 2022 07:31
@graingert graingert requested a review from asvetlov as a code owner August 9, 2022 07:31
in 3.11 asyncio.TimeoutError became an OSError
aiohttp/client_reqrep.py Outdated Show resolved Hide resolved
aiohttp/client_reqrep.py Outdated Show resolved Hide resolved
@graingert
Copy link
Contributor Author

I think I've been a bit too liberal with my except TimeoutError clauses, it's only really needed if there's a timeout contextmanager or asyncio.wait_for in the try

aiohttp/client.py Outdated Show resolved Hide resolved
aiohttp/connector.py Outdated Show resolved Hide resolved
aiohttp/connector.py Outdated Show resolved Hide resolved
aiohttp/connector.py Outdated Show resolved Hide resolved
aiohttp/connector.py Outdated Show resolved Hide resolved
aiohttp/connector.py Outdated Show resolved Hide resolved
@psf-chronographer psf-chronographer bot added the bot:chronographer:provided There is a change note present in this PR label Aug 9, 2022
@graingert graingert changed the title try fixing AioHTTPTestCase for 3.11 work around the changes in 3.11, eg asyncio.TimeoutError is an OSError, and IsolatedAsyncioTestCase calls set_event_loop differently Aug 9, 2022
@@ -532,6 +532,8 @@ async def _request(
except ClientError:
raise
except OSError as exc:
if exc.errno is None and isinstance(exc, asyncio.TimeoutError):
Copy link
Member

Choose a reason for hiding this comment

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

Could you explain the is None check? Is it just a performance optimization? Why'd you drop the separate block idea?

Copy link
Contributor Author

@graingert graingert Aug 9, 2022

Choose a reason for hiding this comment

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

So this is for the case when you get a real OSError with an errno that's also a TimeoutError

I thought about checking for type(TimeoutError.__cause__) is CancelledError but your timeout context manager doesn't set the cause and neither does _chain_future

Then to my dismay if you do:

a, b = socket.socketpair()
with a, b:
    a.settimeout(0.1)
    a.recv(1)

You still get a TimeoutError with a None .errno so there's no way to actually tell if you have a real operating system TimeoutError or a synthetic one from asyncio

This is why trio uses trio.TooSlowError so it's a bit more clear

Copy link
Member

Choose a reason for hiding this comment

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

Maybe worth checking if asyncio.timeout() has the same problem. We could start migrating from async-timeout to that in Python 3.11+.
https://docs.python.org/3.11/library/asyncio-task.html#timeouts

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Would be good if we can all agree on some

class TooSlowError(asyncio.TimeoutError):
   ...

Copy link
Member

Choose a reason for hiding this comment

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

Ah, it still uses the same logic from async-timeout:
https://github.com/python/cpython/blob/main/Lib/asyncio/timeouts.py#L98

You'd have to take that up with the cpython issue tracker, or @asvetlov.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Copy link
Member

@Dreamsorcerer Dreamsorcerer Aug 9, 2022

Choose a reason for hiding this comment

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

So, if that gets merged, what does the code here become (assuming we've switched away from async-timeout)?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixing _chain_future needs to happen first, but we can check the __cause__ to see if it's an asyncio Timeout rather than an OS timeout

Copy link
Member

Choose a reason for hiding this comment

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

Just coming back round to this, I see the change is now in Python 3.12+. Can we update these checks with a sys.version_info check, so we don't forget about it completely?

@Dreamsorcerer
Copy link
Member

Note to self: After this is merged, we should remove .loop, asyncTearDown and asyncSetUp from master branch.

@Dreamsorcerer
Copy link
Member

I think this looks fine as is, for a temporary fix to get 3.11 working. We can come back and update this with another PR once we can do the __cause__ check.

CHANGES/6757.misc Outdated Show resolved Hide resolved
@webknjaz webknjaz merged commit 5bf9b4a into aio-libs:master Aug 22, 2022
@patchback
Copy link
Contributor

patchback bot commented Aug 22, 2022

Backport to 3.8: 💔 cherry-picking failed — conflicts found

❌ Failed to cleanly apply 5bf9b4a on top of patchback/backports/3.8/5bf9b4aae7046704b418c16452c2d1ced934abfb/pr-6877

Backporting merged PR #6877 into master

  1. Ensure you have a local repo clone of your fork. Unless you cloned it
    from the upstream, this would be your origin remote.
  2. Make sure you have an upstream repo added as a remote too. In these
    instructions you'll refer to it by the name upstream. If you don't
    have it, here's how you can add it:
    $ git remote add upstream https://github.com/aio-libs/aiohttp.git
  3. Ensure you have the latest copy of upstream and prepare a branch
    that will hold the backported code:
    $ git fetch upstream
    $ git checkout -b patchback/backports/3.8/5bf9b4aae7046704b418c16452c2d1ced934abfb/pr-6877 upstream/3.8
  4. Now, cherry-pick PR work around the changes in 3.11, eg asyncio.TimeoutError is an OSError, and IsolatedAsyncioTestCase calls set_event_loop differently #6877 contents into that branch:
    $ git cherry-pick -x 5bf9b4aae7046704b418c16452c2d1ced934abfb
    If it'll yell at you with something like fatal: Commit 5bf9b4aae7046704b418c16452c2d1ced934abfb is a merge but no -m option was given., add -m 1 as follows intead:
    $ git cherry-pick -m1 -x 5bf9b4aae7046704b418c16452c2d1ced934abfb
  5. At this point, you'll probably encounter some merge conflicts. You must
    resolve them in to preserve the patch from PR work around the changes in 3.11, eg asyncio.TimeoutError is an OSError, and IsolatedAsyncioTestCase calls set_event_loop differently #6877 as close to the
    original as possible.
  6. Push this branch to your fork on GitHub:
    $ git push origin patchback/backports/3.8/5bf9b4aae7046704b418c16452c2d1ced934abfb/pr-6877
  7. Create a PR, ensure that the CI is green. If it's not — update it so that
    the tests and any other checks pass. This is it!
    Now relax and wait for the maintainers to process your pull request
    when they have some cycles to do reviews. Don't worry — they'll tell you if
    any improvements are necessary when the time comes!

🤖 @patchback
I'm built with octomachinery and
my source is open — https://github.com/sanitizers/patchback-github-app.

@patchback
Copy link
Contributor

patchback bot commented Aug 22, 2022

Backport to 3.9: 💔 cherry-picking failed — conflicts found

❌ Failed to cleanly apply 5bf9b4a on top of patchback/backports/3.9/5bf9b4aae7046704b418c16452c2d1ced934abfb/pr-6877

Backporting merged PR #6877 into master

  1. Ensure you have a local repo clone of your fork. Unless you cloned it
    from the upstream, this would be your origin remote.
  2. Make sure you have an upstream repo added as a remote too. In these
    instructions you'll refer to it by the name upstream. If you don't
    have it, here's how you can add it:
    $ git remote add upstream https://github.com/aio-libs/aiohttp.git
  3. Ensure you have the latest copy of upstream and prepare a branch
    that will hold the backported code:
    $ git fetch upstream
    $ git checkout -b patchback/backports/3.9/5bf9b4aae7046704b418c16452c2d1ced934abfb/pr-6877 upstream/3.9
  4. Now, cherry-pick PR work around the changes in 3.11, eg asyncio.TimeoutError is an OSError, and IsolatedAsyncioTestCase calls set_event_loop differently #6877 contents into that branch:
    $ git cherry-pick -x 5bf9b4aae7046704b418c16452c2d1ced934abfb
    If it'll yell at you with something like fatal: Commit 5bf9b4aae7046704b418c16452c2d1ced934abfb is a merge but no -m option was given., add -m 1 as follows intead:
    $ git cherry-pick -m1 -x 5bf9b4aae7046704b418c16452c2d1ced934abfb
  5. At this point, you'll probably encounter some merge conflicts. You must
    resolve them in to preserve the patch from PR work around the changes in 3.11, eg asyncio.TimeoutError is an OSError, and IsolatedAsyncioTestCase calls set_event_loop differently #6877 as close to the
    original as possible.
  6. Push this branch to your fork on GitHub:
    $ git push origin patchback/backports/3.9/5bf9b4aae7046704b418c16452c2d1ced934abfb/pr-6877
  7. Create a PR, ensure that the CI is green. If it's not — update it so that
    the tests and any other checks pass. This is it!
    Now relax and wait for the maintainers to process your pull request
    when they have some cycles to do reviews. Don't worry — they'll tell you if
    any improvements are necessary when the time comes!

🤖 @patchback
I'm built with octomachinery and
my source is open — https://github.com/sanitizers/patchback-github-app.

webknjaz added a commit to webknjaz/aiohttp that referenced this pull request Aug 22, 2022
(cherry picked from commit 5bf9b4a)
webknjaz added a commit to webknjaz/aiohttp that referenced this pull request Sep 7, 2022
(cherry picked from commit 5bf9b4a)
webknjaz added a commit to webknjaz/aiohttp that referenced this pull request Sep 7, 2022
(cherry picked from commit 5bf9b4a)
webknjaz added a commit that referenced this pull request Sep 7, 2022
(cherry picked from commit 5bf9b4a)
webknjaz added a commit that referenced this pull request Sep 7, 2022
(cherry picked from commit 5bf9b4a)
@webknjaz
Copy link
Member

webknjaz commented Sep 7, 2022

Backported as fd7a29e and ae40e98.

Comment on lines -435 to -436
except RuntimeError:
self.loop = asyncio.get_event_loop_policy().get_event_loop()
Copy link
Member

Choose a reason for hiding this comment

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

This bit needed to be recovered in aiohttp v3.8 to preserve the compatibility with Python 3.6: ef6a373.

@webknjaz webknjaz mentioned this pull request Dec 7, 2022
1 task
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bot:chronographer:provided There is a change note present in this PR
Projects
None yet
3 participants