Python version: Please be as specific as possible: "cPython 3.6.9 from ubuntu 18.04 archives
Operating System: Ubuntu 18.04 amd64
Description:
The new gevent.contextvars supports patching stdlib contextvars module, but explicitly only in py3.7+. The logic is in gevent/contextvars.py:48.
__implements__ = __all__ if PY37 else None
However, the decision in gevent.monkey.patch_contextvars about whether or not to patch is based on whether contextvars can be imported.
In the case of running python <=3.6 and using the backported contextvars package from PyPI, this results in patch_contexvars attempting to patch contextvars, as it can be imported, and raising an exception, because gevent.contextvars.__implements__ is None.
File "/home/travis/build/canonical-ols/talisker/.tox/py36/lib/python3.6/site-packages/gunicorn/arbiter.py", line 583, in spawn_worker
worker.init_process()
File "/home/travis/build/canonical-ols/talisker/.tox/py36/lib/python3.6/site-packages/gunicorn/workers/ggevent.py", line 160, in init_process
self.patch()
File "/home/travis/build/canonical-ols/talisker/.tox/py36/lib/python3.6/site-packages/gunicorn/workers/ggevent.py", line 53, in patch
monkey.patch_all()
File "/home/travis/build/canonical-ols/talisker/.tox/py36/lib/python3.6/site-packages/gevent/monkey.py", line 1152, in patch_all
patch_contextvars()
File "/home/travis/build/canonical-ols/talisker/.tox/py36/lib/python3.6/site-packages/gevent/monkey.py", line 183, in ignores
return func(*args, **kwargs)
File "/home/travis/build/canonical-ols/talisker/.tox/py36/lib/python3.6/site-packages/gevent/monkey.py", line 546, in patch_contextvars
_patch_module('contextvars')
File "/home/travis/build/canonical-ols/talisker/.tox/py36/lib/python3.6/site-packages/gevent/monkey.py", line 408, in _patch_module
_call_hooks=_call_hooks)
File "/home/travis/build/canonical-ols/talisker/.tox/py36/lib/python3.6/site-packages/gevent/monkey.py", line 354, in patch_module
raise AttributeError('%r does not have __implements__' % source_module)
AttributeError: <module 'gevent.contextvars' from '/home/travis/build/canonical-ols/talisker/.tox/py36/lib/python3.6/site-packages/gevent/contextvars.py'> does not have __implements__
Note: the error message is slightly confusing here, as it does have __implements__, it's just explicitly set to None.
If worked around this in my code by setting gevent.contextvars.__implements__ = gevent.contextvars.__all__ manually iff contextvars backport is installed, and this seems to work, though it's not made it into production yet.
From my POV, patching the backport makes sense, but there may be other considerations, of course. Given that patching is protected via an import check, might it possible to just set __implements__ = __all__? i.e. drop the py37 check?
My particular situation it that my library has a hard dependency on contextvars for <=3.6, and optionally supports gevent.
I'd be happy to work on a PR for this, if can provide some guidance as to what direction you'd like the solution to go in.
Thanks
[Edit: formatting]
The text was updated successfully, but these errors were encountered:
Thanks for the report! There are tests that prevent us from setting __implements__ to __all__ without doing something more complicated, but its still easy enough to fix.
Description:
The new gevent.contextvars supports patching stdlib contextvars module, but explicitly only in py3.7+. The logic is in gevent/contextvars.py:48.
However, the decision in gevent.monkey.patch_contextvars about whether or not to patch is based on whether contextvars can be imported.
In the case of running python <=3.6 and using the backported contextvars package from PyPI, this results in patch_contexvars attempting to patch contextvars, as it can be imported, and raising an exception, because
gevent.contextvars.__implements__
is None.Note: the error message is slightly confusing here, as it does have
__implements__
, it's just explicitly set to None.If worked around this in my code by setting
gevent.contextvars.__implements__ = gevent.contextvars.__all__
manually iff contextvars backport is installed, and this seems to work, though it's not made it into production yet.From my POV, patching the backport makes sense, but there may be other considerations, of course. Given that patching is protected via an import check, might it possible to just set
__implements__ = __all__
? i.e. drop the py37 check?My particular situation it that my library has a hard dependency on contextvars for <=3.6, and optionally supports gevent.
I'd be happy to work on a PR for this, if can provide some guidance as to what direction you'd like the solution to go in.
Thanks
[Edit: formatting]
The text was updated successfully, but these errors were encountered: