def _is_contextvars_broken(): # type: () -> bool """ Returns whether gevent/eventlet have patched the stdlib in a way where thread locals are now more "correct" than contextvars. """ try: from gevent.monkey import is_object_patched # type: ignore 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"): return False return True except ImportError: pass try: from eventlet.patcher import is_monkey_patched # type: ignore if is_monkey_patched("thread"): return True except ImportError: pass return False
def test_saved(self): self.assertTrue(monkey.saved) for modname in monkey.saved: self.assertTrue(monkey.is_module_patched(modname)) for objname in monkey.saved[modname]: self.assertTrue(monkey.is_object_patched(modname, objname))
def _create_accept(self): # TODO: raise appropriate errors # Handle case where we are being used inside gevent sock = None try: from gevent import monkey if monkey.is_object_patched('socket', 'socket'): sock = monkey.get_original('socket', 'socket')() except: pass # connect to sam sock = pysocket.create_connection(self._samAddr) # say hello repl = _sam_cmd(sock, _greeting()) if repl.opts["RESULT"] != "OK": raise pysocket.error(errno.ENOTCONN, "failed to accept: %s" % repl.opts['RESULT']) # send command cmd = 'STREAM ACCEPT ID={} SILENT=false'.format(self.socketname) repl = _sam_cmd(sock, cmd) if repl.opts['RESULT'] != 'OK': raise pysocket.error(errno.ENOTCONN, "failed to accept: %s" % repl.opts['RESULT']) sock.setblocking(self._blocking_flag) return (sock, '')
def test_saved(self): self.assertTrue(monkey.saved) for modname in monkey.saved: self.assertTrue(monkey.is_module_patched(modname)) for objname in monkey.saved[modname]: self.assertTrue(monkey.is_object_patched(modname, objname))
def test_saved(self): self.assertTrue(monkey.saved) for modname, objects in monkey.saved.items(): self.assertTrue(monkey.is_module_patched(modname)) for objname in objects: self.assertTrue(monkey.is_object_patched(modname, objname))
def test_thread(self): try: import thread except ImportError: import _thread as thread import threading from gevent import thread as gthread self.assertIs(thread.start_new_thread, gthread.start_new_thread) self.assertIs(threading._start_new_thread, gthread.start_new_thread) if sys.version_info[0] == 2: from gevent import threading as gthreading self.assertIs(threading._sleep, gthreading._sleep) self.assertFalse(monkey.is_object_patched('threading', 'Event')) monkey.patch_thread(Event=True) self.assertTrue(monkey.is_object_patched('threading', 'Event'))
def test_thread(self): try: import thread except ImportError: import _thread as thread import threading from gevent import thread as gthread self.assertIs(thread.start_new_thread, gthread.start_new_thread) self.assertIs(threading._start_new_thread, gthread.start_new_thread) # Event patched by default self.assertTrue(monkey.is_object_patched('threading', 'Event')) if sys.version_info[0] == 2: from gevent import threading as gthreading from gevent.event import Event as GEvent self.assertIs(threading._sleep, gthreading._sleep) self.assertTrue(monkey.is_object_patched('threading', '_Event')) self.assertIs(threading._Event, GEvent)
def test_thread(self): try: import thread except ImportError: import _thread as thread import threading from gevent import thread as gthread self.assertIs(thread.start_new_thread, gthread.start_new_thread) self.assertIs(threading._start_new_thread, gthread.start_new_thread) # Event patched by default self.assertTrue(monkey.is_object_patched('threading', 'Event')) if sys.version_info[0] == 2: from gevent import threading as gthreading from gevent.event import Event as GEvent self.assertIs(threading._sleep, gthreading._sleep) self.assertTrue(monkey.is_object_patched('threading', '_Event')) self.assertIs(threading._Event, GEvent)
def _is_contextvars_broken(): # type: () -> bool """ 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 re.split(r"a|b|rc|\.", gevent.__version__)[:2] ]) if is_object_patched("threading", "local"): # 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 except ImportError: pass try: from eventlet.patcher import is_monkey_patched # type: ignore if is_monkey_patched("thread"): return True except ImportError: pass return False
def _is_contextvars_broken(): # type: () -> bool try: from gevent.monkey import is_object_patched # type: ignore if is_object_patched("threading", "local"): if is_object_patched("contextvars", "ContextVar"): return False return True except ImportError: pass try: from eventlet.patcher import is_monkey_patched # type: ignore if is_monkey_patched("thread"): return True except ImportError: pass return False
def _is_threading_local_monkey_patched(): # type: () -> bool try: from gevent.monkey import is_object_patched # type: ignore if is_object_patched("threading", "local"): return True except ImportError: pass try: from eventlet.patcher import is_monkey_patched # type: ignore if is_monkey_patched("thread"): return True except ImportError: pass return False
def threading_local_monkey_patched(): # Returns True if thread locals have been patched by either gevent of # eventlet try: from gevent.monkey import is_object_patched except ImportError: pass else: if is_object_patched("_threading", "local"): return True try: from eventlet.patcher import is_monkey_patched except ImportError: pass else: if is_monkey_patched("thread"): return True return False
def get_system_poll(): """Returns the original select.poll() object. If select.poll is monkey patched by eventlet or gevent library, it gets the original select.poll and returns an object of it using the eventlet.patcher.original/gevent.monkey.get_original functions. As a last resort, if there is any exception it returns the SelectPoll() object. """ try: if _using_eventlet_green_select(): _system_poll = eventlet_patcher.original("select").poll elif gevent_monkey and gevent_monkey.is_object_patched( 'select', 'poll'): _system_poll = gevent_monkey.get_original('select', 'poll') else: _system_poll = select.poll except: _system_poll = SelectPoll return _system_poll()
def get_system_poll(): """Returns the original select.poll() object. If select.poll is monkey patched by eventlet or gevent library, it gets the original select.poll and returns an object of it using the eventlet.patcher.original/gevent.monkey.get_original functions. As a last resort, if there is any exception it returns the SelectPoll() object. """ try: if _using_eventlet_green_select(): _system_poll = eventlet_patcher.original("select").poll elif gevent_monkey and gevent_monkey.is_object_patched( 'select', 'poll'): _system_poll = gevent_monkey.get_original('select', 'poll') else: _system_poll = select.poll except: _system_poll = SelectPoll return _system_poll()
def _create_accept(self): # TODO: raise appropriate errors # Handle case where we are being used inside gevent sock = None try: from gevent import monkey if monkey.is_object_patched('socket', 'socket'): sock = monkey.get_original('socket', 'socket')() except: pass # connect to sam sock = pysocket.create_connection(self._samAddr) # say hello repl = _sam_cmd(sock, _greeting()) if repl.opts["RESULT"] != "OK": raise pysocket.error(errno.ENOTCONN, "failed to accept: %s" % repl.opts['RESULT']) # send command cmd = 'STREAM ACCEPT ID={} SILENT=false'.format(self.socketname) repl = _sam_cmd(sock, cmd) if repl.opts['RESULT'] != 'OK': raise pysocket.error(errno.ENOTCONN, "failed to accept: %s" % repl.opts['RESULT']) sock.setblocking(self._blocking_flag) return (sock, '')
import socket from gevent import socket as gevent_socket assert socket.create_connection is gevent_socket.create_connection import os import types for name in ('fork', 'forkpty'): if hasattr(os, name): attr = getattr(os, name) assert 'built-in' not in repr(attr), repr(attr) assert not isinstance(attr, types.BuiltinFunctionType), repr(attr) assert isinstance(attr, types.FunctionType), repr(attr) assert monkey.saved assert not monkey.is_object_patched('threading', 'Event') monkey.patch_thread(Event=True) assert monkey.is_object_patched('threading', 'Event') for modname in monkey.saved: assert monkey.is_module_patched(modname) for objname in monkey.saved[modname]: assert monkey.is_object_patched(modname, objname) orig_saved = {} for k, v in monkey.saved.items(): orig_saved[k] = v.copy() import warnings with warnings.catch_warnings(record=True) as issued_warnings:
import thread except ImportError: import _thread as thread import threading assert 'built-in' not in repr(thread.start_new_thread), repr( thread.start_new_thread) assert 'built-in' not in repr(threading._start_new_thread), repr( threading._start_new_thread) if sys.version_info[0] == 2: assert 'built-in' not in repr(threading._sleep), repr(threading._sleep) import socket from gevent import socket as gevent_socket assert socket.create_connection is gevent_socket.create_connection import os if hasattr(os, 'fork'): assert 'built-in' not in repr(os.fork), repr(os.fork) assert monkey.saved assert not monkey.is_object_patched('threading', 'Event') monkey.patch_thread(Event=True) assert monkey.is_object_patched('threading', 'Event') for modname in monkey.saved: assert monkey.is_module_patched(modname) for objname in monkey.saved[modname]: assert monkey.is_object_patched(modname, objname)
# ContextVars, Greenlet <0.4.17 does not. import greenlet greenlet_patched = getattr(greenlet, "GREENLET_USE_CONTEXT_VARS", False) if not greenlet_patched: # If Gevent is used, check it has patched ContextVars, # <20.5 does not. try: from gevent.monkey import is_object_patched except ImportError: # Gevent isn't used, but Greenlet is and hasn't patched raise _CannotUseContextVar() else: if is_object_patched("threading", "local") and not is_object_patched( "contextvars", "ContextVar"): raise _CannotUseContextVar() except (ImportError, _CannotUseContextVar): class ContextVar: # type: ignore """A fake ContextVar based on the previous greenlet/threading ident function. Used on Python 3.6, eventlet, and old versions of gevent. """ def __init__(self, _name: str) -> None: self.storage: t.Dict[int, t.Dict[str, t.Any]] = {} def get(self, default: t.Dict[str, t.Any]) -> t.Dict[str, t.Any]: return self.storage.get(_get_ident(), default)