Author: cito
Date: Sat Jan 9 17:53:44 2016
New Revision: 706
Log:
Make sure DB methods respect the new bool option
Two DB methods assumed that booleans are always returned as strings,
which is no longer true when the set_bool() option is activated.
Added a test run with different global options to make sure that
no DB methods make such tacit assumptions about these options.
Modified:
branches/4.x/module/pg.py
trunk/module/pg.py
trunk/module/tests/test_classic_dbwrapper.py
Modified: branches/4.x/module/pg.py
==============================================================================
--- branches/4.x/module/pg.py Sat Jan 9 15:49:18 2016 (r705)
+++ branches/4.x/module/pg.py Sat Jan 9 17:53:44 2016 (r706)
@@ -338,6 +338,13 @@
else:
print(s)
+ def _make_bool(d):
+ """Get boolean value corresponding to d."""
+ if get_bool():
+ return bool(d)
+ return d and 't' or 'f'
+ _make_bool = staticmethod(_make_bool)
+
def _quote_text(self, d):
"""Quote text value."""
if not isinstance(d, basestring):
@@ -352,9 +359,7 @@
if not d:
return 'NULL'
d = d.lower() in self._bool_true
- else:
- d = bool(d)
- return ("'f'", "'t'")[d]
+ return d and "'t'" or "'f'"
_date_literals = frozenset('current_date current_time'
' current_timestamp localtime localtimestamp'.split())
@@ -716,7 +721,7 @@
return self._privileges[(qcl, privilege)]
except KeyError:
q = "SELECT has_table_privilege('%s', '%s')" % (qcl, privilege)
- ret = self.db.query(q).getresult()[0][0] == 't'
+ ret = self.db.query(q).getresult()[0][0] == self._make_bool(True)
self._privileges[(qcl, privilege)] = ret
return ret
@@ -895,7 +900,7 @@
def clear(self, cl, a=None):
"""Clear all the attributes to values determined by the types.
- Numeric types are set to 0, Booleans are set to 'f', and everything
+ Numeric types are set to 0, Booleans are set to false, and everything
else is set to the empty string. If the array argument is present,
it is used as the array and any entries matching attribute names are
cleared with everything else left unchanged.
@@ -914,7 +919,7 @@
'num', 'numeric', 'money'):
a[n] = 0
elif t in ('bool', 'boolean'):
- a[n] = 'f'
+ a[n] = self._make_bool(False)
else:
a[n] = ''
return a
Modified: trunk/module/pg.py
==============================================================================
--- trunk/module/pg.py Sat Jan 9 15:49:18 2016 (r705)
+++ trunk/module/pg.py Sat Jan 9 17:53:44 2016 (r706)
@@ -340,6 +340,11 @@
else:
print(s)
+ @staticmethod
+ def _make_bool(d):
+ """Get boolean value corresponding to d."""
+ return bool(d) if get_bool() else ('t' if d else 'f')
+
def _quote_text(self, d):
"""Quote text value."""
if not isinstance(d, basestring):
@@ -354,9 +359,7 @@
if not d:
return 'NULL'
d = d.lower() in self._bool_true
- else:
- d = bool(d)
- return ("'f'", "'t'")[d]
+ return "'t'" if d else "'f'"
_date_literals = frozenset('current_date current_time'
' current_timestamp localtime localtimestamp'.split())
@@ -722,7 +725,7 @@
return self._privileges[(qcl, privilege)]
except KeyError:
q = "SELECT has_table_privilege('%s', '%s')" % (qcl, privilege)
- ret = self.db.query(q).getresult()[0][0] == 't'
+ ret = self.db.query(q).getresult()[0][0] == self._make_bool(True)
self._privileges[(qcl, privilege)] = ret
return ret
@@ -913,7 +916,7 @@
def clear(self, cl, a=None):
"""Clear all the attributes to values determined by the types.
- Numeric types are set to 0, Booleans are set to 'f', and everything
+ Numeric types are set to 0, Booleans are set to false, and everything
else is set to the empty string. If the array argument is present,
it is used as the array and any entries matching attribute names are
cleared with everything else left unchanged.
@@ -932,7 +935,7 @@
'num', 'numeric', 'money'):
a[n] = 0
elif t in ('bool', 'boolean'):
- a[n] = 'f'
+ a[n] = self._make_bool(False)
else:
a[n] = ''
return a
Modified: trunk/module/tests/test_classic_dbwrapper.py
==============================================================================
--- trunk/module/tests/test_classic_dbwrapper.py Sat Jan 9 15:49:18
2016 (r705)
+++ trunk/module/tests/test_classic_dbwrapper.py Sat Jan 9 17:53:44
2016 (r706)
@@ -670,6 +670,8 @@
self.assertEqual(can('test', 'insert'), True)
self.assertEqual(can('test', 'update'), True)
self.assertEqual(can('test', 'delete'), True)
+ self.assertEqual(can('pg_views', 'select'), True)
+ self.assertEqual(can('pg_views', 'delete'), False)
self.assertRaises(pg.ProgrammingError, can, 'test', 'foobar')
self.assertRaises(pg.ProgrammingError, can, 'table_does_not_exist')
@@ -757,6 +759,8 @@
insert = self.db.insert
query = self.db.query
server_version = self.db.server_version
+ bool_on = pg.get_bool()
+ decimal = pg.get_decimal()
for table in ('insert_test_table', 'test table for insert'):
query('drop table if exists "%s"' % table)
query('create table "%s" ('
@@ -819,6 +823,17 @@
data, change = test
expect = data.copy()
expect.update(change)
+ if bool_on:
+ b = expect.get('b')
+ if b is not None:
+ expect['b'] = b == 't'
+ if decimal is not Decimal:
+ d = expect.get('d')
+ if d is not None:
+ expect['d'] = decimal(d)
+ m = expect.get('m')
+ if m is not None:
+ expect['m'] = decimal(m)
if data.get('m') and server_version < 910000:
# PostgreSQL < 9.1 cannot directly convert numbers to money
data['m'] = "'%s'::money" % data['m']
@@ -909,19 +924,20 @@
def testClear(self):
clear = self.db.clear
query = self.db.query
+ f = False if pg.get_bool() else 'f'
for table in ('clear_test_table', 'test table for clear'):
query('drop table if exists "%s"' % table)
query('create table "%s" ('
"n integer, b boolean, d date, t text)" % table)
r = clear(table)
- result = {'n': 0, 'b': 'f', 'd': '', 't': ''}
+ result = {'n': 0, 'b': f, 'd': '', 't': ''}
self.assertEqual(r, result)
r['a'] = r['n'] = 1
r['d'] = r['t'] = 'x'
r['b'] = 't'
r['oid'] = long(1)
r = clear(table, r)
- result = {'a': 1, 'n': 0, 'b': 'f', 'd': '', 't': '',
+ result = {'a': 1, 'n': 0, 'b': f, 'd': '', 't': '',
'oid': long(1)}
self.assertEqual(r, result)
query('drop table "%s"' % table)
@@ -1143,6 +1159,36 @@
self.db.debug = debug
+class TestDBClassNonStdOpts(TestDBClass):
+ """Test the methods of the DB class with non-standard global options."""
+
+ @classmethod
+ def setUpClass(cls):
+ cls.saved_options = {}
+ cls.set_option('decimal', float)
+ not_bool = not pg.get_bool()
+ cls.set_option('bool', not_bool)
+ unnamed_result = lambda q: q.getresult()
+ cls.set_option('namedresult', unnamed_result)
+ super(TestDBClassNonStdOpts, cls).setUpClass()
+
+ @classmethod
+ def tearDownClass(cls):
+ super(TestDBClassNonStdOpts, cls).tearDownClass()
+ cls.reset_option('namedresult')
+ cls.reset_option('bool')
+ cls.reset_option('decimal')
+
+ @classmethod
+ def set_option(cls, option, value):
+ cls.saved_options[option] = getattr(pg, 'get_' + option)()
+ return getattr(pg, 'set_' + option)(value)
+
+ @classmethod
+ def reset_option(cls, option):
+ return getattr(pg, 'set_' + option)(cls.saved_options[option])
+
+
class TestSchemas(unittest.TestCase):
"""Test correct handling of schemas (namespaces)."""
_______________________________________________
PyGreSQL mailing list
[email protected]
https://mail.vex.net/mailman/listinfo.cgi/pygresql