From e8d45870b7354859760e498ef15928e74018e505 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Tue, 27 Jul 2021 11:25:09 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20Fix=20detection=20of=20contextva?= =?UTF-8?q?rs=20compatibility=20with=20Gevent=2020.9.0+=20(#1157)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 🐛 Fix detection of contextvars compatibility with Gevent 20.9.0+ * 🐛 Improve implementation of version detection and account for Python versions * 🔥 Remove duplicated sys import * 🚨 Fix linter warnings --- sentry_sdk/utils.py | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/sentry_sdk/utils.py b/sentry_sdk/utils.py index 323e4ceffa..43b63b41ac 100644 --- a/sentry_sdk/utils.py +++ b/sentry_sdk/utils.py @@ -785,12 +785,24 @@ def _is_contextvars_broken(): Returns whether gevent/eventlet have patched the stdlib in a way where thread locals are now more "correct" than contextvars. """ try: + import gevent # type: ignore from gevent.monkey import is_object_patched # type: ignore + # Get the MAJOR and MINOR version numbers of Gevent + version_tuple = tuple([int(part) for part in gevent.__version__.split(".")[:2]]) if is_object_patched("threading", "local"): - # Gevent 20.5 is able to patch both thread locals and contextvars, - # in that case all is good. - if is_object_patched("contextvars", "ContextVar"): + # Gevent 20.9.0 depends on Greenlet 0.4.17 which natively handles switching + # context vars when greenlets are switched, so, Gevent 20.9.0+ is all fine. + # Ref: https://github.com/gevent/gevent/blob/83c9e2ae5b0834b8f84233760aabe82c3ba065b4/src/gevent/monkey.py#L604-L609 + # Gevent 20.5, that doesn't depend on Greenlet 0.4.17 with native support + # for contextvars, is able to patch both thread locals and contextvars, in + # that case, check if contextvars are effectively patched. + if ( + # Gevent 20.9.0+ + (sys.version_info >= (3, 7) and version_tuple >= (20, 9)) + # Gevent 20.5.0+ or Python < 3.7 + or (is_object_patched("contextvars", "ContextVar")) + ): return False return True