Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#8: connection timeout #10

Merged
merged 4 commits into from
May 31, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 17 additions & 5 deletions Products/ZMySQLDA/DA.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ class Connection(ConnectionBase):
auto_create_db = True
use_unicode = False
charset = None
timeout = None
_v_connected = ''
_isAnSQLConnection = 1
info = None
Expand All @@ -70,7 +71,7 @@ class Connection(ConnectionBase):
{'label': 'Browse', 'action': 'manage_browse'},)

def __init__(self, id, title, connection_string, check, use_unicode=None,
charset=None, auto_create_db=None):
charset=None, auto_create_db=None, timeout=None):
""" Instance setup. Optionally opens the connection.

:string: id -- The id of the ZMySQLDA Connection
Expand Down Expand Up @@ -105,10 +106,13 @@ def __init__(self, id, title, connection_string, check, use_unicode=None,
:bool: auto_create_db -- If the database given in ``connection_string``
does not exist, create it automatically.
Default: False.
:int: timeout -- The connect timeout for the connection in seconds.
Default: None
"""
self.use_unicode = bool(use_unicode)
self.charset = charset
self.auto_create_db = bool(auto_create_db)
self.timeout = int(timeout) if timeout else None
return super(Connection, self).__init__(id, title, connection_string,
check)

Expand Down Expand Up @@ -160,7 +164,8 @@ def connect(self, conn_string):

conn_pool = DBPool(self.factory(), create_db=self.auto_create_db,
use_unicode=self.use_unicode,
charset=self.charset)
charset=self.charset,
timeout=self.timeout)
database_connection_pool_lock.acquire()
try:
conn = conn_pool(conn_string)
Expand Down Expand Up @@ -199,7 +204,7 @@ def sql_quote__(self, sql_str, escapes={}):

def manage_edit(self, title, connection_string, check=None,
use_unicode=None, charset=None, auto_create_db=None,
REQUEST=None):
timeout=None, REQUEST=None):
""" Edit the connection attributes through the Zope ZMI.

:string: title -- The title of the ZMySQLDA Connection
Expand Down Expand Up @@ -227,11 +232,15 @@ def manage_edit(self, title, connection_string, check=None,
does not exist, create it automatically.
Default: False.

:int: timeout -- The connect timeout for the connection in seconds.
Default: None

:request: REQUEST -- A Zope REQUEST object
"""
self.use_unicode = bool(use_unicode)
self.charset = charset
self.auto_create_db = bool(auto_create_db)
self.timeout = int(timeout) if timeout else None

try:
result = super(Connection, self).manage_edit(title,
Expand Down Expand Up @@ -288,7 +297,7 @@ def tpValues(self):

def manage_addZMySQLConnection(self, id, title, connection_string, check=None,
use_unicode=None, auto_create_db=None,
charset=None, REQUEST=None):
charset=None, timeout=None, REQUEST=None):
"""Factory function to add a connection object from the Zope ZMI.

:string: id -- The id of the ZMySQLDA Connection
Expand Down Expand Up @@ -324,13 +333,16 @@ def manage_addZMySQLConnection(self, id, title, connection_string, check=None,
does not exist, create it automatically.
Default: False.

:int: timeout -- The connect timeout for the connection in seconds.
Default: None

:object: REQUEST -- The currently active Zope request object.
Default: None.
"""
self._setObject(id,
Connection(id, title, connection_string, check,
use_unicode=use_unicode, charset=charset,
auto_create_db=auto_create_db))
auto_create_db=auto_create_db, timeout=timeout))

if REQUEST is not None:
return self.manage_main(self, REQUEST)
Expand Down
12 changes: 9 additions & 3 deletions Products/ZMySQLDA/db.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,9 +110,10 @@ class DBPool(object):
_create_db = False
use_unicode = False
charset = None
timeout = None

def __init__(self, db_cls, create_db=False, use_unicode=False,
charset=None):
charset=None, timeout=None):
""" Set transaction managed class for use in pool.
"""
self._db_cls = db_cls
Expand All @@ -124,6 +125,8 @@ def __init__(self, db_cls, create_db=False, use_unicode=False,
# unicode settings
self.use_unicode = use_unicode
self.charset = charset
# timeout setting
self.timeout = int(timeout) if timeout else None

def __call__(self, connection):
""" Parse the connection string.
Expand All @@ -136,7 +139,8 @@ def __call__(self, connection):
self.connection = connection
db_flags = self._db_cls._parse_connection_string(connection,
self.use_unicode,
charset=self.charset)
charset=self.charset,
timeout=self.timeout)
self._db_flags = db_flags

# connect to server to determin tranasactional capabilities
Expand Down Expand Up @@ -337,7 +341,7 @@ def _forceReconnection(self):

@classmethod
def _parse_connection_string(cls, connection, use_unicode=False,
charset=None):
charset=None, timeout=None):
""" Done as a class method to both allow access to class attribute
conv (conversion) settings while allowing for wrapping pool class
use of this method. The former is important to allow for subclasses
Expand Down Expand Up @@ -387,6 +391,8 @@ def _parse_connection_string(cls, connection, use_unicode=False,
kw_args['passwd'], items = items[0], items[1:]
if items:
kw_args['unix_socket'], items = items[0], items[1:]
if timeout:
kw_args['connect_timeout'] = timeout

return flags

Expand Down
21 changes: 14 additions & 7 deletions Products/ZMySQLDA/tests/test_DA.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,14 @@ def _simpleMakeOne(self):

def test_initialization(self):
conn = self._makeOne('conn_id', 'Conn Title', 'db_conn_string', False,
use_unicode=True, auto_create_db=True)
use_unicode=True, auto_create_db=True, timeout=3)
self.assertEqual(conn.getId(), 'conn_id')
self.assertEqual(conn.title, 'Conn Title')
self.assertEqual(conn.connection_string, 'db_conn_string')
self.assertTrue(conn.use_unicode)
self.assertIsNone(conn.charset)
self.assertTrue(conn.auto_create_db)
self.assertEqual(conn.timeout, 3)

def test_factory(self):
from Products.ZMySQLDA.db import DB
Expand All @@ -71,22 +72,25 @@ def fake_connect(self, conn_str):
conn = self._simpleMakeOne()

conn.manage_edit('New Title', 'new_conn_string', check=False,
use_unicode=True, auto_create_db=True)
use_unicode=True, auto_create_db=True, timeout=3)
self.assertEqual(conn.title, 'New Title')
self.assertEqual(conn.connection_string, 'new_conn_string')
self.assertTrue(conn.use_unicode)
self.assertTrue(conn.auto_create_db)
self.assertIsNone(conn.charset)
self.assertFalse(conn.connected())
self.assertEqual(conn.timeout, 3)

