[Python-checkins] r62707 - in python/branches/tlee-ast-optimize: Doc/library/sqlite3.rst Doc/library/unittest.rst Doc/whatsnew/2.6.rst Lib/sqlite3/test/factory.py Lib/sqlite3/test/types.py Modules/_sqlite/cursor.c Modules/_sqlite/row.c Modules/_sqlite/statement.c

thomas.lee python-checkins at python.org
Sun May 4 19:02:25 CEST 2008


Author: thomas.lee
Date: Sun May  4 19:02:25 2008
New Revision: 62707

Log:
Merged revisions 62698-62706 via svnmerge from 
svn+ssh://pythondev@svn.python.org/python/trunk

........
  r62699 | christian.heimes | 2008-05-04 21:50:53 +1000 (Sun, 04 May 2008) | 1 line
  
  Added note that Python requires at least Win2k SP4
........
  r62700 | gerhard.haering | 2008-05-04 22:59:57 +1000 (Sun, 04 May 2008) | 3 lines
  
  SQLite requires 64-bit integers in order to build. So the whole HAVE_LONG_LONG
  #ifdefing was useless.
........
  r62701 | gerhard.haering | 2008-05-04 23:15:12 +1000 (Sun, 04 May 2008) | 3 lines
  
  Applied sqliterow-richcmp.diff patch from Thomas Heller in Issue2152. The
  sqlite3.Row type is now correctly hashable.
........
  r62702 | gerhard.haering | 2008-05-04 23:42:44 +1000 (Sun, 04 May 2008) | 5 lines
  
  Implemented feature request 2157: Converter names are cut off at '('
  characters. This avoids the common case of something like 'NUMBER(10)' not
  being parsed as 'NUMBER', like expected. Also corrected the docs about
  converter names being case-sensitive. They aren't any longer.
........
  r62703 | georg.brandl | 2008-05-05 01:45:05 +1000 (Mon, 05 May 2008) | 2 lines
  
  #2757: Remove spare newline.
........


Modified:
   python/branches/tlee-ast-optimize/   (props changed)
   python/branches/tlee-ast-optimize/Doc/library/sqlite3.rst
   python/branches/tlee-ast-optimize/Doc/library/unittest.rst
   python/branches/tlee-ast-optimize/Doc/whatsnew/2.6.rst
   python/branches/tlee-ast-optimize/Lib/sqlite3/test/factory.py
   python/branches/tlee-ast-optimize/Lib/sqlite3/test/types.py
   python/branches/tlee-ast-optimize/Modules/_sqlite/cursor.c
   python/branches/tlee-ast-optimize/Modules/_sqlite/row.c
   python/branches/tlee-ast-optimize/Modules/_sqlite/statement.c

Modified: python/branches/tlee-ast-optimize/Doc/library/sqlite3.rst
==============================================================================
--- python/branches/tlee-ast-optimize/Doc/library/sqlite3.rst	(original)
+++ python/branches/tlee-ast-optimize/Doc/library/sqlite3.rst	Sun May  4 19:02:25 2008
@@ -114,10 +114,11 @@
    :func:`connect` function.
 
    Setting it makes the :mod:`sqlite3` module parse the declared type for each
-   column it returns.  It will parse out the first word of the declared type, i. e.
-   for "integer primary key", it will parse out "integer". Then for that column, it
-   will look into the converters dictionary and use the converter function
-   registered for that type there.  Converter names are case-sensitive!
+   column it returns.  It will parse out the first word of the declared type,
+   i. e.  for "integer primary key", it will parse out "integer", or for
+   "number(10)" it will parse out "number". Then for that column, it will look
+   into the converters dictionary and use the converter function registered for
+   that type there.
 
 
 .. data:: PARSE_COLNAMES
@@ -666,10 +667,6 @@
    Converter functions **always** get called with a string, no matter under which
    data type you sent the value to SQLite.
 
-.. note::
-
-   Converter names are looked up in a case-sensitive manner.
-
 ::
 
    def convert_point(s):

Modified: python/branches/tlee-ast-optimize/Doc/library/unittest.rst
==============================================================================
--- python/branches/tlee-ast-optimize/Doc/library/unittest.rst	(original)
+++ python/branches/tlee-ast-optimize/Doc/library/unittest.rst	Sun May  4 19:02:25 2008
@@ -262,7 +262,6 @@
 Often, many small test cases will use the same fixture.  In this case, we would
 end up subclassing :class:`SimpleWidgetTestCase` into many small one-method
 classes such as :class:`DefaultWidgetSizeTestCase`.  This is time-consuming and
-
 discouraging, so in the same vein as JUnit, :mod:`unittest` provides a simpler
 mechanism::
 

Modified: python/branches/tlee-ast-optimize/Doc/whatsnew/2.6.rst
==============================================================================
--- python/branches/tlee-ast-optimize/Doc/whatsnew/2.6.rst	(original)
+++ python/branches/tlee-ast-optimize/Doc/whatsnew/2.6.rst	Sun May  4 19:02:25 2008
@@ -2319,6 +2319,9 @@
 Port-Specific Changes: Windows
 -----------------------------------
 
+* The support for Windows 95, 98, ME and NT4 has been dropped.
+  Python 2.6 requires at least Windows 2000 SP4.
+
 * The :mod:`msvcrt` module now supports 
   both the normal and wide char variants of the console I/O
   API.  The :func:`getwch` function reads a keypress and returns a Unicode 

Modified: python/branches/tlee-ast-optimize/Lib/sqlite3/test/factory.py
==============================================================================
--- python/branches/tlee-ast-optimize/Lib/sqlite3/test/factory.py	(original)
+++ python/branches/tlee-ast-optimize/Lib/sqlite3/test/factory.py	Sun May  4 19:02:25 2008
@@ -131,6 +131,26 @@
         self.failUnlessEqual(d["a"], row["a"])
         self.failUnlessEqual(d["b"], row["b"])
 
+    def CheckSqliteRowHashCmp(self):
+        """Checks if the row object compares and hashes correctly"""
+        self.con.row_factory = sqlite.Row
+        row_1 = self.con.execute("select 1 as a, 2 as b").fetchone()
+        row_2 = self.con.execute("select 1 as a, 2 as b").fetchone()
+        row_3 = self.con.execute("select 1 as a, 3 as b").fetchone()
+
+        self.failUnless(row_1 == row_1)
+        self.failUnless(row_1 == row_2)
+        self.failUnless(row_2 != row_3)
+
+        self.failIf(row_1 != row_1)
+        self.failIf(row_1 != row_2)
+        self.failIf(row_2 == row_3)
+
+        self.failUnlessEqual(row_1, row_2)
+        self.failUnlessEqual(hash(row_1), hash(row_2))
+        self.failIfEqual(row_1, row_3)
+        self.failIfEqual(hash(row_1), hash(row_3))
+
     def tearDown(self):
         self.con.close()
 

Modified: python/branches/tlee-ast-optimize/Lib/sqlite3/test/types.py
==============================================================================
--- python/branches/tlee-ast-optimize/Lib/sqlite3/test/types.py	(original)
+++ python/branches/tlee-ast-optimize/Lib/sqlite3/test/types.py	Sun May  4 19:02:25 2008
@@ -98,7 +98,7 @@
     def setUp(self):
         self.con = sqlite.connect(":memory:", detect_types=sqlite.PARSE_DECLTYPES)
         self.cur = self.con.cursor()
-        self.cur.execute("create table test(i int, s str, f float, b bool, u unicode, foo foo, bin blob)")
+        self.cur.execute("create table test(i int, s str, f float, b bool, u unicode, foo foo, bin blob, n1 number, n2 number(5))")
 
         # override float, make them always return the same number
         sqlite.converters["FLOAT"] = lambda x: 47.2
@@ -107,11 +107,13 @@
         sqlite.converters["BOOL"] = lambda x: bool(int(x))
         sqlite.converters["FOO"] = DeclTypesTests.Foo
         sqlite.converters["WRONG"] = lambda x: "WRONG"
+        sqlite.converters["NUMBER"] = float
 
     def tearDown(self):
         del sqlite.converters["FLOAT"]
         del sqlite.converters["BOOL"]
         del sqlite.converters["FOO"]
+        del sqlite.converters["NUMBER"]
         self.cur.close()
         self.con.close()
 
@@ -203,6 +205,19 @@
         row = self.cur.fetchone()
         self.failUnlessEqual(row[0], val)
 
+    def CheckNumber1(self):
+        self.cur.execute("insert into test(n1) values (5)")
+        value = self.cur.execute("select n1 from test").fetchone()[0]
+        # if the converter is not used, it's an int instead of a float
+        self.failUnlessEqual(type(value), float)
+
+    def CheckNumber2(self):
+        """Checks wether converter names are cut off at '(' characters"""
+        self.cur.execute("insert into test(n2) values (5)")
+        value = self.cur.execute("select n2 from test").fetchone()[0]
+        # if the converter is not used, it's an int instead of a float
+        self.failUnlessEqual(type(value), float)
+
 class ColNamesTests(unittest.TestCase):
     def setUp(self):
         self.con = sqlite.connect(":memory:", detect_types=sqlite.PARSE_COLNAMES)

