mirror of
https://github.com/Sneed-Group/Poodletooth-iLand
synced 2024-12-29 06:32:40 -06:00
251 lines
8.1 KiB
Python
251 lines
8.1 KiB
Python
|
# Copyright (c) 2009-2012 Denis Bilenko. See LICENSE for details.
|
||
|
"""Make the standard library cooperative."""
|
||
|
from __future__ import absolute_import
|
||
|
import sys
|
||
|
from sys import version_info
|
||
|
|
||
|
__all__ = ['patch_all',
|
||
|
'patch_socket',
|
||
|
'patch_ssl',
|
||
|
'patch_os',
|
||
|
'patch_time',
|
||
|
'patch_select',
|
||
|
'patch_thread',
|
||
|
'patch_subprocess',
|
||
|
'patch_sys']
|
||
|
|
||
|
|
||
|
# maps module name -> attribute name -> original item
|
||
|
# e.g. "time" -> "sleep" -> built-in function sleep
|
||
|
saved = {}
|
||
|
|
||
|
|
||
|
def _get_original(name, items):
|
||
|
d = saved.get(name, {})
|
||
|
values = []
|
||
|
module = None
|
||
|
for item in items:
|
||
|
if item in d:
|
||
|
values.append(d[item])
|
||
|
else:
|
||
|
if module is None:
|
||
|
module = __import__(name)
|
||
|
values.append(getattr(module, item))
|
||
|
return values
|
||
|
|
||
|
|
||
|
def get_original(name, item):
|
||
|
if isinstance(item, basestring):
|
||
|
return _get_original(name, [item])[0]
|
||
|
else:
|
||
|
return _get_original(name, item)
|
||
|
|
||
|
|
||
|
def patch_item(module, attr, newitem):
|
||
|
NONE = object()
|
||
|
olditem = getattr(module, attr, NONE)
|
||
|
if olditem is not NONE:
|
||
|
saved.setdefault(module.__name__, {}).setdefault(attr, olditem)
|
||
|
setattr(module, attr, newitem)
|
||
|
|
||
|
|
||
|
def remove_item(module, attr):
|
||
|
NONE = object()
|
||
|
olditem = getattr(module, attr, NONE)
|
||
|
if olditem is NONE:
|
||
|
return
|
||
|
saved.setdefault(module.__name__, {}).setdefault(attr, olditem)
|
||
|
delattr(module, attr)
|
||
|
|
||
|
|
||
|
def patch_module(name, items=None):
|
||
|
gevent_module = getattr(__import__('gevent.' + name), name)
|
||
|
module_name = getattr(gevent_module, '__target__', name)
|
||
|
module = __import__(module_name)
|
||
|
if items is None:
|
||
|
items = getattr(gevent_module, '__implements__', None)
|
||
|
if items is None:
|
||
|
raise AttributeError('%r does not have __implements__' % gevent_module)
|
||
|
for attr in items:
|
||
|
patch_item(module, attr, getattr(gevent_module, attr))
|
||
|
|
||
|
|
||
|
def _patch_sys_std(name):
|
||
|
from gevent.fileobject import FileObjectThread
|
||
|
orig = getattr(sys, name)
|
||
|
if not isinstance(orig, FileObjectThread):
|
||
|
patch_item(sys, name, FileObjectThread(orig))
|
||
|
|
||
|
|
||
|
def patch_sys(stdin=True, stdout=True, stderr=True):
|
||
|
if stdin:
|
||
|
_patch_sys_std('stdin')
|
||
|
if stdout:
|
||
|
_patch_sys_std('stdout')
|
||
|
if stderr:
|
||
|
_patch_sys_std('stderr')
|
||
|
|
||
|
|
||
|
def patch_os():
|
||
|
"""Replace :func:`os.fork` with :func:`gevent.fork`. Does nothing if fork is not available."""
|
||
|
patch_module('os')
|
||
|
|
||
|
|
||
|
def patch_time():
|
||
|
"""Replace :func:`time.sleep` with :func:`gevent.sleep`."""
|
||
|
from gevent.hub import sleep
|
||
|
import time
|
||
|
patch_item(time, 'sleep', sleep)
|
||
|
|
||
|
|
||
|
def patch_thread(threading=True, _threading_local=True, Event=False):
|
||
|
"""Replace the standard :mod:`thread` module to make it greenlet-based.
|
||
|
If *threading* is true (the default), also patch ``threading``.
|
||
|
If *_threading_local* is true (the default), also patch ``_threading_local.local``.
|
||
|
"""
|
||
|
patch_module('thread')
|
||
|
if threading:
|
||
|
patch_module('threading')
|
||
|
threading = __import__('threading')
|
||
|
if Event:
|
||
|
from gevent.event import Event
|
||
|
threading.Event = Event
|
||
|
if _threading_local:
|
||
|
_threading_local = __import__('_threading_local')
|
||
|
from gevent.local import local
|
||
|
_threading_local.local = local
|
||
|
|
||
|
|
||
|
def patch_socket(dns=True, aggressive=True):
|
||
|
"""Replace the standard socket object with gevent's cooperative sockets.
|
||
|
|
||
|
If *dns* is true, also patch dns functions in :mod:`socket`.
|
||
|
"""
|
||
|
from gevent import socket
|
||
|
# Note: although it seems like it's not strictly necessary to monkey patch 'create_connection',
|
||
|
# it's better to do it. If 'create_connection' was not monkey patched, but the rest of socket module
|
||
|
# was, create_connection would still use "green" getaddrinfo and "green" socket.
|
||
|
# However, because gevent.socket.socket.connect is a Python function, the exception raised by it causes
|
||
|
# _socket object to be referenced by the frame, thus causing the next invocation of bind(source_address) to fail.
|
||
|
if dns:
|
||
|
items = socket.__implements__
|
||
|
else:
|
||
|
items = set(socket.__implements__) - set(socket.__dns__)
|
||
|
patch_module('socket', items=items)
|
||
|
if aggressive:
|
||
|
if 'ssl' not in socket.__implements__:
|
||
|
remove_item(socket, 'ssl')
|
||
|
|
||
|
|
||
|
def patch_dns():
|
||
|
from gevent import socket
|
||
|
patch_module('socket', items=socket.__dns__)
|
||
|
|
||
|
|
||
|
def patch_ssl():
|
||
|
patch_module('ssl')
|
||
|
|
||
|
|
||
|
def patch_select(aggressive=True):
|
||
|
"""Replace :func:`select.select` with :func:`gevent.select.select`.
|
||
|
|
||
|
If aggressive is true (the default), also remove other blocking functions the :mod:`select`.
|
||
|
"""
|
||
|
patch_module('select')
|
||
|
if aggressive:
|
||
|
select = __import__('select')
|
||
|
# since these are blocking we're removing them here. This makes some other
|
||
|
# modules (e.g. asyncore) non-blocking, as they use select that we provide
|
||
|
# when none of these are available.
|
||
|
remove_item(select, 'poll')
|
||
|
remove_item(select, 'epoll')
|
||
|
remove_item(select, 'kqueue')
|
||
|
remove_item(select, 'kevent')
|
||
|
|
||
|
|
||
|
def patch_subprocess():
|
||
|
patch_module('subprocess')
|
||
|
|
||
|
|
||
|
def patch_all(socket=True, dns=True, time=True, select=True, thread=True, os=True, ssl=True, httplib=False,
|
||
|
subprocess=False, sys=False, aggressive=True, Event=False):
|
||
|
"""Do all of the default monkey patching (calls every other function in this module."""
|
||
|
# order is important
|
||
|
if os:
|
||
|
patch_os()
|
||
|
if time:
|
||
|
patch_time()
|
||
|
if thread:
|
||
|
patch_thread(Event=Event)
|
||
|
# sys must be patched after thread. in other cases threading._shutdown will be
|
||
|
# initiated to _MainThread with real thread ident
|
||
|
if sys:
|
||
|
patch_sys()
|
||
|
if socket:
|
||
|
patch_socket(dns=dns, aggressive=aggressive)
|
||
|
if select:
|
||
|
patch_select(aggressive=aggressive)
|
||
|
if ssl:
|
||
|
if version_info[:2] > (2, 5):
|
||
|
patch_ssl()
|
||
|
else:
|
||
|
try:
|
||
|
patch_ssl()
|
||
|
except ImportError:
|
||
|
pass # in Python 2.5, 'ssl' is a standalone package not included in stdlib
|
||
|
if httplib:
|
||
|
raise ValueError('gevent.httplib is no longer provided, httplib must be False')
|
||
|
if subprocess:
|
||
|
patch_subprocess()
|
||
|
|
||
|
|
||
|
if __name__ == '__main__':
|
||
|
from inspect import getargspec
|
||
|
patch_all_args = getargspec(patch_all)[0]
|
||
|
modules = [x for x in patch_all_args if 'patch_' + x in globals()]
|
||
|
script_help = """gevent.monkey - monkey patch the standard modules to use gevent.
|
||
|
|
||
|
USAGE: python -m gevent.monkey [MONKEY OPTIONS] script [SCRIPT OPTIONS]
|
||
|
|
||
|
If no OPTIONS present, monkey patches all the modules it can patch.
|
||
|
You can exclude a module with --no-module, e.g. --no-thread. You can
|
||
|
specify a module to patch with --module, e.g. --socket. In the latter
|
||
|
case only the modules specified on the command line will be patched.
|
||
|
|
||
|
MONKEY OPTIONS: --verbose %s""" % ', '.join('--[no-]%s' % m for m in modules)
|
||
|
args = {}
|
||
|
argv = sys.argv[1:]
|
||
|
verbose = False
|
||
|
while argv and argv[0].startswith('--'):
|
||
|
option = argv[0][2:]
|
||
|
if option == 'verbose':
|
||
|
verbose = True
|
||
|
elif option.startswith('no-') and option.replace('no-', '') in patch_all_args:
|
||
|
args[option[3:]] = False
|
||
|
elif option in patch_all_args:
|
||
|
args[option] = True
|
||
|
if option in modules:
|
||
|
for module in modules:
|
||
|
args.setdefault(module, False)
|
||
|
else:
|
||
|
sys.exit(script_help + '\n\n' + 'Cannot patch %r' % option)
|
||
|
del argv[0]
|
||
|
# TODO: break on --
|
||
|
if verbose:
|
||
|
import pprint
|
||
|
import os
|
||
|
print ('gevent.monkey.patch_all(%s)' % ', '.join('%s=%s' % item for item in args.items()))
|
||
|
print ('sys.version=%s' % (sys.version.strip().replace('\n', ' '), ))
|
||
|
print ('sys.path=%s' % pprint.pformat(sys.path))
|
||
|
print ('sys.modules=%s' % pprint.pformat(sorted(sys.modules.keys())))
|
||
|
print ('cwd=%s' % os.getcwd())
|
||
|
|
||
|
patch_all(**args)
|
||
|
if argv:
|
||
|
sys.argv = argv
|
||
|
__package__ = None
|
||
|
globals()['__file__'] = sys.argv[0] # issue #302
|
||
|
execfile(sys.argv[0])
|
||
|
else:
|
||
|
print (script_help)
|