fix the skip print notices in mysql_requirement so they are actually visible on stderr when run from nose (plus some stuff pyflakes recommended and a few cosmetic ws and line-len changes)
This commit is contained in:
@@ -1,11 +1,13 @@
|
|||||||
"Test cases for db_pool"
|
"Test cases for db_pool"
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
from unittest import TestCase, main
|
||||||
|
|
||||||
from tests import skipped, skip_unless, skip_with_pyevent
|
from tests import skipped, skip_unless, skip_with_pyevent
|
||||||
from unittest import TestCase, main
|
|
||||||
from eventlet import event
|
from eventlet import event
|
||||||
from eventlet import db_pool
|
from eventlet import db_pool
|
||||||
import eventlet
|
import eventlet
|
||||||
import os
|
|
||||||
|
|
||||||
class DBTester(object):
|
class DBTester(object):
|
||||||
__test__ = False # so that nose doesn't try to execute this directly
|
__test__ = False # so that nose doesn't try to execute this directly
|
||||||
@@ -14,19 +16,19 @@ class DBTester(object):
|
|||||||
self.connection = None
|
self.connection = None
|
||||||
connection = self._dbmodule.connect(**self._auth)
|
connection = self._dbmodule.connect(**self._auth)
|
||||||
cursor = connection.cursor()
|
cursor = connection.cursor()
|
||||||
cursor.execute("""CREATE TABLE gargleblatz
|
cursor.execute("""CREATE TABLE gargleblatz
|
||||||
(
|
(
|
||||||
a INTEGER
|
a INTEGER
|
||||||
);""")
|
);""")
|
||||||
connection.commit()
|
connection.commit()
|
||||||
cursor.close()
|
cursor.close()
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
if self.connection:
|
if self.connection:
|
||||||
self.connection.close()
|
self.connection.close()
|
||||||
self.drop_db()
|
self.drop_db()
|
||||||
|
|
||||||
def set_up_dummy_table(self, connection = None):
|
def set_up_dummy_table(self, connection=None):
|
||||||
close_connection = False
|
close_connection = False
|
||||||
if connection is None:
|
if connection is None:
|
||||||
close_connection = True
|
close_connection = True
|
||||||
@@ -53,7 +55,7 @@ class DBConnectionPool(DBTester):
|
|||||||
super(DBConnectionPool, self).setUp()
|
super(DBConnectionPool, self).setUp()
|
||||||
self.pool = self.create_pool()
|
self.pool = self.create_pool()
|
||||||
self.connection = self.pool.get()
|
self.connection = self.pool.get()
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
if self.connection:
|
if self.connection:
|
||||||
self.pool.put(self.connection)
|
self.pool.put(self.connection)
|
||||||
@@ -84,7 +86,7 @@ class DBConnectionPool(DBTester):
|
|||||||
self.assert_(False)
|
self.assert_(False)
|
||||||
except AssertionError:
|
except AssertionError:
|
||||||
raise
|
raise
|
||||||
except Exception, e:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
cursor.close()
|
cursor.close()
|
||||||
|
|
||||||
@@ -107,7 +109,7 @@ class DBConnectionPool(DBTester):
|
|||||||
|
|
||||||
@skipped
|
@skipped
|
||||||
def test_deletion_does_a_put(self):
|
def test_deletion_does_a_put(self):
|
||||||
# doing a put on del causes some issues if __del__ is called in the
|
# doing a put on del causes some issues if __del__ is called in the
|
||||||
# main coroutine, so, not doing that for now
|
# main coroutine, so, not doing that for now
|
||||||
self.assert_(self.pool.free() == 0)
|
self.assert_(self.pool.free() == 0)
|
||||||
self.connection = None
|
self.connection = None
|
||||||
@@ -144,7 +146,6 @@ class DBConnectionPool(DBTester):
|
|||||||
curs.execute(SHORT_QUERY)
|
curs.execute(SHORT_QUERY)
|
||||||
results.append(2)
|
results.append(2)
|
||||||
evt.send()
|
evt.send()
|
||||||
evt2 = event.Event()
|
|
||||||
eventlet.spawn(a_query)
|
eventlet.spawn(a_query)
|
||||||
results.append(1)
|
results.append(1)
|
||||||
self.assertEqual([1], results)
|
self.assertEqual([1], results)
|
||||||
@@ -201,10 +202,10 @@ class DBConnectionPool(DBTester):
|
|||||||
curs.execute("delete from gargleblatz where a=314159")
|
curs.execute("delete from gargleblatz where a=314159")
|
||||||
conn.commit()
|
conn.commit()
|
||||||
self.pool.put(conn)
|
self.pool.put(conn)
|
||||||
|
|
||||||
@skipped
|
@skipped
|
||||||
def test_two_simultaneous_connections(self):
|
def test_two_simultaneous_connections(self):
|
||||||
# timing-sensitive test, disabled until we come up with a better
|
# timing-sensitive test, disabled until we come up with a better
|
||||||
# way to do this
|
# way to do this
|
||||||
self.pool = self.create_pool(2)
|
self.pool = self.create_pool(2)
|
||||||
conn = self.pool.get()
|
conn = self.pool.get()
|
||||||
@@ -238,36 +239,36 @@ class DBConnectionPool(DBTester):
|
|||||||
evt2.wait()
|
evt2.wait()
|
||||||
results.sort()
|
results.sort()
|
||||||
self.assertEqual([1, 2], results)
|
self.assertEqual([1, 2], results)
|
||||||
|
|
||||||
def test_clear(self):
|
def test_clear(self):
|
||||||
self.pool = self.create_pool()
|
self.pool = self.create_pool()
|
||||||
self.pool.put(self.connection)
|
self.pool.put(self.connection)
|
||||||
self.pool.clear()
|
self.pool.clear()
|
||||||
self.assertEqual(len(self.pool.free_items), 0)
|
self.assertEqual(len(self.pool.free_items), 0)
|
||||||
|
|
||||||
def test_unwrap_connection(self):
|
def test_unwrap_connection(self):
|
||||||
self.assert_(isinstance(self.connection,
|
self.assert_(isinstance(self.connection,
|
||||||
db_pool.GenericConnectionWrapper))
|
db_pool.GenericConnectionWrapper))
|
||||||
conn = self.pool._unwrap_connection(self.connection)
|
conn = self.pool._unwrap_connection(self.connection)
|
||||||
self.assert_(not isinstance(conn, db_pool.GenericConnectionWrapper))
|
self.assert_(not isinstance(conn, db_pool.GenericConnectionWrapper))
|
||||||
|
|
||||||
self.assertEquals(None, self.pool._unwrap_connection(None))
|
self.assertEquals(None, self.pool._unwrap_connection(None))
|
||||||
self.assertEquals(None, self.pool._unwrap_connection(1))
|
self.assertEquals(None, self.pool._unwrap_connection(1))
|
||||||
|
|
||||||
# testing duck typing here -- as long as the connection has a
|
# testing duck typing here -- as long as the connection has a
|
||||||
# _base attribute, it should be unwrappable
|
# _base attribute, it should be unwrappable
|
||||||
x = Mock()
|
x = Mock()
|
||||||
x._base = 'hi'
|
x._base = 'hi'
|
||||||
self.assertEquals('hi', self.pool._unwrap_connection(x))
|
self.assertEquals('hi', self.pool._unwrap_connection(x))
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
||||||
def test_safe_close(self):
|
def test_safe_close(self):
|
||||||
self.pool._safe_close(self.connection, quiet=True)
|
self.pool._safe_close(self.connection, quiet=True)
|
||||||
self.assertEquals(len(self.pool.free_items), 1)
|
self.assertEquals(len(self.pool.free_items), 1)
|
||||||
|
|
||||||
self.pool._safe_close(None)
|
self.pool._safe_close(None)
|
||||||
self.pool._safe_close(1)
|
self.pool._safe_close(1)
|
||||||
|
|
||||||
# now we're really going for 100% coverage
|
# now we're really going for 100% coverage
|
||||||
x = Mock()
|
x = Mock()
|
||||||
def fail():
|
def fail():
|
||||||
@@ -280,7 +281,7 @@ class DBConnectionPool(DBTester):
|
|||||||
raise RuntimeError("if this line has been printed, the test succeeded")
|
raise RuntimeError("if this line has been printed, the test succeeded")
|
||||||
x.close = fail2
|
x.close = fail2
|
||||||
self.pool._safe_close(x, quiet=False)
|
self.pool._safe_close(x, quiet=False)
|
||||||
|
|
||||||
def test_zero_max_idle(self):
|
def test_zero_max_idle(self):
|
||||||
self.pool.put(self.connection)
|
self.pool.put(self.connection)
|
||||||
self.pool.clear()
|
self.pool.clear()
|
||||||
@@ -296,10 +297,13 @@ class DBConnectionPool(DBTester):
|
|||||||
self.connection = self.pool.get()
|
self.connection = self.pool.get()
|
||||||
self.connection.close()
|
self.connection.close()
|
||||||
self.assertEquals(len(self.pool.free_items), 0)
|
self.assertEquals(len(self.pool.free_items), 0)
|
||||||
|
|
||||||
@skipped
|
@skipped
|
||||||
def test_max_idle(self):
|
def test_max_idle(self):
|
||||||
# This test is timing-sensitive. Rename the function without the "dont" to run it, but beware that it could fail or take a while.
|
# This test is timing-sensitive. Rename the function without
|
||||||
|
# the "dont" to run it, but beware that it could fail or take
|
||||||
|
# a while.
|
||||||
|
|
||||||
self.pool = self.create_pool(max_size=2, max_idle=0.02)
|
self.pool = self.create_pool(max_size=2, max_idle=0.02)
|
||||||
self.connection = self.pool.get()
|
self.connection = self.pool.get()
|
||||||
self.connection.close()
|
self.connection.close()
|
||||||
@@ -319,7 +323,10 @@ class DBConnectionPool(DBTester):
|
|||||||
|
|
||||||
@skipped
|
@skipped
|
||||||
def test_max_idle_many(self):
|
def test_max_idle_many(self):
|
||||||
# This test is timing-sensitive. Rename the function without the "dont" to run it, but beware that it could fail or take a while.
|
# This test is timing-sensitive. Rename the function without
|
||||||
|
# the "dont" to run it, but beware that it could fail or take
|
||||||
|
# a while.
|
||||||
|
|
||||||
self.pool = self.create_pool(max_size=2, max_idle=0.02)
|
self.pool = self.create_pool(max_size=2, max_idle=0.02)
|
||||||
self.connection, conn2 = self.pool.get(), self.pool.get()
|
self.connection, conn2 = self.pool.get(), self.pool.get()
|
||||||
self.connection.close()
|
self.connection.close()
|
||||||
@@ -332,7 +339,10 @@ class DBConnectionPool(DBTester):
|
|||||||
|
|
||||||
@skipped
|
@skipped
|
||||||
def test_max_age(self):
|
def test_max_age(self):
|
||||||
# This test is timing-sensitive. Rename the function without the "dont" to run it, but beware that it could fail or take a while.
|
# This test is timing-sensitive. Rename the function without
|
||||||
|
# the "dont" to run it, but beware that it could fail or take
|
||||||
|
# a while.
|
||||||
|
|
||||||
self.pool = self.create_pool(max_size=2, max_age=0.05)
|
self.pool = self.create_pool(max_size=2, max_age=0.05)
|
||||||
self.connection = self.pool.get()
|
self.connection = self.pool.get()
|
||||||
self.connection.close()
|
self.connection.close()
|
||||||
@@ -347,7 +357,10 @@ class DBConnectionPool(DBTester):
|
|||||||
|
|
||||||
@skipped
|
@skipped
|
||||||
def test_max_age_many(self):
|
def test_max_age_many(self):
|
||||||
# This test is timing-sensitive. Rename the function without the "dont" to run it, but beware that it could fail or take a while.
|
# This test is timing-sensitive. Rename the function without
|
||||||
|
# the "dont" to run it, but beware that it could fail or take
|
||||||
|
# a while.
|
||||||
|
|
||||||
self.pool = self.create_pool(max_size=2, max_age=0.15)
|
self.pool = self.create_pool(max_size=2, max_age=0.15)
|
||||||
self.connection, conn2 = self.pool.get(), self.pool.get()
|
self.connection, conn2 = self.pool.get(), self.pool.get()
|
||||||
self.connection.close()
|
self.connection.close()
|
||||||
@@ -366,7 +379,7 @@ class DBConnectionPool(DBTester):
|
|||||||
self.pool.put(self.connection)
|
self.pool.put(self.connection)
|
||||||
self.pool.clear()
|
self.pool.clear()
|
||||||
self.pool = self.create_pool(max_size=1, max_age=0)
|
self.pool = self.create_pool(max_size=1, max_age=0)
|
||||||
|
|
||||||
self.connection = self.pool.get()
|
self.connection = self.pool.get()
|
||||||
self.assertEquals(self.pool.free(), 0)
|
self.assertEquals(self.pool.free(), 0)
|
||||||
self.assertEquals(self.pool.waiting(), 0)
|
self.assertEquals(self.pool.waiting(), 0)
|
||||||
@@ -397,7 +410,7 @@ class DBConnectionPool(DBTester):
|
|||||||
def bench(c):
|
def bench(c):
|
||||||
for i in xrange(iterations):
|
for i in xrange(iterations):
|
||||||
c.execute('select 1')
|
c.execute('select 1')
|
||||||
|
|
||||||
bench(c) # warm-up
|
bench(c) # warm-up
|
||||||
results = []
|
results = []
|
||||||
for i in xrange(3):
|
for i in xrange(3):
|
||||||
@@ -405,7 +418,7 @@ class DBConnectionPool(DBTester):
|
|||||||
bench(c)
|
bench(c)
|
||||||
end = time.time()
|
end = time.time()
|
||||||
results.append(end-start)
|
results.append(end-start)
|
||||||
|
|
||||||
print "\n%u iterations took an average of %f seconds, (%s) in %s\n" % (
|
print "\n%u iterations took an average of %f seconds, (%s) in %s\n" % (
|
||||||
iterations, sum(results)/len(results), results, type(self))
|
iterations, sum(results)/len(results), results, type(self))
|
||||||
|
|
||||||
@@ -415,29 +428,30 @@ class DBConnectionPool(DBTester):
|
|||||||
self.pool = self.create_pool(max_size=1, module=RaisingDBModule())
|
self.pool = self.create_pool(max_size=1, module=RaisingDBModule())
|
||||||
self.assertRaises(RuntimeError, self.pool.get)
|
self.assertRaises(RuntimeError, self.pool.get)
|
||||||
self.assertEquals(self.pool.free(), 1)
|
self.assertEquals(self.pool.free(), 1)
|
||||||
|
|
||||||
|
|
||||||
class RaisingDBModule(object):
|
class RaisingDBModule(object):
|
||||||
def connect(self, *args, **kw):
|
def connect(self, *args, **kw):
|
||||||
raise RuntimeError()
|
raise RuntimeError()
|
||||||
|
|
||||||
|
|
||||||
class TpoolConnectionPool(DBConnectionPool):
|
class TpoolConnectionPool(DBConnectionPool):
|
||||||
__test__ = False # so that nose doesn't try to execute this directly
|
__test__ = False # so that nose doesn't try to execute this directly
|
||||||
def create_pool(self, max_size = 1, max_idle = 10, max_age = 10, connect_timeout=0.5, module=None):
|
def create_pool(self, max_size=1, max_idle=10, max_age=10,
|
||||||
|
connect_timeout=0.5, module=None):
|
||||||
if module is None:
|
if module is None:
|
||||||
module = self._dbmodule
|
module = self._dbmodule
|
||||||
return db_pool.TpooledConnectionPool(module,
|
return db_pool.TpooledConnectionPool(module,
|
||||||
min_size=0, max_size=max_size,
|
min_size=0, max_size=max_size,
|
||||||
max_idle=max_idle, max_age=max_age,
|
max_idle=max_idle, max_age=max_age,
|
||||||
connect_timeout = connect_timeout,
|
connect_timeout = connect_timeout,
|
||||||
**self._auth)
|
**self._auth)
|
||||||
|
|
||||||
|
|
||||||
@skip_with_pyevent
|
@skip_with_pyevent
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(TpoolConnectionPool, self).setUp()
|
super(TpoolConnectionPool, self).setUp()
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
super(TpoolConnectionPool, self).tearDown()
|
super(TpoolConnectionPool, self).tearDown()
|
||||||
from eventlet import tpool
|
from eventlet import tpool
|
||||||
@@ -447,19 +461,21 @@ class TpoolConnectionPool(DBConnectionPool):
|
|||||||
|
|
||||||
class RawConnectionPool(DBConnectionPool):
|
class RawConnectionPool(DBConnectionPool):
|
||||||
__test__ = False # so that nose doesn't try to execute this directly
|
__test__ = False # so that nose doesn't try to execute this directly
|
||||||
def create_pool(self, max_size = 1, max_idle = 10, max_age = 10, connect_timeout= 0.5, module=None):
|
def create_pool(self, max_size=1, max_idle=10, max_age=10,
|
||||||
|
connect_timeout=0.5, module=None):
|
||||||
if module is None:
|
if module is None:
|
||||||
module = self._dbmodule
|
module = self._dbmodule
|
||||||
return db_pool.RawConnectionPool(module,
|
return db_pool.RawConnectionPool(module,
|
||||||
min_size=0, max_size=max_size,
|
min_size=0, max_size=max_size,
|
||||||
max_idle=max_idle, max_age=max_age,
|
max_idle=max_idle, max_age=max_age,
|
||||||
connect_timeout=connect_timeout,
|
connect_timeout=connect_timeout,
|
||||||
**self._auth)
|
**self._auth)
|
||||||
|
|
||||||
|
|
||||||
def get_auth():
|
def get_auth():
|
||||||
"""Looks in the local directory and in the user's home directory for a file named ".test_dbauth",
|
"""Looks in the local directory and in the user's home directory
|
||||||
which contains a json map of parameters to the connect function.
|
for a file named ".test_dbauth", which contains a json map of
|
||||||
|
parameters to the connect function.
|
||||||
"""
|
"""
|
||||||
files = [os.path.join(os.path.dirname(__file__), '.test_dbauth'),
|
files = [os.path.join(os.path.dirname(__file__), '.test_dbauth'),
|
||||||
os.path.join(os.path.expanduser('~'), '.test_dbauth')]
|
os.path.join(os.path.expanduser('~'), '.test_dbauth')]
|
||||||
@@ -473,7 +489,7 @@ def get_auth():
|
|||||||
return dict([(str(modname), dict([(str(k), str(v))
|
return dict([(str(modname), dict([(str(k), str(v))
|
||||||
for k, v in connectargs.items()]))
|
for k, v in connectargs.items()]))
|
||||||
for modname, connectargs in auth_utf8.items()])
|
for modname, connectargs in auth_utf8.items()])
|
||||||
except (IOError, ImportError), e:
|
except (IOError, ImportError):
|
||||||
pass
|
pass
|
||||||
return {'MySQLdb':{'host': 'localhost','user': 'root','passwd': ''},
|
return {'MySQLdb':{'host': 'localhost','user': 'root','passwd': ''},
|
||||||
'psycopg2':{'user':'test'}}
|
'psycopg2':{'user':'test'}}
|
||||||
@@ -487,26 +503,26 @@ def mysql_requirement(_f):
|
|||||||
MySQLdb.connect(**auth)
|
MySQLdb.connect(**auth)
|
||||||
return True
|
return True
|
||||||
except MySQLdb.OperationalError:
|
except MySQLdb.OperationalError:
|
||||||
print "Skipping mysql tests, error when connecting"
|
print >> sys.stderr, ">> Skipping mysql tests, error when connecting:"
|
||||||
import traceback
|
import traceback
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
return False
|
return False
|
||||||
except ImportError:
|
except ImportError:
|
||||||
print "Skipping mysql tests, MySQLdb not importable"
|
print >> sys.stderr, ">> Skipping mysql tests, MySQLdb not importable"
|
||||||
return False
|
return False
|
||||||
|
|
||||||
class MysqlConnectionPool(object):
|
class MysqlConnectionPool(object):
|
||||||
dummy_table_sql = """CREATE TEMPORARY TABLE test_table
|
dummy_table_sql = """CREATE TEMPORARY TABLE test_table
|
||||||
(
|
(
|
||||||
row_id INTEGER PRIMARY KEY AUTO_INCREMENT,
|
row_id INTEGER PRIMARY KEY AUTO_INCREMENT,
|
||||||
value_int INTEGER,
|
value_int INTEGER,
|
||||||
value_float FLOAT,
|
value_float FLOAT,
|
||||||
value_string VARCHAR(200),
|
value_string VARCHAR(200),
|
||||||
value_uuid CHAR(36),
|
value_uuid CHAR(36),
|
||||||
value_binary BLOB,
|
value_binary BLOB,
|
||||||
value_binary_string VARCHAR(200) BINARY,
|
value_binary_string VARCHAR(200) BINARY,
|
||||||
value_enum ENUM('Y','N'),
|
value_enum ENUM('Y','N'),
|
||||||
created TIMESTAMP
|
created TIMESTAMP
|
||||||
) ENGINE=InnoDB;"""
|
) ENGINE=InnoDB;"""
|
||||||
|
|
||||||
@skip_unless(mysql_requirement)
|
@skip_unless(mysql_requirement)
|
||||||
@@ -515,7 +531,7 @@ class MysqlConnectionPool(object):
|
|||||||
self._dbmodule = MySQLdb
|
self._dbmodule = MySQLdb
|
||||||
self._auth = get_auth()['MySQLdb']
|
self._auth = get_auth()['MySQLdb']
|
||||||
super(MysqlConnectionPool, self).setUp()
|
super(MysqlConnectionPool, self).setUp()
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
super(MysqlConnectionPool, self).tearDown()
|
super(MysqlConnectionPool, self).tearDown()
|
||||||
|
|
||||||
@@ -561,16 +577,16 @@ def postgres_requirement(_f):
|
|||||||
|
|
||||||
|
|
||||||
class Psycopg2ConnectionPool(object):
|
class Psycopg2ConnectionPool(object):
|
||||||
dummy_table_sql = """CREATE TEMPORARY TABLE test_table
|
dummy_table_sql = """CREATE TEMPORARY TABLE test_table
|
||||||
(
|
(
|
||||||
row_id SERIAL PRIMARY KEY,
|
row_id SERIAL PRIMARY KEY,
|
||||||
value_int INTEGER,
|
value_int INTEGER,
|
||||||
value_float FLOAT,
|
value_float FLOAT,
|
||||||
value_string VARCHAR(200),
|
value_string VARCHAR(200),
|
||||||
value_uuid CHAR(36),
|
value_uuid CHAR(36),
|
||||||
value_binary BYTEA,
|
value_binary BYTEA,
|
||||||
value_binary_string BYTEA,
|
value_binary_string BYTEA,
|
||||||
created TIMESTAMP
|
created TIMESTAMP
|
||||||
);"""
|
);"""
|
||||||
|
|
||||||
@skip_unless(postgres_requirement)
|
@skip_unless(postgres_requirement)
|
||||||
@@ -600,7 +616,6 @@ class Psycopg2ConnectionPool(object):
|
|||||||
|
|
||||||
def drop_db(self):
|
def drop_db(self):
|
||||||
auth = self._auth.copy()
|
auth = self._auth.copy()
|
||||||
dbname = auth.pop('database')
|
|
||||||
conn = self._dbmodule.connect(**auth)
|
conn = self._dbmodule.connect(**auth)
|
||||||
conn.set_isolation_level(0)
|
conn.set_isolation_level(0)
|
||||||
db = conn.cursor()
|
db = conn.cursor()
|
||||||
|
Reference in New Issue
Block a user