-
Notifications
You must be signed in to change notification settings - Fork 5.5k
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
Run tornado gen.coroutines in the context of a task. #2716
base: master
Are you sure you want to change the base?
Run tornado gen.coroutines in the context of a task. #2716
Conversation
54c86b4
to
1bd3e7b
Compare
1bd3e7b
to
8345ecd
Compare
Thank you @BrandonTheBuilder for contributing this PR! |
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 the contribution, and I apologize for being slow to review it. There's subtle code here and it needs a lot of attention.
This looks like it could have significant performance overhead: we now have both a Task and a Runner, we've lost the first_yielded
optimization, we're creating an asyncio.Event
for every yield, etc. Performance-sensitive code should be moving to native coroutines, but it's still undesirable to slow down decorated coroutines if we don't have to.
It looks to me like it might be simpler to make @coroutine
support contextvars
directly than to integrate it with asyncio tasks: save contextvars.copy_context()
when creating the runner, and use ctx.run
when we call back into the runner from add_future
. Have you looked into this possibility?
_step.set() | ||
|
||
self.io_loop.add_future(self.future, step) # type: ignore | ||
await _step.wait() |
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.
I would have expected this to be simply await self.future
. We might need to create an Event
for some edge cases (concurrent futures, or the moment
singleton), but most of the time I think awaiting the future directly would work.
if future is None: | ||
raise Exception("No pending future") | ||
if not self.future.done(): # type: ignore | ||
_step = asyncio.Event() |
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.
Style note: Tornado uses a leading underscore on "private" class/instance attributes, but local variables should just have plain names like step
.
This is some awesome feedback! I totally understand taking time to fully review this there is definitely a lot going on here. It does lose the first yield optimization, I had the same thought though that performance critical code should be using native coroutines. Using contextvars directly might solve this problem as well, and not lose the performance optimization. I will test it out and try to push something up for further review soon. |
Thanks for the PR. I'm trying to patch python-tornado (https://github.com/opentracing-contrib/python-tornado) and tornado 6 coroutines actually don't work with context vars. I tried this patch and it fixes the problem. Would be great if this patch or a different solution could be merged in. Removal of the stack context feature and coroutines not working with contextvars means there is no reliable way to pass contextual information down when using coroutines. I guess we know what the problem is here and how it manifests but I can post an demo app that shows how using contextvars doesn't work currently but works with this patch applied. LMK if that would be useful. Thanks. |
This PR adds support for Tornado 6 by conditionally using different scope manager, context manager and tracing implementation depending on the version of Tornado and Python being used. It does not require existing users to change anything other than upgrade to the latest version of this package. This package used to use the TornadoScopeManager shipped by opentracing-python. The scope manager used `tornado.stack_context` which was deprecated in Tornado 5 and removed in Tornado 6. Tornado now recommends using contextvars package introduced in Python3.7. opentracing-python already provides a ContextVarsScopeManager that builds on top of the contextvars package. It also implements AsyncioScopeManager which builds on top of asyncio and falls back on thread local storage to implement context propagation. We fallback on this for Python 3.6 and older when using Tornado 6 and newer. The package also had seen some decay and some tests were not passing. This PR updates the test suite and unit tests to get them working again. Changes this PR introduces: - Default to ContextVarsScopeManager instead of TornadoScopeManager. Fallback on TornadoScopeManager or AsyncioScopeManager based on the Tornado and Python version. - Added tox support to enable easier testing across Python and Tornado versions. - Updated travis config to work with tox environments. Now each travis build will run tests on every supported python version in parallel. Each parallel test will run all tests for all versions of tornado serially. - The PR add some code that uses the new async/await syntax. Such code is invalid for older versions of python. To make it works for all versions, we conditionally import modules depending on the Python interpreter version. - To preserve backward compatibility and to keep using common code for all tornado versions, we've added some noop implementations that are not to be used with newer versions of tornado. - `tornado.gen.coroutine` was deprecated in favour of async/await but we still support it where we can. There is a bug in Tornado 6 that prevents us from support the deprecated feature on Python3.7 with ContextVarsScopeManager. (tornadoweb/tornado#2716) - Python3.4 also does not pass the tests for `tornado.gen.coroutine` but it is not a regression caused by this PR. Testing on master results in the same behavior. For now, I've added skip markers to these tests on Python3.4. If needed, we can look into supporting these in future in a separate PR.
This PR adds support for Tornado 6 by conditionally using different scope manager, context manager and tracing implementation depending on the version of Tornado and Python being used. It does not require existing users to change anything other than upgrade to the latest version of this package. This package used to use the TornadoScopeManager shipped by opentracing-python. The scope manager used `tornado.stack_context` which was deprecated in Tornado 5 and removed in Tornado 6. Tornado now recommends using contextvars package introduced in Python3.7. opentracing-python already provides a ContextVarsScopeManager that builds on top of the contextvars package. It also implements AsyncioScopeManager which builds on top of asyncio and falls back on thread local storage to implement context propagation. We fallback on this for Python 3.6 and older when using Tornado 6 and newer. The package also had seen some decay and some tests were not passing. This PR updates the test suite and unit tests to get them working again. Changes this PR introduces: - Default to ContextVarsScopeManager instead of TornadoScopeManager. Fallback on TornadoScopeManager or AsyncioScopeManager based on the Tornado and Python version. - Added tox support to enable easier testing across Python and Tornado versions. - Updated travis config to work with tox environments. Now each travis build will run tests on every supported python version in parallel. Each parallel test will run all tests for all versions of tornado serially. - The PR add some code that uses the new async/await syntax. Such code is invalid for older versions of python. To make it works for all versions, we conditionally import modules depending on the Python interpreter version. - To preserve backward compatibility and to keep using common code for all tornado versions, we've added some noop implementations that are not to be used with newer versions of tornado. - `tornado.gen.coroutine` was deprecated in favour of async/await but we still support it where we can. There is a bug in Tornado 6 that prevents us from support the deprecated feature on Python3.7 with ContextVarsScopeManager. (tornadoweb/tornado#2716) - Python3.4 also does not pass the tests for `tornado.gen.coroutine` but it is not a regression caused by this PR. Testing on master results in the same behavior. For now, I've added skip markers to these tests on Python3.4. If needed, we can look into supporting these in future in a separate PR.
This PR adds support for Tornado 6 by conditionally using different scope manager, context manager and tracing implementation depending on the version of Tornado and Python being used. It does not require existing users to change anything other than upgrade to the latest version of this package. This package used to use the TornadoScopeManager shipped by opentracing-python. The scope manager used `tornado.stack_context` which was deprecated in Tornado 5 and removed in Tornado 6. Tornado now recommends using contextvars package introduced in Python3.7. opentracing-python already provides a ContextVarsScopeManager that builds on top of the contextvars package. It also implements AsyncioScopeManager which builds on top of asyncio and falls back on thread local storage to implement context propagation. We fallback on this for Python 3.6 and older when using Tornado 6 and newer. The package also had seen some decay and some tests were not passing. This PR updates the test suite and unit tests to get them working again. Changes this PR introduces: - Default to ContextVarsScopeManager instead of TornadoScopeManager. Fallback on TornadoScopeManager or AsyncioScopeManager based on the Tornado and Python version. - Added tox support to enable easier testing across Python and Tornado versions. - Updated travis config to work with tox environments. Now each travis build will run tests on every supported python version in parallel. Each parallel test will run all tests for all versions of tornado serially. - The PR add some code that uses the new async/await syntax. Such code is invalid for older versions of python. To make it works for all versions, we conditionally import modules depending on the Python interpreter version. - To preserve backward compatibility and to keep using common code for all tornado versions, we've added some noop implementations that are not to be used with newer versions of tornado. - `tornado.gen.coroutine` was deprecated in favour of async/await but we still support it where we can. There is a bug in Tornado 6 that prevents us from support the deprecated feature on Python3.7 with ContextVarsScopeManager. (tornadoweb/tornado#2716) - Python3.4 also does not pass the tests for `tornado.gen.coroutine` but it is not a regression caused by this PR. Testing on master results in the same behavior. For now, I've added skip markers to these tests on Python3.4. If needed, we can look into supporting these in future in a separate PR.
This PR adds support for Tornado 6 by conditionally using different scope manager, context manager and tracing implementation depending on the version of Tornado and Python being used. It does not require existing users to change anything other than upgrade to the latest version of this package. This package used to use the TornadoScopeManager shipped by opentracing-python. The scope manager used `tornado.stack_context` which was deprecated in Tornado 5 and removed in Tornado 6. Tornado now recommends using contextvars package introduced in Python3.7. opentracing-python already provides a ContextVarsScopeManager that builds on top of the contextvars package. It also implements AsyncioScopeManager which builds on top of asyncio and falls back on thread local storage to implement context propagation. We fallback on this for Python 3.6 and older when using Tornado 6 and newer. The package also had seen some decay and some tests were not passing. This PR updates the test suite and unit tests to get them working again. Changes this PR introduces: - Default to ContextVarsScopeManager instead of TornadoScopeManager. Fallback on TornadoScopeManager or AsyncioScopeManager based on the Tornado and Python version. - Added tox support to enable easier testing across Python and Tornado versions. - Updated travis config to work with tox environments. Now each travis build will run tests on every supported python version in parallel. Each parallel test will run all tests for all versions of tornado serially. - The PR add some code that uses the new async/await syntax. Such code is invalid for older versions of python. To make it works for all versions, we conditionally import modules depending on the Python interpreter version. - To preserve backward compatibility and to keep using common code for all tornado versions, we've added some noop implementations that are not to be used with newer versions of tornado. - `tornado.gen.coroutine` was deprecated in favour of async/await but we still support it where we can. There is a bug in Tornado 6 that prevents us from support the deprecated feature on Python3.7 with ContextVarsScopeManager. (tornadoweb/tornado#2716) - Python3.4 also does not pass the tests for `tornado.gen.coroutine` but it is not a regression caused by this PR. Testing on master results in the same behavior. For now, I've added skip markers to these tests on Python3.4. If needed, we can look into supporting these in future in a separate PR.
This PR adds support for Tornado 6 by conditionally using different scope manager, context manager and tracing implementation depending on the version of Tornado and Python being used. It does not require existing users to change anything other than upgrade to the latest version of this package. This package used to use the TornadoScopeManager shipped by opentracing-python. The scope manager used `tornado.stack_context` which was deprecated in Tornado 5 and removed in Tornado 6. Tornado now recommends using contextvars package introduced in Python3.7. opentracing-python already provides a ContextVarsScopeManager that builds on top of the contextvars package. It also implements AsyncioScopeManager which builds on top of asyncio and falls back on thread local storage to implement context propagation. We fallback on this for Python 3.6 and older when using Tornado 6 and newer. The package also had seen some decay and some tests were not passing. This PR updates the test suite and unit tests to get them working again. Changes this PR introduces: - Default to ContextVarsScopeManager instead of TornadoScopeManager. Fallback on TornadoScopeManager or AsyncioScopeManager based on the Tornado and Python version. - Added tox support to enable easier testing across Python and Tornado versions. - Updated travis config to work with tox environments. Now each travis build will run tests on every supported python version in parallel. Each parallel test will run all tests for all versions of tornado serially. - The PR add some code that uses the new async/await syntax. Such code is invalid for older versions of python. To make it works for all versions, we conditionally import modules depending on the Python interpreter version. - To preserve backward compatibility and to keep using common code for all tornado versions, we've added some noop implementations that are not to be used with newer versions of tornado. - `tornado.gen.coroutine` was deprecated in favour of async/await but we still support it where we can. There is a bug in Tornado 6 that prevents us from support the deprecated feature on Python3.7 with ContextVarsScopeManager. (tornadoweb/tornado#2716) - Python3.4 also does not pass the tests for `tornado.gen.coroutine` but it is not a regression caused by this PR. Testing on master results in the same behavior. For now, I've added skip markers to these tests on Python3.4. If needed, we can look into supporting these in future in a separate PR.
This PR adds support for Tornado 6 by conditionally using different scope manager, context manager and tracing implementation depending on the version of Tornado and Python being used. It does not require existing users to change anything other than upgrade to the latest version of this package. This package used to use the TornadoScopeManager shipped by opentracing-python. The scope manager used `tornado.stack_context` which was deprecated in Tornado 5 and removed in Tornado 6. Tornado now recommends using contextvars package introduced in Python3.7. opentracing-python already provides a ContextVarsScopeManager that builds on top of the contextvars package. It also implements AsyncioScopeManager which builds on top of asyncio and falls back on thread local storage to implement context propagation. We fallback on this for Python 3.6 and older when using Tornado 6 and newer. The package also had seen some decay and some tests were not passing. This PR updates the test suite and unit tests to get them working again. Changes this PR introduces: - Default to ContextVarsScopeManager instead of TornadoScopeManager. Fallback on TornadoScopeManager or AsyncioScopeManager based on the Tornado and Python version. - Added tox support to enable easier testing across Python and Tornado versions. - Updated travis config to work with tox environments. Now each travis build will run tests on every supported python version in parallel. Each parallel test will run all tests for all versions of tornado serially. - The PR add some code that uses the new async/await syntax. Such code is invalid for older versions of python. To make it works for all versions, we conditionally import modules depending on the Python interpreter version. - To preserve backward compatibility and to keep using common code for all tornado versions, we've added some noop implementations that are not to be used with newer versions of tornado. - `tornado.gen.coroutine` was deprecated in favour of async/await but we still support it where we can. There is a bug in Tornado 6 that prevents us from support the deprecated feature on Python3.7 with ContextVarsScopeManager. (tornadoweb/tornado#2716) - Python3.4 also does not pass the tests for `tornado.gen.coroutine` but it is not a regression caused by this PR. Testing on master results in the same behavior. For now, I've added skip markers to these tests on Python3.4. If needed, we can look into supporting these in future in a separate PR.
This PR adds support for Tornado 6 by conditionally using different scope manager, context manager and tracing implementation depending on the version of Tornado and Python being used. It does not require existing users to change anything other than upgrade to the latest version of this package. This package used to use the TornadoScopeManager shipped by opentracing-python. The scope manager used `tornado.stack_context` which was deprecated in Tornado 5 and removed in Tornado 6. Tornado now recommends using contextvars package introduced in Python3.7. opentracing-python already provides a ContextVarsScopeManager that builds on top of the contextvars package. It also implements AsyncioScopeManager which builds on top of asyncio and falls back on thread local storage to implement context propagation. We fallback on this for Python 3.6 and older when using Tornado 6 and newer. The package also had seen some decay and some tests were not passing. This PR updates the test suite and unit tests to get them working again. Changes this PR introduces: - Default to ContextVarsScopeManager instead of TornadoScopeManager. Fallback on TornadoScopeManager or AsyncioScopeManager based on the Tornado and Python version. - Added tox support to enable easier testing across Python and Tornado versions. - Updated travis config to work with tox environments. Now each travis build will run tests on every supported python version in parallel. Each parallel test will run all tests for all versions of tornado serially. - The PR add some code that uses the new async/await syntax. Such code is invalid for older versions of python. To make it works for all versions, we conditionally import modules depending on the Python interpreter version. - To preserve backward compatibility and to keep using common code for all tornado versions, we've added some noop implementations that are not to be used with newer versions of tornado. - `tornado.gen.coroutine` was deprecated in favour of async/await but we still support it where we can. There is a bug in Tornado 6 that prevents us from support the deprecated feature on Python3.7 with ContextVarsScopeManager. (tornadoweb/tornado#2716) - Python3.4 also does not pass the tests for `tornado.gen.coroutine` but it is not a regression caused by this PR. Testing on master results in the same behavior. For now, I've added skip markers to these tests on Python3.4. If needed, we can look into supporting these in future in a separate PR.
This PR adds support for Tornado 6 by conditionally using different scope manager, context manager and tracing implementation depending on the version of Tornado and Python being used. It does not require existing users to change anything other than upgrade to the latest version of this package. This package used to use the TornadoScopeManager shipped by opentracing-python. The scope manager used `tornado.stack_context` which was deprecated in Tornado 5 and removed in Tornado 6. Tornado now recommends using contextvars package introduced in Python3.7. opentracing-python already provides a ContextVarsScopeManager that builds on top of the contextvars package. It also implements AsyncioScopeManager which builds on top of asyncio and falls back on thread local storage to implement context propagation. We fallback on this for Python 3.6 and older when using Tornado 6 and newer. The package also had seen some decay and some tests were not passing. This PR updates the test suite and unit tests to get them working again. Changes this PR introduces: - Default to ContextVarsScopeManager instead of TornadoScopeManager. Fallback on TornadoScopeManager or AsyncioScopeManager based on the Tornado and Python version. - Added tox support to enable easier testing across Python and Tornado versions. - Updated travis config to work with tox environments. Now each travis build will run tests on every supported python version in parallel. Each parallel test will run all tests for all versions of tornado serially. - The PR add some code that uses the new async/await syntax. Such code is invalid for older versions of python. To make it works for all versions, we conditionally import modules depending on the Python interpreter version. - To preserve backward compatibility and to keep using common code for all tornado versions, we've added some noop implementations that are not to be used with newer versions of tornado. - `tornado.gen.coroutine` was deprecated in favour of async/await but we still support it where we can. There is a bug in Tornado 6 that prevents us from support the deprecated feature on Python3.7 with ContextVarsScopeManager. (tornadoweb/tornado#2716) - Python3.4 also does not pass the tests for `tornado.gen.coroutine` but it is not a regression caused by this PR. Testing on master results in the same behavior. For now, I've added skip markers to these tests on Python3.4. If needed, we can look into supporting these in future in a separate PR.
This PR adds support for Tornado 6 by conditionally using different scope manager, context manager and tracing implementation depending on the version of Tornado and Python being used. It does not require existing users to change anything other than upgrade to the latest version of this package. This package used to use the TornadoScopeManager shipped by opentracing-python. The scope manager used `tornado.stack_context` which was deprecated in Tornado 5 and removed in Tornado 6. Tornado now recommends using contextvars package introduced in Python3.7. opentracing-python already provides a ContextVarsScopeManager that builds on top of the contextvars package. It also implements AsyncioScopeManager which builds on top of asyncio and falls back on thread local storage to implement context propagation. We fallback on this for Python 3.6 and older when using Tornado 6 and newer. The package also had seen some decay and some tests were not passing. This PR updates the test suite and unit tests to get them working again. Changes this PR introduces: - Default to ContextVarsScopeManager instead of TornadoScopeManager. Fallback on TornadoScopeManager or AsyncioScopeManager based on the Tornado and Python version. - Added tox support to enable easier testing across Python and Tornado versions. - Updated travis config to work with tox environments. Now each travis build will run tests on every supported python version in parallel. Each parallel test will run all tests for all versions of tornado serially. - The PR add some code that uses the new async/await syntax. Such code is invalid for older versions of python. To make it works for all versions, we conditionally import modules depending on the Python interpreter version. - To preserve backward compatibility and to keep using common code for all tornado versions, we've added some noop implementations that are not to be used with newer versions of tornado. - `tornado.gen.coroutine` was deprecated in favour of async/await but we still support it where we can. There is a bug in Tornado 6 that prevents us from support the deprecated feature on Python3.7 with ContextVarsScopeManager. (tornadoweb/tornado#2716) - Python3.4 also does not pass the tests for `tornado.gen.coroutine` but it is not a regression caused by this PR. Testing on master results in the same behavior. For now, I've added skip markers to these tests on Python3.4. If needed, we can look into supporting these in future in a separate PR.
@owais If you're still interested, an example demonstrating where But now that I'm returning to this PR, I see I may have gotten things mixed up. The original PR and commit messages talk about supporting I'm not sure that supporting |
@bdarnell The initial motivation behind this PR was to get the |
@BrandonTheBuilder OK, so the If the goal is to support
If something like that works, I think I'd support the change. Otherwise, I'm not sure it's a good idea to try and make Also, while it wouldn't support newrelic as-is, if |
This PR re-factors the gen.coroutine runner to exercise the generator in the context of a single asyncio.Task.
With this update gen.coroutines will work more like native coroutines and work with the asyncio.current_task api. One change in functionality is that execution will always be deferred to the IOLoop when previously the generator was exercised to the first yield on instantiation.