Added Daniele Varrazzo's green-psycopg2 patch. Untested in the case where the module is actually present, but verified that it's a no-op if not installed.

This commit is contained in:
Ryan Williams
2010-04-08 19:39:20 -07:00
parent 1737479626
commit b76a8c76c0
3 changed files with 67 additions and 6 deletions

View File

@@ -136,7 +136,7 @@ def monkey_patch(**on):
It's safe to call monkey_patch multiple times.
"""
accepted_args = set(('os', 'select', 'socket', 'thread', 'time'))
accepted_args = set(('os', 'select', 'socket', 'thread', 'time', 'psycopg'))
default_on = on.pop("all",None)
for k in on.iterkeys():
if k not in accepted_args:
@@ -167,6 +167,13 @@ def monkey_patch(**on):
if on['time'] and not already_patched.get('time'):
modules_to_patch += _green_time_modules()
already_patched['time'] = True
if on['psycopg'] and not already_patched.get('psycopg'):
try:
from eventlet.support import psycopg2_patcher
psycopg2_patcher.make_psycopg_green()
except ImportError:
pass
already_patched['psycopg'] = True
for name, mod in modules_to_patch:
orig_mod = sys.modules.get(name)
@@ -201,6 +208,7 @@ def _green_time_modules():
from eventlet.green import time
return [('time', time)]
if __name__ == "__main__":
import sys
sys.argv.pop(0)

View File

@@ -0,0 +1,53 @@
"""A wait callback to allow psycopg2 cooperation with eventlet.
Use `make_psycopg_green()` to enable eventlet support in Psycopg.
"""
# Copyright (C) 2010 Daniele Varrazzo <daniele.varrazzo@gmail.com>
# and licensed under the MIT license:
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
import psycopg2
from psycopg2 import extensions
from eventlet.hubs import trampoline
def make_psycopg_green():
"""Configure Psycopg to be used with eventlet in non-blocking way."""
if not hasattr(extensions, 'set_wait_callback'):
raise ImportError(
"support for coroutines not available in this Psycopg version (%s)"
% psycopg2.__version__)
extensions.set_wait_callback(eventlet_wait_callback)
def eventlet_wait_callback(conn, timeout=-1):
"""A wait callback useful to allow eventlet to work with Psycopg."""
while 1:
state = conn.poll()
if state == extensions.POLL_OK:
break
elif state == extensions.POLL_READ:
trampoline(conn.fileno(), read=True)
elif state == extensions.POLL_WRITE:
trampoline(conn.fileno(), write=True)
else:
raise psycopg2.OperationalError(
"Bad result from poll: %r" % state)

View File

@@ -171,15 +171,15 @@ print "already_patched", ",".join(sorted(patcher.already_patched.keys()))
def test_boolean(self):
self.assert_boolean_logic("patcher.monkey_patch()",
'os,select,socket,thread,time')
'os,psycopg,select,socket,thread,time')
def test_boolean_all(self):
self.assert_boolean_logic("patcher.monkey_patch(all=True)",
'os,select,socket,thread,time')
'os,psycopg,select,socket,thread,time')
def test_boolean_all_single(self):
self.assert_boolean_logic("patcher.monkey_patch(all=True, socket=True)",
'os,select,socket,thread,time')
'os,psycopg,select,socket,thread,time')
def test_boolean_all_negative(self):
self.assert_boolean_logic("patcher.monkey_patch(all=False, "\
@@ -197,12 +197,12 @@ print "already_patched", ",".join(sorted(patcher.already_patched.keys()))
def test_boolean_negative(self):
self.assert_boolean_logic("patcher.monkey_patch(socket=False)",
'os,select,thread,time')
'os,psycopg,select,thread,time')
def test_boolean_negative2(self):
self.assert_boolean_logic("patcher.monkey_patch(socket=False,"\
"time=False)",
'os,select,thread')
'os,psycopg,select,thread')
def test_conflicting_specifications(self):
self.assert_boolean_logic("patcher.monkey_patch(socket=False, "\