Modified: python/branches/tlee-ast-optimize/Modules/_sqlite/cursor.c
==============================================================================
--- python/branches/tlee-ast-optimize/Modules/_sqlite/cursor.c	(original)
+++ python/branches/tlee-ast-optimize/Modules/_sqlite/cursor.c	Sun May  4 19:02:25 2008
@@ -202,7 +202,11 @@
             decltype = sqlite3_column_decltype(self->statement->st, i);
             if (decltype) {
                 for (pos = decltype;;pos++) {
-                    if (*pos == ' ' || *pos == 0) {
+                    /* Converter names are split at '(' and blanks.
+                     * This allows 'INTEGER NOT NULL' to be treated as 'INTEGER' and
+                     * 'NUMBER(10)' to be treated as 'NUMBER', for example.
+                     * In other words, it will work as people expect it to work.*/
+                    if (*pos == ' ' || *pos == '(' || *pos == 0) {
                         py_decltype = PyString_FromStringAndSize(decltype, pos - decltype);
                         if (!py_decltype) {
                             return -1;

Modified: python/branches/tlee-ast-optimize/Modules/_sqlite/row.c
==============================================================================
--- python/branches/tlee-ast-optimize/Modules/_sqlite/row.c	(original)
+++ python/branches/tlee-ast-optimize/Modules/_sqlite/row.c	Sun May  4 19:02:25 2008
@@ -169,6 +169,30 @@
     return PyObject_GetIter(self->data);
 }
 
+static long pysqlite_row_hash(pysqlite_Row *self)
+{
+    return PyObject_Hash(self->description) ^ PyObject_Hash(self->data);
+}
+
+static PyObject* pysqlite_row_richcompare(pysqlite_Row *self, PyObject *_other, int opid)
+{
+    if (opid != Py_EQ && opid != Py_NE) {
+	Py_INCREF(Py_NotImplemented);
+	return Py_NotImplemented;
+    }
+    if (PyType_IsSubtype(Py_TYPE(_other), &pysqlite_RowType)) {
+	pysqlite_Row *other = (pysqlite_Row *)_other;
+	PyObject *res = PyObject_RichCompare(self->description, other->description, opid);
+	if (opid == Py_EQ && res == Py_True
+	    || opid == Py_NE && res == Py_False) {
+	    Py_DECREF(res);
+	    return PyObject_RichCompare(self->data, other->data, opid);
+	}
+    }
+    Py_INCREF(Py_NotImplemented);
+    return Py_NotImplemented;
+}
+
 PyMappingMethods pysqlite_row_as_mapping = {
     /* mp_length        */ (lenfunc)pysqlite_row_length,
     /* mp_subscript     */ (binaryfunc)pysqlite_row_subscript,
@@ -196,7 +220,7 @@
         0,                                              /* tp_as_number */
         0,                                              /* tp_as_sequence */
         0,                                              /* tp_as_mapping */
-        0,                                              /* tp_hash */
+        (hashfunc)pysqlite_row_hash,                    /* tp_hash */
         0,                                              /* tp_call */
         0,                                              /* tp_str */
         0,                                              /* tp_getattro */
@@ -206,7 +230,7 @@
         0,                                              /* tp_doc */
         (traverseproc)0,                                /* tp_traverse */
         0,                                              /* tp_clear */
-        0,                                              /* tp_richcompare */
+        (richcmpfunc)pysqlite_row_richcompare,          /* tp_richcompare */
         0,                                              /* tp_weaklistoffset */
         (getiterfunc)pysqlite_iter,                     /* tp_iter */
         0,                                              /* tp_iternext */

Modified: python/branches/tlee-ast-optimize/Modules/_sqlite/statement.c
==============================================================================
--- python/branches/tlee-ast-optimize/Modules/_sqlite/statement.c	(original)
+++ python/branches/tlee-ast-optimize/Modules/_sqlite/statement.c	Sun May  4 19:02:25 2008
@@ -100,9 +100,7 @@
 {
     int rc = SQLITE_OK;
     long longval;
-#ifdef HAVE_LONG_LONG
     PY_LONG_LONG longlongval;
-#endif
     const char* buffer;
     char* string;
     Py_ssize_t buflen;
@@ -157,13 +155,11 @@
             longval = PyInt_AsLong(parameter);
             rc = sqlite3_bind_int64(self->st, pos, (sqlite_int64)longval);
             break;
-#ifdef HAVE_LONG_LONG
         case TYPE_LONG:
             longlongval = PyLong_AsLongLong(parameter);
             /* in the overflow error case, longlongval is -1, and an exception is set */
             rc = sqlite3_bind_int64(self->st, pos, (sqlite_int64)longlongval);
             break;
-#endif
         case TYPE_FLOAT:
             rc = sqlite3_bind_double(self->st, pos, PyFloat_AsDouble(parameter));
             break;


More information about the Python-checkins mailing list