On 15 July 2011 17:26, D'Arcy J.M. Cain <[email protected]> wrote:

> On Fri, 15 Jul 2011 17:02:43 +0100
> Maxim Yegorushkin <[email protected]> wrote:
> > However, it misses support for datetime.date objects and can't correctly
> > quote floats with nan value. So, I thought you may like to consider
> adding
> > the following to pgdb.py:
>
> Looks reasonable.  Can you work up the unit tests as well?  See the
> script TEST_PyGreSQL_dbapi20.py.  I did check and your changes don't
> break the existing tests but we always like to add new tests along with
> new code.


Oh, I am a fan of unit tests myself. The original patch was made in anger,
here is a more thoughtful one.

This patch extends float handling by supporting nan and inf values along
with a new unit test. It basically always quotes floats to avoid isinf() and
isnan() checks for each and every float value.

With regards to date support, I am thinking of handling date and datetime
similar to decimal, that is, to convert strings to date and datetime when
reading rowsets, so that user code does not have to convert strings to
dates. Does it make sense?

-- Maxim
Index: setup.py
===================================================================
--- setup.py	(revision 429)
+++ setup.py	(working copy)
@@ -71,7 +71,7 @@
 libraries = ['pq']
 include_dirs = [pg_config('includedir')]
 library_dirs=[pg_config('libdir')]
-define_macros = [('PYGRESQL_VERSION', '\\"%s\\"' % version)]
+define_macros = [('PYGRESQL_VERSION', '"\\"%s\\""' % version)]
 undef_macros = []
 extra_compile_args = ['-O2']
 
Index: TEST_PyGreSQL_dbapi20.py
===================================================================
--- TEST_PyGreSQL_dbapi20.py	(revision 429)
+++ TEST_PyGreSQL_dbapi20.py	(working copy)
@@ -4,6 +4,7 @@
 import dbapi20
 import unittest
 import pgdb
+import math
 
 # We need a database to test against.
 # If LOCAL_PyGreSQL.py exists we will get our information from that.
@@ -93,6 +94,28 @@
         finally:
             con.close()
 
+    def test_float(self):
+        values = [ (3.14,), (float('nan'),), (float('+inf'),), (float('-inf'),) ]
+        table = self.table_prefix + 'float'
+        con = self._connect()
+        try:
+            cur = con.cursor()
+            cur.execute("create table %s (floattest float8)" % table)
+            cur.executemany("insert into %s values(%%s)" % table, values)
+            cur.execute("select * from %s" % table)
+            rows = cur.fetchall()
+            self.assertEqual(len(rows), len(values))
+            for (val,), (db_val,) in zip(values, rows):
+                if math.isinf(val):
+                    self.assertTrue(math.isinf(db_val))
+                    self.assertEqual(math.copysign(1, val), math.copysign(1, db_val))
+                elif math.isnan(val):
+                    self.assertTrue(math.isnan(db_val))
+                else:
+                    self.assertEqual(val, db_val)
+        finally:
+            con.close()
+
     def test_set_decimal_type(self):
         decimal_type = pgdb.decimal_type()
         self.assertTrue(decimal_type is not None and callable(decimal_type))
Index: pgdb.py
===================================================================
--- pgdb.py	(revision 429)
+++ pgdb.py	(working copy)
@@ -201,8 +201,11 @@
                 val = "E'%s'" % self._cnx.escape_bytea(val)
             else:
                 val = "'%s'" % self._cnx.escape_string(val)
-        elif isinstance(val, (int, long, float)):
+        elif isinstance(val, (int, long)):
             pass
+        elif isinstance(val, float):
+            # always quote floats to handle nan, +inf and -inf
+            val = "'%s'" % val
         elif val is None:
             val = 'NULL'
         elif isinstance(val, (list, tuple)):
_______________________________________________
PyGreSQL mailing list
[email protected]
http://mailman.vex.net/mailman/listinfo/pygresql

Reply via email to