conn.manage_edit('Another Title', 'another_conn_string', check=True,
use_unicode=None, auto_create_db=None, charset='utf8')
use_unicode=None, auto_create_db=None, charset='utf8',
timeout=20)
self.assertEqual(conn.title, 'Another Title')
self.assertEqual(conn.connection_string, 'another_conn_string')
self.assertFalse(conn.use_unicode)
self.assertEqual(conn.charset, 'utf8')
self.assertFalse(conn.auto_create_db)
self.assertTrue(conn.connected())
self.assertEqual(conn.timeout, 20)

Connection.connect = old_connect

Expand All @@ -98,23 +102,25 @@ def test_zope_factory(self):
manage_addZMySQLConnection(container, 'conn_id', 'Conn Title',
'db_conn_string', False,
use_unicode=True, charset='utf8',
auto_create_db=True)
auto_create_db=True, timeout=15)
conn = container.conn_id
self.assertEqual(conn.getId(), 'conn_id')
self.assertEqual(conn.title, 'Conn Title')
self.assertEqual(conn.connection_string, 'db_conn_string')
self.assertTrue(conn.use_unicode)
self.assertEqual(conn.charset, 'utf8')
self.assertTrue(conn.auto_create_db)
self.assertEqual(conn.timeout, 15)

# Make sure the defaults for use_unicode and auto_create_db
# Make sure the defaults for use_unicode, auto_create_db and timeout
# do the right thing
manage_addZMySQLConnection(container, 'conn2', 'Other title',
'db_conn_string', False)
conn = container.conn2
self.assertFalse(conn.use_unicode)
self.assertIsNone(conn.charset)
self.assertFalse(conn.auto_create_db)
self.assertIsNone(conn.timeout)


class PatchedConnectionTests(PatchedConnectionTestsBase):
Expand Down Expand Up @@ -181,10 +187,11 @@ class RealConnectionTests(unittest.TestCase):

layer = MySQLRequiredLayer

def _makeOne(self, use_unicode=False, charset=None):
def _makeOne(self, use_unicode=False, charset=None, timeout=None):
from Products.ZMySQLDA.DA import Connection
return Connection('conn_id', 'Conn Title', DB_CONN_STRING, False,
use_unicode=use_unicode, charset=charset)
use_unicode=use_unicode, charset=charset,
timeout=timeout)

def _makeRequest(self):
class DummyRequest(dict):
Expand Down
1 change: 1 addition & 0 deletions Products/ZMySQLDA/tests/test_db.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ def test_instantiate_defaults(self):
self.assertFalse(pool._create_db)
self.assertFalse(pool.use_unicode)
self.assertIsNone(pool.charset)
self.assertIsNone(pool.timeout)

def test_instantiate_use_unicode(self):
pool = self._makeOne(create_db=True, use_unicode=True)
Expand Down
9 changes: 9 additions & 0 deletions Products/ZMySQLDA/www/connectionAdd.dtml
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,15 @@
</small>
</td>
</tr>
<tr>
<th align="left" valign="top">
Connect timeout
</th>
<td align="left" valign="top">
<input type="text" name="timeout" size="3" />
<small>in seconds</small>
</td>
</tr>
<tr>
<td></td>
<td><br><input type="submit" value="Add"></td>
Expand Down
12 changes: 12 additions & 0 deletions Products/ZMySQLDA/www/connectionEdit.dtml
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,18 @@
</dtml-let>
</td>
</tr>
<tr>
<th align="left" valign="top">
Connect timeout
</th>
<td align="left" valign="top">
<dtml-let preptimeout="timeout and str(timeout) or ''">
<input type="text" name="timeout" size="3" value="&dtml-preptimeout;" />
</dtml-let>
<small>in seconds</small>
</td>
</tr>

<td></td>
<td><br><input type="submit" value="Change"></td>
</tr>
Expand Down