Commit 011f719f authored by Denis Bilenko's avatar Denis Bilenko

monkey: remove broken get_unpatched; add get_original() with new implementation

parent 03cfd4b1
......@@ -11,6 +11,7 @@ import heapq
from time import time as _time, sleep as _sleep
from gevent import monkey
from gevent.hub import PY3
__all__ = ['Condition',
......@@ -24,7 +25,8 @@ __all__ = ['Condition',
'stack_size']
start_new_thread, Lock, get_ident, local, stack_size = monkey.get_unpatched('thread', [
thread_name = '_thread' if PY3 else 'thread'
start_new_thread, Lock, get_ident, local, stack_size = monkey.get_original(thread_name, [
'start_new_thread', 'allocate_lock', 'get_ident', '_local', 'stack_size'])
......
......@@ -67,70 +67,77 @@ __all__ = ['patch_all',
'patch_thread']
def get_unpatched(name, items):
# QQQ would prefer to avoid importing gevent.xxx module just to get __target__
# XXX does not work for 'time', 'sleep'
source = getattr(__import__('gevent.' + name), name)
target = getattr(source, '__target__', name)
dest = __import__(target)
original = getattr(dest, 'monkey_original', dest)
if isinstance(items, basestring):
return getattr(original, items)
else:
results = []
for item in items:
results.append(getattr(original, item))
return results
# 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 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)
class original(object):
pass
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):
source = getattr(__import__('gevent.' + name), name)
target = getattr(source, '__target__', name)
dest = __import__(target)
monkey_original = dest.monkey_original = original()
count = 0
gevent_module = getattr(__import__('gevent.' + name), name)
module_name = getattr(gevent_module, '__target__', name)
module = __import__(module_name)
if items is None:
items = getattr(source, '__implements__', None)
items = getattr(gevent_module, '__implements__', None)
if items is None:
raise AttributeError('%r does not have __implements__' % source)
raise AttributeError('%r does not have __implements__' % gevent_module)
for attr in items:
olditem = getattr(dest, attr, None)
newitem = getattr(source, attr)
if olditem is not newitem:
setattr(monkey_original, attr, olditem)
setattr(dest, attr, newitem)
count += 1
return count
patch_item(module, attr, getattr(gevent_module, attr))
def patch_os():
"""Replace :func:`os.fork` with :func:`gevent.fork`."""
"""Replace :func:`os.fork` with :func:`gevent.fork`. Does nothing if fork is not available."""
try:
from gevent.hub import fork
except ImportError:
return
import os
os.fork = fork
patch_item(os, 'fork', fork)
def patch_time():
"""Replace :func:`time.sleep` with :func:`gevent.sleep`."""
from gevent.hub import sleep
_time = __import__('time')
_time.sleep = sleep
import time
patch_item(time, 'sleep', sleep)
def patch_thread(threading=True, _threading_local=True):
"""Replace the standard :mod:`thread` module to make it greenlet-based.
If *threading* is true (the default), also patch ``threading.local``.
If *threading* is true (the default), also patch ``threading``.
If *_threading_local* is true (the default), also patch ``_threading_local.local``.
"""
if not patch_module('thread'):
return
patch_module('thread')
from gevent.local import local
if threading:
from gevent import thread as green_thread
......@@ -168,7 +175,7 @@ def patch_socket(dns=True, aggressive=True):
patch_module('socket', items=items)
if aggressive:
if 'ssl' not in socket.__implements__:
socket.__dict__.pop('ssl', None)
remove_item(socket, 'ssl')
def patch_dns():
......@@ -180,7 +187,7 @@ def patch_ssl():
patch_module('ssl')
def patch_select(aggressive=False):
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`.
......@@ -191,10 +198,10 @@ def patch_select(aggressive=False):
# 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.
select.__dict__.pop('poll', None)
select.__dict__.pop('epoll', None)
select.__dict__.pop('kqueue', None)
select.__dict__.pop('kevent', None)
remove_item(select, 'poll')
remove_item(select, 'epoll')
remove_item(select, 'kqueue')
remove_item(select, 'kevent')
def patch_all(socket=True, dns=True, time=True, select=True, thread=True, os=True, ssl=True, httplib=False, aggressive=True):
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment