diff --git a/eventlet/green/os.py b/eventlet/green/os.py index db5fa27..e8fe292 100644 --- a/eventlet/green/os.py +++ b/eventlet/green/os.py @@ -11,19 +11,21 @@ __patched__ = ['fdopen', 'read', 'write', 'wait', 'waitpid'] for var in dir(os_orig): exec "%s = os_orig.%s" % (var, var) +__original_fdopen__ = os_orig.fdopen def fdopen(*args, **kw): """fdopen(fd [, mode='r' [, bufsize]]) -> file_object Return an open file object connected to a file descriptor.""" - return greenio.GreenPipe(os_orig.fdopen(*args, **kw)) + return greenio.GreenPipe(__original_fdopen__(*args, **kw)) +__original_read__ = os_orig.read def read(fd, n): """read(fd, buffersize) -> string Read a file descriptor.""" while True: try: - return os_orig.read(fd, n) + return __original_read__(fd, n) except (OSError, IOError), e: if e[0] != errno.EAGAIN: raise @@ -33,6 +35,7 @@ def read(fd, n): raise hubs.trampoline(fd, read=True) +__original_write__ = os_orig.write def write(fd, st): """write(fd, string) -> byteswritten @@ -40,7 +43,7 @@ def write(fd, st): """ while True: try: - return os_orig.write(fd, st) + return __original_write__(fd, st) except (OSError, IOError), e: if e[0] != errno.EAGAIN: raise @@ -55,17 +58,18 @@ def wait(): Wait for completion of a child process.""" return waitpid(0,0) +__original_waitpid__ = os_orig.waitpid def waitpid(pid, options): """waitpid(...) waitpid(pid, options) -> (pid, status) Wait for completion of a given child process.""" if options & os.WNOHANG != 0: - return os_orig.waitpid(pid, options) + return __original_waitpid__(pid, options) else: new_options = options | os.WNOHANG while True: - rpid, status = os_orig.waitpid(pid, new_options) + rpid, status = __original_waitpid__(pid, new_options) if status >= 0: return rpid, status greenthread.sleep(0.01) diff --git a/eventlet/green/socket.py b/eventlet/green/socket.py index d5aa063..e9cde35 100644 --- a/eventlet/green/socket.py +++ b/eventlet/green/socket.py @@ -13,13 +13,16 @@ import warnings __patched__ = ['fromfd', 'socketpair', 'gethostbyname', 'create_connection', 'ssl', 'socket'] +__original_fromfd__ = __socket.fromfd def fromfd(*args): - return socket(__socket.fromfd(*args)) + return socket(__original_fromfd__(*args)) +__original_socketpair__ = __socket.socketpair def socketpair(*args): - one, two = __socket.socketpair(*args) + one, two = __original_socketpair__(*args) return socket(one), socket(two) +__original_gethostbyname__ = __socket.gethostbyname def gethostbyname(name): can_use_tpool = os.environ.get("EVENTLET_TPOOL_GETHOSTBYNAME", '').lower() == "yes" @@ -28,7 +31,7 @@ def gethostbyname(name): elif sys.platform.startswith('darwin') or not can_use_tpool: # the thread primitives on Darwin have some bugs that make # it undesirable to use tpool for hostname lookups - globals()['gethostbyname'] = __socket.gethostbyname + globals()['gethostbyname'] = __original_gethostbyname__ else: globals()['gethostbyname'] = _gethostbyname_tpool @@ -42,7 +45,7 @@ def _gethostbyname_twisted(name): def _gethostbyname_tpool(name): from eventlet import tpool return tpool.execute( - __socket.gethostbyname, name) + __original_gethostbyname__, name) # def getaddrinfo(*args, **kw): # return tpool.execute( diff --git a/eventlet/green/thread.py b/eventlet/green/thread.py index cf1cb31..7d92ec6 100644 --- a/eventlet/green/thread.py +++ b/eventlet/green/thread.py @@ -1,11 +1,11 @@ """implements standard module 'thread' with greenlets""" __thread = __import__('thread') from eventlet.support import greenlets as greenlet -from eventlet.api import spawn +from eventlet import greenthread from eventlet.semaphore import Semaphore as LockType __patched__ = ['get_ident', 'start_new_thread', 'start_new', 'allocate_lock', - 'allocate', 'exit', 'interrupt_main', 'stack_size', '_local'] + 'allocate', 'exit', 'interrupt_main', 'stack_size', '_local', 'LockType'] error = __thread.error @@ -16,7 +16,7 @@ def get_ident(gr=None): return id(gr) def start_new_thread(function, args=(), kwargs={}): - g = spawn(function, *args, **kwargs) + g = greenthread.spawn(function, *args, **kwargs) return get_ident(g) start_new = start_new_thread @@ -38,12 +38,13 @@ def interrupt_main(): else: raise KeyboardInterrupt() +__original_stack_size__ = __thread.stack_size if hasattr(__thread, 'stack_size'): def stack_size(size=None): if size is None: - return __thread.stack_size() - if size > __thread.stack_size(): - return __thread.stack_size(size) + return __original_stack_size__() + if size > __original_stack_size__(): + return __original_stack_size__(size) else: pass # not going to decrease stack_size, because otherwise other greenlets in this thread will suffer diff --git a/eventlet/green/threading.py b/eventlet/green/threading.py index 473766e..e729779 100644 --- a/eventlet/green/threading.py +++ b/eventlet/green/threading.py @@ -2,6 +2,8 @@ from eventlet import patcher from eventlet.green import thread from eventlet.green import time +__patched__ = ['_start_new_thread', '_allocate_lock', '_get_ident'] + patcher.inject('threading', globals(), ('thread', thread), diff --git a/eventlet/patcher.py b/eventlet/patcher.py index 64f9cf9..8330100 100644 --- a/eventlet/patcher.py +++ b/eventlet/patcher.py @@ -142,7 +142,8 @@ def _green_socket_modules(): def _green_thread_modules(): from eventlet.green import Queue from eventlet.green import thread - return [('Queue', Queue), ('thread', thread)] + from eventlet.green import threading + return [('Queue', Queue), ('thread', thread), ('threading', threading)] def _green_time_modules(): from eventlet.green import time diff --git a/eventlet/queue.py b/eventlet/queue.py index cb655ec..e63a6ac 100644 --- a/eventlet/queue.py +++ b/eventlet/queue.py @@ -22,6 +22,7 @@ in :meth:`put ` or :meth:`get ` respectively. import sys import heapq import collections +import traceback from Queue import Full, Empty diff --git a/tests/stdlib/all.py b/tests/stdlib/all.py index 33b7d8f..5236e7c 100644 --- a/tests/stdlib/all.py +++ b/tests/stdlib/all.py @@ -4,7 +4,7 @@ Many of these tests make connections to external servers, and all.py tries to sk """ -def import_main(name): +def assimilate_patched(name): try: modobj = __import__(name, globals(), locals(), ['test_main']) except ImportError: @@ -18,44 +18,7 @@ def import_main(name): except AttributeError: print "No test_main for %s, assuming it tests on import" % name - -# quick and dirty way of testing whether we can access -# remote hosts; any tests that try internet connections -# will fail if we cannot -import socket -s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) -try: - s.settimeout(0.5) - s.connect(('eventlet.net', 80)) - s.close() - have_network_access = True -except socket.error, e: - print "Skipping network tests" - have_network_access = False - -import_main('test_select') -import_main('test_SimpleHTTPServer') -import_main('test_asynchat') -import_main('test_asyncore') -import_main('test_ftplib') -import_main('test_httplib') -if have_network_access: - import_main('test_httpservers') -import_main('test_os') -import_main('test_queue') -if have_network_access: - import_main('test_socket') -import_main('test_socket_ssl') -#import_main('test_socketserver') -#import_main('test_subprocess') -if have_network_access: - import_main('test_ssl') -import_main('test_thread') -#import_main('test_threading') -import_main('test_threading_local') -if have_network_access: - import_main('test_timeout') -import_main('test_urllib') -if have_network_access: - import_main('test_urllib2') -import_main('test_urllib2_localnet') +import all_modules + +for m in all_modules.get_modules(): + assimilate_patched(m) diff --git a/tests/stdlib/all_modules.py b/tests/stdlib/all_modules.py new file mode 100644 index 0000000..1a13c3c --- /dev/null +++ b/tests/stdlib/all_modules.py @@ -0,0 +1,41 @@ +def get_modules(): + test_modules = [ + 'test_select', + 'test_SimpleHTTPServer', + 'test_asynchat', + 'test_asyncore', + 'test_ftplib', + 'test_httplib', + 'test_os', + 'test_queue', + 'test_socket_ssl', +# 'test_socketserver', +# 'test_subprocess', + 'test_thread', +# 'test_threading', + 'test_threading_local', + 'test_urllib', + 'test_urllib2_localnet'] + + network_modules = [ + 'test_httpservers', + 'test_socket', + 'test_ssl', + 'test_timeout', + 'test_urllib2'] + + # quick and dirty way of testing whether we can access + # remote hosts; any tests that try internet connections + # will fail if we cannot + import socket + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + try: + s.settimeout(0.5) + s.connect(('eventlet.net', 80)) + s.close() + test_modules = test_modules + network_modules + except socket.error, e: + print "Skipping network tests" + + return test_modules + diff --git a/tests/stdlib/all_monkey.py b/tests/stdlib/all_monkey.py new file mode 100644 index 0000000..e29b09c --- /dev/null +++ b/tests/stdlib/all_monkey.py @@ -0,0 +1,24 @@ +import eventlet +eventlet.sleep(0) +from eventlet import patcher +patcher.monkey_patch() + +def assimilate_real(name): + print "Assimilating", name + try: + modobj = __import__('test.' + name, globals(), locals(), ['test_main']) + except ImportError: + print "Not importing %s, it doesn't exist in this installation/version of Python" % name + return + else: + method_name = name + "_test_main" + try: + globals()[method_name] = modobj.test_main + modobj.test_main.__name__ = name + '.test_main' + except AttributeError: + print "No test_main for %s, assuming it tests on import" % name + +import all_modules + +for m in all_modules.get_modules(): + assimilate_real(m)