def __exit__(self, *args): self.close() _open_environment = dict(globals()) _open_environment.update(dict( BufferedRandom=_OriginalBufferedRandom, BufferedWriter=_OriginalBufferedWriter, BufferedReader=_OriginalBufferedReader, TextIOWrapper=_OriginalTextIOWrapper, FileIO=GreenFileIO, os=_original_os, )) _open = FunctionType( six.get_function_code(_original_pyio.open), _open_environment, ) def GreenPipe(name, mode="r", buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None): try: fileno = name.fileno() except AttributeError: pass else: fileno = _original_os.dup(fileno) name.close() name = fileno
class Popen(subprocess_orig.Popen): """eventlet-friendly version of subprocess.Popen""" # We do not believe that Windows pipes support non-blocking I/O. At least, # the Python file objects stored on our base-class object have no # setblocking() method, and the Python fcntl module doesn't exist on # Windows. (see eventlet.greenio.set_nonblocking()) As the sole purpose of # this __init__() override is to wrap the pipes for eventlet-friendly # non-blocking I/O, don't even bother overriding it on Windows. if not mswindows: def __init__(self, args, bufsize=0, *argss, **kwds): self.args = args # Forward the call to base-class constructor subprocess_orig.Popen.__init__(self, args, 0, *argss, **kwds) # Now wrap the pipes, if any. This logic is loosely borrowed from # eventlet.processes.Process.run() method. for attr in "stdin", "stdout", "stderr": pipe = getattr(self, attr) if pipe is not None and type(pipe) != greenio.GreenPipe: # https://github.com/eventlet/eventlet/issues/243 # AttributeError: '_io.TextIOWrapper' object has no attribute 'mode' mode = getattr(pipe, 'mode', '') if not mode: if pipe.readable(): mode += 'r' if pipe.writable(): mode += 'w' # ValueError: can't have unbuffered text I/O if bufsize == 0: bufsize = -1 wrapped_pipe = greenio.GreenPipe(pipe, mode, bufsize) setattr(self, attr, wrapped_pipe) __init__.__doc__ = subprocess_orig.Popen.__init__.__doc__ def wait(self, timeout=None, check_interval=0.01): # Instead of a blocking OS call, this version of wait() uses logic # borrowed from the eventlet 0.2 processes.Process.wait() method. if timeout is not None: endtime = time.time() + timeout try: while True: status = self.poll() if status is not None: return status if timeout is not None and time.time() > endtime: raise TimeoutExpired(self.args, timeout) eventlet.sleep(check_interval) except OSError as e: if e.errno == errno.ECHILD: # no child process, this happens if the child process # already died and has been cleaned up return -1 else: raise wait.__doc__ = subprocess_orig.Popen.wait.__doc__ if not mswindows: # don't want to rewrite the original _communicate() method, we # just want a version that uses eventlet.green.select.select() # instead of select.select(). _communicate = FunctionType( six.get_function_code( six.get_unbound_function(subprocess_orig.Popen._communicate)), globals()) try: _communicate_with_select = FunctionType( six.get_function_code( six.get_unbound_function( subprocess_orig.Popen._communicate_with_select)), globals()) _communicate_with_poll = FunctionType( six.get_function_code( six.get_unbound_function( subprocess_orig.Popen._communicate_with_poll)), globals()) except AttributeError: pass
self.close() _open_environment = dict(globals()) _open_environment.update( dict( BufferedRandom=_OriginalBufferedRandom, BufferedWriter=_OriginalBufferedWriter, BufferedReader=_OriginalBufferedReader, TextIOWrapper=_OriginalTextIOWrapper, FileIO=GreenFileIO, os=_original_os, ) ) _open = FunctionType(six.get_function_code(_original_pyio.open), _open_environment) def GreenPipe(name, mode="r", buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None): try: fileno = name.fileno() except AttributeError: pass else: fileno = _original_os.dup(fileno) name.close() name = fileno return _open(name, mode, buffering, encoding, errors, newline, closefd, opener)
# already died and has been cleaned up return -1 else: raise wait.__doc__ = subprocess_orig.Popen.wait.__doc__ if not mswindows: # don't want to rewrite the original _communicate() method, we # just want a version that uses eventlet.green.select.select() # instead of select.select(). _communicate = FunctionType( six.get_function_code(six.get_unbound_function( subprocess_orig.Popen._communicate)), globals()) try: _communicate_with_select = FunctionType( six.get_function_code(six.get_unbound_function( subprocess_orig.Popen._communicate_with_select)), globals()) _communicate_with_poll = FunctionType( six.get_function_code(six.get_unbound_function( subprocess_orig.Popen._communicate_with_poll)), globals()) except AttributeError: pass # Borrow subprocess.call() and check_call(), but patch them so they reference # OUR Popen class rather than subprocess.Popen. call = FunctionType(six.get_function_code(subprocess_orig.call), globals()) check_call = FunctionType(six.get_function_code(subprocess_orig.check_call), globals())
def patched_function(function): return FunctionType(six.get_function_code(function), globals())
def patched_function(function): new_function = FunctionType(six.get_function_code(function), globals()) if six.PY3: new_function.__kwdefaults__ = function.__kwdefaults__ new_function.__defaults__ = function.__defaults__ return new_function
wait.__doc__ = subprocess_orig.Popen.wait.__doc__ if not subprocess_orig.mswindows: # don't want to rewrite the original _communicate() method, we # just want a version that uses eventlet.green.select.select() # instead of select.select(). _communicate = FunctionType( six.get_function_code( six.get_unbound_function(subprocess_orig.Popen._communicate)), globals()) try: _communicate_with_select = FunctionType( six.get_function_code( six.get_unbound_function( subprocess_orig.Popen._communicate_with_select)), globals()) _communicate_with_poll = FunctionType( six.get_function_code( six.get_unbound_function( subprocess_orig.Popen._communicate_with_poll)), globals()) except AttributeError: pass # Borrow subprocess.call() and check_call(), but patch them so they reference # OUR Popen class rather than subprocess.Popen. call = FunctionType(six.get_function_code(subprocess_orig.call), globals()) check_call = FunctionType(six.get_function_code(subprocess_orig.check_call), globals())