[Python-checkins] r78698 - in python/branches/py3k: Doc/includes/sqlite3/load_extension.py Doc/library/sqlite3.rst Lib/sqlite3/test/dbapi.py Lib/sqlite3/test/regression.py Lib/sqlite3/test/transactions.py Misc/NEWS Modules/_sqlite/cache.c Modules/_sqlite/cache.h Modules/_sqlite/connection.c Modules/_sqlite/connection.h Modules/_sqlite/cursor.c Modules/_sqlite/cursor.h Modules/_sqlite/module.c Modules/_sqlite/module.h Modules/_sqlite/prepare_protocol.c Modules/_sqlite/prepare_protocol.h Modules/_sqlite/row.c Modules/_sqlite/row.h Modules/_sqlite/sqlitecompat.h Modules/_sqlite/statement.c Modules/_sqlite/statement.h Modules/_sqlite/util.c Modules/_sqlite/util.h setup.py

gerhard.haering python-checkins at python.org
Fri Mar 5 16:20:03 CET 2010


Author: gerhard.haering
Date: Fri Mar  5 16:20:03 2010
New Revision: 78698

Log:
Merged new pysqlite version 2.6.0 from trunk.


Added:
   python/branches/py3k/Doc/includes/sqlite3/load_extension.py
Modified:
   python/branches/py3k/   (props changed)
   python/branches/py3k/Doc/library/sqlite3.rst
   python/branches/py3k/Lib/sqlite3/test/dbapi.py
   python/branches/py3k/Lib/sqlite3/test/regression.py
   python/branches/py3k/Lib/sqlite3/test/transactions.py
   python/branches/py3k/Misc/NEWS
   python/branches/py3k/Modules/_sqlite/cache.c
   python/branches/py3k/Modules/_sqlite/cache.h
   python/branches/py3k/Modules/_sqlite/connection.c
   python/branches/py3k/Modules/_sqlite/connection.h
   python/branches/py3k/Modules/_sqlite/cursor.c
   python/branches/py3k/Modules/_sqlite/cursor.h
   python/branches/py3k/Modules/_sqlite/module.c
   python/branches/py3k/Modules/_sqlite/module.h
   python/branches/py3k/Modules/_sqlite/prepare_protocol.c
   python/branches/py3k/Modules/_sqlite/prepare_protocol.h
   python/branches/py3k/Modules/_sqlite/row.c
   python/branches/py3k/Modules/_sqlite/row.h
   python/branches/py3k/Modules/_sqlite/sqlitecompat.h
   python/branches/py3k/Modules/_sqlite/statement.c
   python/branches/py3k/Modules/_sqlite/statement.h
   python/branches/py3k/Modules/_sqlite/util.c
   python/branches/py3k/Modules/_sqlite/util.h
   python/branches/py3k/setup.py

Added: python/branches/py3k/Doc/includes/sqlite3/load_extension.py
==============================================================================
--- (empty file)
+++ python/branches/py3k/Doc/includes/sqlite3/load_extension.py	Fri Mar  5 16:20:03 2010
@@ -0,0 +1,26 @@
+import sqlite3
+
+con = sqlite3.connect(":memory:")
+
+# enable extension loading
+con.enable_load_extension(True)
+
+# Load the fulltext search extension
+con.execute("select load_extension('./fts3.so')")
+
+# alternatively you can load the extension using an API call:
+# con.load_extension("./fts3.so")
+
+# disable extension laoding again
+con.enable_load_extension(False)
+
+# example from SQLite wiki
+con.execute("create virtual table recipe using fts3(name, ingredients)")
+con.executescript("""
+    insert into recipe (name, ingredients) values ('broccoli stew', 'broccoli peppers cheese tomatoes');
+    insert into recipe (name, ingredients) values ('pumpkin stew', 'pumpkin onions garlic celery');
+    insert into recipe (name, ingredients) values ('broccoli pie', 'broccoli cheese onions flour');
+    insert into recipe (name, ingredients) values ('pumpkin pie', 'pumpkin sugar flour butter');
+    """)
+for row in con.execute("select rowid, name, ingredients from recipe where name match 'pie'"):
+    print row

Modified: python/branches/py3k/Doc/library/sqlite3.rst
==============================================================================
--- python/branches/py3k/Doc/library/sqlite3.rst	(original)
+++ python/branches/py3k/Doc/library/sqlite3.rst	Fri Mar  5 16:20:03 2010
@@ -365,6 +365,25 @@
    method with :const:`None` for *handler*.
 
 
+.. method:: Connection.enable_load_extension(enabled)
+
+   .. versionadded:: 2.7
+
+   This routine allows/disallows the SQLite engine to load SQLite extensions
+   from shared libraries.  SQLite extensions can define new functions,
+   aggregates or whole new virtual table implementations. One well-known
+   extension is the fulltext-search extension distributed with SQLite.
+
+   .. literalinclude:: ../includes/sqlite3/load_extension.py
+
+.. method:: Connection.load_extension(path)
+
+   .. versionadded:: 2.7
+
+   This routine loads a SQLite extension from a shared library. You have to
+   enable extension loading with ``enable_load_extension`` before you can use
+   this routine.
+
 .. attribute:: Connection.row_factory
 
    You can change this attribute to a callable that accepts the cursor and the
@@ -434,7 +453,7 @@
 Cursor Objects
 --------------
 
-.. class:: Cursor
+A :class:`Cursor` instance has the following attributes and methods:
 
    A SQLite database cursor has the following attributes and methods:
 

Modified: python/branches/py3k/Lib/sqlite3/test/dbapi.py
==============================================================================
--- python/branches/py3k/Lib/sqlite3/test/dbapi.py	(original)
+++ python/branches/py3k/Lib/sqlite3/test/dbapi.py	Fri Mar  5 16:20:03 2010
@@ -1,7 +1,7 @@
 #-*- coding: ISO-8859-1 -*-
 # pysqlite2/test/dbapi.py: tests for DB-API compliance
 #
-# Copyright (C) 2004-2007 Gerhard Häring <gh at ghaering.de>
+# Copyright (C) 2004-2010 Gerhard Häring <gh at ghaering.de>
 #
 # This file is part of pysqlite.
 #
@@ -653,13 +653,13 @@
         res = cur.fetchone()[0]
         self.assertEqual(res, 5)
 
-    def CheckScriptErrorIncomplete(self):
+    def CheckScriptSyntaxError(self):
         con = sqlite.connect(":memory:")
         cur = con.cursor()
         raised = False
         try:
-            cur.executescript("create table test(sadfsadfdsa")
-        except sqlite.ProgrammingError:
+            cur.executescript("create table test(x); asdf; create table test2(x)")
+        except sqlite.OperationalError:
             raised = True
         self.assertEqual(raised, True, "should have raised an exception")
 
@@ -692,7 +692,7 @@
         result = con.execute("select foo from test").fetchone()[0]
         self.assertEqual(result, 5, "Basic test of Connection.executescript")
 
-class ClosedTests(unittest.TestCase):
+class ClosedConTests(unittest.TestCase):
     def setUp(self):
         pass
 
@@ -744,6 +744,102 @@
         except:
             self.fail("Should have raised a ProgrammingError")
 
+    def CheckClosedCreateFunction(self):
+        con = sqlite.connect(":memory:")
+        con.close()
+        def f(x): return 17
+        try:
+            con.create_function("foo", 1, f)
+            self.fail("Should have raised a ProgrammingError")
+        except sqlite.ProgrammingError:
+            pass
+        except:
+            self.fail("Should have raised a ProgrammingError")
+
+    def CheckClosedCreateAggregate(self):
+        con = sqlite.connect(":memory:")
+        con.close()
+        class Agg:
+            def __init__(self):
+                pass
+            def step(self, x):
+                pass
+            def finalize(self):
+                return 17
+        try:
+            con.create_aggregate("foo", 1, Agg)
+            self.fail("Should have raised a ProgrammingError")
+        except sqlite.ProgrammingError:
+            pass
+        except:
+            self.fail("Should have raised a ProgrammingError")
+
+    def CheckClosedSetAuthorizer(self):
+        con = sqlite.connect(":memory:")
+        con.close()
+        def authorizer(*args):
+            return sqlite.DENY
+        try:
+            con.set_authorizer(authorizer)
+            self.fail("Should have raised a ProgrammingError")
+        except sqlite.ProgrammingError:
+            pass
+        except:
+            self.fail("Should have raised a ProgrammingError")
+
+    def CheckClosedSetProgressCallback(self):
+        con = sqlite.connect(":memory:")
+        con.close()
+        def progress(): pass
+        try:
+            con.set_progress_handler(progress, 100)
+            self.fail("Should have raised a ProgrammingError")
+        except sqlite.ProgrammingError:
+            pass
+        except:
+            self.fail("Should have raised a ProgrammingError")
+
+    def CheckClosedCall(self):
+        con = sqlite.connect(":memory:")
+        con.close()
+        try:
+            con()
+            self.fail("Should have raised a ProgrammingError")
+        except sqlite.ProgrammingError:
+            pass
+        except:
+            self.fail("Should have raised a ProgrammingError")
+
+class ClosedCurTests(unittest.TestCase):
+    def setUp(self):
+        pass
+
+    def tearDown(self):
+        pass
+
+    def CheckClosed(self):
+        con = sqlite.connect(":memory:")
+        cur = con.cursor()
+        cur.close()
+
+        for method_name in ("execute", "executemany", "executescript", "fetchall", "fetchmany", "fetchone"):
+            if method_name in ("execute", "executescript"):
+                params = ("select 4 union select 5",)
+            elif method_name == "executemany":
+                params = ("insert into foo(bar) values (?)", [(3,), (4,)])
+            else:
+                params = []
+
+            try:
+                method = getattr(cur, method_name)
+
+                method(*params)
+                self.fail("Should have raised a ProgrammingError: method " + method_name)
+            except sqlite.ProgrammingError:
+                pass
+            except:
+                self.fail("Should have raised a ProgrammingError: " + method_name)
+
 def suite():
     module_suite = unittest.makeSuite(ModuleTests, "Check")
     connection_suite = unittest.makeSuite(ConnectionTests, "Check")
@@ -751,8 +847,9 @@
     thread_suite = unittest.makeSuite(ThreadTests, "Check")
     constructor_suite = unittest.makeSuite(ConstructorTests, "Check")
     ext_suite = unittest.makeSuite(ExtensionTests, "Check")
-    closed_suite = unittest.makeSuite(ClosedTests, "Check")
-    return unittest.TestSuite((module_suite, connection_suite, cursor_suite, thread_suite, constructor_suite, ext_suite, closed_suite))
+    closed_con_suite = unittest.makeSuite(ClosedConTests, "Check")
+    closed_cur_suite = unittest.makeSuite(ClosedCurTests, "Check")
+    return unittest.TestSuite((module_suite, connection_suite, cursor_suite, thread_suite, constructor_suite, ext_suite, closed_con_suite, closed_cur_suite))
 
 def test():
     runner = unittest.TextTestRunner()

Modified: python/branches/py3k/Lib/sqlite3/test/regression.py
==============================================================================
--- python/branches/py3k/Lib/sqlite3/test/regression.py	(original)
+++ python/branches/py3k/Lib/sqlite3/test/regression.py	Fri Mar  5 16:20:03 2010
@@ -1,7 +1,7 @@
 #-*- coding: ISO-8859-1 -*-
 # pysqlite2/test/regression.py: pysqlite regression tests
 #
-# Copyright (C) 2006 Gerhard Häring <gh at ghaering.de>
+# Copyright (C) 2006-2010 Gerhard Häring <gh at ghaering.de>
 #
 # This file is part of pysqlite.
 #
@@ -70,16 +70,6 @@
         cur.execute('select 1 as "foo baz"')
         self.assertEqual(cur.description[0][0], "foo baz")
 
-    def CheckStatementAvailable(self):
-        # pysqlite up to 2.3.2 crashed on this, because the active statement handle was not checked
-        # before trying to fetch data from it. close() destroys the active statement ...
-        con = sqlite.connect(":memory:", detect_types=sqlite.PARSE_DECLTYPES)
-        cur = con.cursor()
-        cur.execute("select 4 union select 5")
-        cur.close()
-        cur.fetchone()
-        cur.fetchone()
-
     def CheckStatementFinalizationOnCloseDb(self):
         # pysqlite versions <= 2.3.3 only finalized statements in the statement
         # cache when closing the database. statements that were still
@@ -169,6 +159,25 @@
         con = sqlite.connect(":memory:")
         setattr(con, "isolation_level", "\xe9")
 
+    def CheckCursorConstructorCallCheck(self):
+        """
+        Verifies that cursor methods check wether base class __init__ was called.
+        """
+        class Cursor(sqlite.Cursor):
+            def __init__(self, con):
+                pass
+
+        con = sqlite.connect(":memory:")
+        cur = Cursor(con)
+        try:
+            cur.execute("select 4+5").fetchall()
+            self.fail("should have raised ProgrammingError")
+        except sqlite.ProgrammingError:
+            pass
+        except:
+            self.fail("should have raised ProgrammingError")
+
+
     def CheckStrSubclass(self):
         """
         The Python 3.0 port of the module didn't cope with values of subclasses of str.
@@ -176,6 +185,90 @@
         class MyStr(str): pass
         self.con.execute("select ?", (MyStr("abc"),))
 
+    def CheckConnectionConstructorCallCheck(self):
+        """
+        Verifies that connection methods check wether base class __init__ was called.
+        """
+        class Connection(sqlite.Connection):
+            def __init__(self, name):
+                pass
+
+        con = Connection(":memory:")
+        try:
+            cur = con.cursor()
+            self.fail("should have raised ProgrammingError")
+        except sqlite.ProgrammingError:
+            pass
+        except:
+            self.fail("should have raised ProgrammingError")
+
+    def CheckCursorRegistration(self):
+        """
+        Verifies that subclassed cursor classes are correctly registered with
+        the connection object, too.  (fetch-across-rollback problem)
+        """
+        class Connection(sqlite.Connection):
+            def cursor(self):
+                return Cursor(self)
+
+        class Cursor(sqlite.Cursor):
+            def __init__(self, con):
+                sqlite.Cursor.__init__(self, con)
+
+        con = Connection(":memory:")
+        cur = con.cursor()
+        cur.execute("create table foo(x)")
+        cur.executemany("insert into foo(x) values (?)", [(3,), (4,), (5,)])
+        cur.execute("select x from foo")
+        con.rollback()
+        try:
+            cur.fetchall()
+            self.fail("should have raised InterfaceError")
+        except sqlite.InterfaceError:
+            pass
+        except:
+            self.fail("should have raised InterfaceError")
+
+    def CheckAutoCommit(self):
+        """
+        Verifies that creating a connection in autocommit mode works.
+        2.5.3 introduced a regression so that these could no longer
+        be created.
+        """
+        con = sqlite.connect(":memory:", isolation_level=None)
+
+    def CheckPragmaAutocommit(self):
+        """
+        Verifies that running a PRAGMA statement that does an autocommit does
+        work. This did not work in 2.5.3/2.5.4.
+        """
+        con = sqlite.connect(":memory:")
+        cur = con.cursor()
+        cur.execute("create table foo(bar)")
+        cur.execute("insert into foo(bar) values (5)")
+
+        cur.execute("pragma page_size")
+        row = cur.fetchone()
+
+    def CheckSetDict(self):
+        """
+        See http://bugs.python.org/issue7478
+
+        It was possible to successfully register callbacks that could not be
+        hashed. Return codes of PyDict_SetItem were not checked properly.
+        """
+        class NotHashable:
+            def __call__(self, *args, **kw):
+                pass
+            def __hash__(self):
+                raise TypeError()
+        var = NotHashable()
+        con = sqlite.connect(":memory:")
+        self.assertRaises(TypeError, con.create_function, var)
+        self.assertRaises(TypeError, con.create_aggregate, var)
+        self.assertRaises(TypeError, con.set_authorizer, var)
+        self.assertRaises(TypeError, con.set_progress_handler, var)
+
 def suite():
     regression_suite = unittest.makeSuite(RegressionTests, "Check")
     return unittest.TestSuite((regression_suite,))

Modified: python/branches/py3k/Lib/sqlite3/test/transactions.py
==============================================================================
--- python/branches/py3k/Lib/sqlite3/test/transactions.py	(original)
+++ python/branches/py3k/Lib/sqlite3/test/transactions.py	Fri Mar  5 16:20:03 2010
@@ -147,6 +147,26 @@
         # NO self.con2.rollback() HERE!!!
         self.con1.commit()
 
+    def CheckRollbackCursorConsistency(self):
+        """
+        Checks if cursors on the connection are set into a "reset" state
+        when a rollback is done on the connection.
+        """
+        con = sqlite.connect(":memory:")
+        cur = con.cursor()
+        cur.execute("create table test(x)")
+        cur.execute("insert into test(x) values (5)")
+        cur.execute("select 1 union select 2 union select 3")
+
+        con.rollback()
+        try:
+            cur.fetchall()
+            self.fail("InterfaceError should have been raised")
+        except sqlite.InterfaceError as e:
+            pass
+        except:
+            self.fail("InterfaceError should have been raised")
+
 class SpecialCommandTests(unittest.TestCase):
     def setUp(self):
         self.con = sqlite.connect(":memory:")

Modified: python/branches/py3k/Misc/NEWS
==============================================================================
--- python/branches/py3k/Misc/NEWS	(original)
+++ python/branches/py3k/Misc/NEWS	Fri Mar  5 16:20:03 2010
@@ -268,6 +268,9 @@
 Library
 -------
 
+- The sqlite3 module was updated to pysqlite 2.6.0. This fixes several obscure
+  bugs and allows loading SQLite extensions from shared libraries.
+
 - Issue #1054943: Fix unicodedata.normalize('NFC', text) for the Public Review
   Issue #29
 

Modified: python/branches/py3k/Modules/_sqlite/cache.c
==============================================================================
--- python/branches/py3k/Modules/_sqlite/cache.c	(original)
+++ python/branches/py3k/Modules/_sqlite/cache.c	Fri Mar  5 16:20:03 2010
@@ -1,6 +1,6 @@
 /* cache .c - a LRU cache
  *
- * Copyright (C) 2004-2007 Gerhard Häring <gh at ghaering.de>
+ * Copyright (C) 2004-2010 Gerhard Häring <gh at ghaering.de>
  *
  * This file is part of pysqlite.
  *
@@ -21,6 +21,7 @@
  * 3. This notice may not be removed or altered from any source distribution.
  */
 
+#include "sqlitecompat.h"
 #include "cache.h"
 #include <limits.h>
 

Modified: python/branches/py3k/Modules/_sqlite/cache.h
==============================================================================
--- python/branches/py3k/Modules/_sqlite/cache.h	(original)
+++ python/branches/py3k/Modules/_sqlite/cache.h	Fri Mar  5 16:20:03 2010
@@ -1,6 +1,6 @@
 /* cache.h - definitions for the LRU cache
  *
- * Copyright (C) 2004-2007 Gerhard Häring <gh at ghaering.de>
+ * Copyright (C) 2004-2010 Gerhard Häring <gh at ghaering.de>
  *
  * This file is part of pysqlite.
  *

Modified: python/branches/py3k/Modules/_sqlite/connection.c
==============================================================================
--- python/branches/py3k/Modules/_sqlite/connection.c	(original)
+++ python/branches/py3k/Modules/_sqlite/connection.c	Fri Mar  5 16:20:03 2010
@@ -1,6 +1,6 @@
 /* connection.c - the connection type
  *
- * Copyright (C) 2004-2007 Gerhard Häring <gh at ghaering.de>
+ * Copyright (C) 2004-2010 Gerhard Häring <gh at ghaering.de>
  *
  * This file is part of pysqlite.
  * 
@@ -35,7 +35,14 @@
 #define ACTION_FINALIZE 1
 #define ACTION_RESET 2
 
+#if SQLITE_VERSION_NUMBER >= 3003008
+#ifndef SQLITE_OMIT_LOAD_EXTENSION
+#define HAVE_LOAD_EXTENSION
+#endif
+#endif
+
 static int pysqlite_connection_set_isolation_level(pysqlite_Connection* self, PyObject* isolation_level);
+static void _pysqlite_drop_unused_cursor_references(pysqlite_Connection* self);
 
 
 static void _sqlite3_result_error(sqlite3_context* ctx, const char* errmsg, int len)
@@ -69,10 +76,13 @@
         return -1;
     }
 
+    self->initialized = 1;
+
     self->begin_statement = NULL;
 
     self->statement_cache = NULL;
     self->statements = NULL;
+    self->cursors = NULL;
 
     Py_INCREF(Py_None);
     self->row_factory = Py_None;
@@ -106,11 +116,15 @@
         return -1;
     }
 
+    self->created_statements = 0;
+    self->created_cursors = 0;
+
+    /* Create lists of weak references to statements/cursors */
     self->statements = PyList_New(0);
-    if (!self->statements) {
+    self->cursors = PyList_New(0);
+    if (!self->statements || !self->cursors) {
         return -1;
     }
-    self->created_statements = 0;
 
     /* By default, the Cache class INCREFs the factory in its initializer, and
      * decrefs it in its deallocator method. Since this would create a circular
@@ -174,11 +188,12 @@
 }
 
 /* action in (ACTION_RESET, ACTION_FINALIZE) */
-void pysqlite_do_all_statements(pysqlite_Connection* self, int action)
+void pysqlite_do_all_statements(pysqlite_Connection* self, int action, int reset_cursors)
 {
     int i;
     PyObject* weakref;
     PyObject* statement;
+    pysqlite_Cursor* cursor;
 
     for (i = 0; i < PyList_Size(self->statements); i++) {
         weakref = PyList_GetItem(self->statements, i);
@@ -191,6 +206,16 @@
             }
         }
     }
+
+    if (reset_cursors) {
+        for (i = 0; i < PyList_Size(self->cursors); i++) {
+            weakref = PyList_GetItem(self->cursors, i);
+            cursor = (pysqlite_Cursor*)PyWeakref_GetObject(weakref);
+            if ((PyObject*)cursor != Py_None) {
+                cursor->reset = 1;
+            }
+        }
+    }
 }
 
 void pysqlite_connection_dealloc(pysqlite_Connection* self)
@@ -213,17 +238,43 @@
     Py_XDECREF(self->text_factory);
     Py_XDECREF(self->collations);
     Py_XDECREF(self->statements);
+    Py_XDECREF(self->cursors);
 
     Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
+/*
+ * Registers a cursor with the connection.
+ *
+ * 0 => error; 1 => ok
+ */
+int pysqlite_connection_register_cursor(pysqlite_Connection* connection, PyObject* cursor)
+{
+    PyObject* weakref;
+
+    weakref = PyWeakref_NewRef((PyObject*)cursor, NULL);
+    if (!weakref) {
+        goto error;
+    }
+
+    if (PyList_Append(connection->cursors, weakref) != 0) {
+        Py_CLEAR(weakref);
+        goto error;
+    }
+
+    Py_DECREF(weakref);
+
+    return 1;
+error:
+    return 0;
+}
+
 PyObject* pysqlite_connection_cursor(pysqlite_Connection* self, PyObject* args, PyObject* kwargs)
 {
     static char *kwlist[] = {"factory", NULL, NULL};
     PyObject* factory = NULL;
     PyObject* cursor;
 
-
     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O", kwlist,
                                      &factory)) {
         return NULL;
@@ -239,6 +290,8 @@
 
     cursor = PyObject_CallFunction(factory, "O", self);
 
+    _pysqlite_drop_unused_cursor_references(self);
+
     if (cursor && self->row_factory != Py_None) {
         Py_XDECREF(((pysqlite_Cursor*)cursor)->row_factory);
         Py_INCREF(self->row_factory);
@@ -256,7 +309,7 @@
         return NULL;
     }
 
-    pysqlite_do_all_statements(self, ACTION_FINALIZE);
+    pysqlite_do_all_statements(self, ACTION_FINALIZE, 1);
 
     if (self->db) {
         Py_BEGIN_ALLOW_THREADS
@@ -282,6 +335,11 @@
  */
 int pysqlite_check_connection(pysqlite_Connection* con)
 {
+    if (!con->initialized) {
+        PyErr_SetString(pysqlite_ProgrammingError, "Base Connection.__init__ not called.");
+        return 0;
+    }
+
     if (!con->db) {
         PyErr_SetString(pysqlite_ProgrammingError, "Cannot operate on a closed database.");
         return 0;
@@ -340,6 +398,8 @@
     }
 
     if (self->inTransaction) {
+        pysqlite_do_all_statements(self, ACTION_RESET, 0);
+
         Py_BEGIN_ALLOW_THREADS
         rc = sqlite3_prepare(self->db, "COMMIT", -1, &statement, &tail);
         Py_END_ALLOW_THREADS
@@ -384,7 +444,7 @@
     }
 
     if (self->inTransaction) {
-        pysqlite_do_all_statements(self, ACTION_RESET);
+        pysqlite_do_all_statements(self, ACTION_RESET, 1);
 
         Py_BEGIN_ALLOW_THREADS
         rc = sqlite3_prepare(self->db, "ROLLBACK", -1, &statement, &tail);
@@ -649,7 +709,7 @@
 #endif
 }
 
-void _pysqlite_drop_unused_statement_references(pysqlite_Connection* self)
+static void _pysqlite_drop_unused_statement_references(pysqlite_Connection* self)
 {
     PyObject* new_list;
     PyObject* weakref;
@@ -681,6 +741,38 @@
     self->statements = new_list;
 }
 
+static void _pysqlite_drop_unused_cursor_references(pysqlite_Connection* self)
+{
+    PyObject* new_list;
+    PyObject* weakref;
+    int i;
+
+    /* we only need to do this once in a while */
+    if (self->created_cursors++ < 200) {
+        return;
+    }
+
+    self->created_cursors = 0;
+
+    new_list = PyList_New(0);
+    if (!new_list) {
+        return;
+    }
+
+    for (i = 0; i < PyList_Size(self->cursors); i++) {
+        weakref = PyList_GetItem(self->cursors, i);
+        if (PyWeakref_GetObject(weakref) != Py_None) {
+            if (PyList_Append(new_list, weakref) != 0) {
+                Py_DECREF(new_list);
+                return;
+            }
+        }
+    }
+
+    Py_DECREF(self->cursors);
+    self->cursors = new_list;
+}
+
 PyObject* pysqlite_connection_create_function(pysqlite_Connection* self, PyObject* args, PyObject* kwargs)
 {
     static char *kwlist[] = {"name", "narg", "func", NULL, NULL};
@@ -690,6 +782,10 @@
     int narg;
     int rc;
 
+    if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) {
+        return NULL;
+    }
+
     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "siO", kwlist,
                                      &name, &narg, &func))
     {
@@ -703,7 +799,8 @@
         PyErr_SetString(pysqlite_OperationalError, "Error creating function");
         return NULL;
     } else {
-        PyDict_SetItem(self->function_pinboard, func, Py_None);
+        if (PyDict_SetItem(self->function_pinboard, func, Py_None) == -1)
+            return NULL;
 
         Py_INCREF(Py_None);
         return Py_None;
@@ -719,6 +816,10 @@
     static char *kwlist[] = { "name", "n_arg", "aggregate_class", NULL };
     int rc;
 
+    if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) {
+        return NULL;
+    }
+
     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "siO:create_aggregate",
                                       kwlist, &name, &n_arg, &aggregate_class)) {
         return NULL;
@@ -730,7 +831,8 @@
         PyErr_SetString(pysqlite_OperationalError, "Error creating aggregate");
         return NULL;
     } else {
-        PyDict_SetItem(self->function_pinboard, aggregate_class, Py_None);
+        if (PyDict_SetItem(self->function_pinboard, aggregate_class, Py_None) == -1)
+            return NULL;
 
         Py_INCREF(Py_None);
         return Py_None;
@@ -802,13 +904,17 @@
     return rc;
 }
 
-PyObject* pysqlite_connection_set_authorizer(pysqlite_Connection* self, PyObject* args, PyObject* kwargs)
+static PyObject* pysqlite_connection_set_authorizer(pysqlite_Connection* self, PyObject* args, PyObject* kwargs)
 {
     PyObject* authorizer_cb;
 
     static char *kwlist[] = { "authorizer_callback", NULL };
     int rc;
 
+    if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) {
+        return NULL;
+    }
+
     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O:set_authorizer",
                                       kwlist, &authorizer_cb)) {
         return NULL;
@@ -820,20 +926,25 @@
         PyErr_SetString(pysqlite_OperationalError, "Error setting authorizer callback");
         return NULL;
     } else {
-        PyDict_SetItem(self->function_pinboard, authorizer_cb, Py_None);
+        if (PyDict_SetItem(self->function_pinboard, authorizer_cb, Py_None) == -1)
+            return NULL;
 
         Py_INCREF(Py_None);
         return Py_None;
     }
 }
 
-PyObject* pysqlite_connection_set_progress_handler(pysqlite_Connection* self, PyObject* args, PyObject* kwargs)
+static PyObject* pysqlite_connection_set_progress_handler(pysqlite_Connection* self, PyObject* args, PyObject* kwargs)
 {
     PyObject* progress_handler;
     int n;
 
     static char *kwlist[] = { "progress_handler", "n", NULL };
 
+    if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) {
+        return NULL;
+    }
+
     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi:set_progress_handler",
                                       kwlist, &progress_handler, &n)) {
         return NULL;
@@ -844,13 +955,64 @@
         sqlite3_progress_handler(self->db, 0, 0, (void*)0);
     } else {
         sqlite3_progress_handler(self->db, n, _progress_handler, progress_handler);
-        PyDict_SetItem(self->function_pinboard, progress_handler, Py_None);
+        if (PyDict_SetItem(self->function_pinboard, progress_handler, Py_None) == -1)
+            return NULL;
     }
 
     Py_INCREF(Py_None);
     return Py_None;
 }
 
+#ifdef HAVE_LOAD_EXTENSION
+static PyObject* pysqlite_enable_load_extension(pysqlite_Connection* self, PyObject* args)
+{
+    int rc;
+    int onoff;
+
+    if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) {
+        return NULL;
+    }
+
+    if (!PyArg_ParseTuple(args, "i", &onoff)) {
+        return NULL;
+    }
+
+    rc = sqlite3_enable_load_extension(self->db, onoff);
+
+    if (rc != SQLITE_OK) {
+        PyErr_SetString(pysqlite_OperationalError, "Error enabling load extension");
+        return NULL;
+    } else {
+        Py_INCREF(Py_None);
+        return Py_None;
+    }
+}
+
+static PyObject* pysqlite_load_extension(pysqlite_Connection* self, PyObject* args)
+{
+    int rc;
+    char* extension_name;
+    char* errmsg;
+
+    if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) {
+        return NULL;
+    }
+
+    if (!PyArg_ParseTuple(args, "s", &extension_name)) {
+        return NULL;
+    }
+
+    rc = sqlite3_load_extension(self->db, extension_name, 0, &errmsg);
+    if (rc != 0) {
+        PyErr_SetString(pysqlite_OperationalError, errmsg);
+        return NULL;
+    } else {
+        Py_INCREF(Py_None);
+        return Py_None;
+    }
+}
+#endif
+
 int pysqlite_check_thread(pysqlite_Connection* self)
 {
 #ifdef WITH_THREAD
@@ -948,6 +1110,10 @@
     PyObject* weakref;
     int rc;
 
+    if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) {
+        return NULL;
+    }
+
     if (!PyArg_ParseTuple(args, "O", &sql)) {
         return NULL;
     }
@@ -1237,9 +1403,11 @@
     }
 
     if (callable != Py_None) {
-        PyDict_SetItem(self->collations, uppercase_name, callable);
+        if (PyDict_SetItem(self->collations, uppercase_name, callable) == -1)
+            goto finally;
     } else {
-        PyDict_DelItem(self->collations, uppercase_name);
+        if (PyDict_DelItem(self->collations, uppercase_name) == -1)
+            goto finally;
     }
 
     rc = sqlite3_create_collation(self->db,
@@ -1327,6 +1495,12 @@
         PyDoc_STR("Creates a new aggregate. Non-standard.")},
     {"set_authorizer", (PyCFunction)pysqlite_connection_set_authorizer, METH_VARARGS|METH_KEYWORDS,
         PyDoc_STR("Sets authorizer callback. Non-standard.")},
+    #ifdef HAVE_LOAD_EXTENSION
+    {"enable_load_extension", (PyCFunction)pysqlite_enable_load_extension, METH_VARARGS,
+        PyDoc_STR("Enable dynamic loading of SQLite extension modules. Non-standard.")},
+    {"load_extension", (PyCFunction)pysqlite_load_extension, METH_VARARGS,
+        PyDoc_STR("Load SQLite extension module. Non-standard.")},
+    #endif
     {"set_progress_handler", (PyCFunction)pysqlite_connection_set_progress_handler, METH_VARARGS|METH_KEYWORDS,
         PyDoc_STR("Sets progress handler callback. Non-standard.")},
     {"execute", (PyCFunction)pysqlite_connection_execute, METH_VARARGS,

Modified: python/branches/py3k/Modules/_sqlite/connection.h
==============================================================================
--- python/branches/py3k/Modules/_sqlite/connection.h	(original)
+++ python/branches/py3k/Modules/_sqlite/connection.h	Fri Mar  5 16:20:03 2010
@@ -1,6 +1,6 @@
 /* connection.h - definitions for the connection type
  *
- * Copyright (C) 2004-2007 Gerhard Häring <gh at ghaering.de>
+ * Copyright (C) 2004-2010 Gerhard Häring <gh at ghaering.de>
  *
  * This file is part of pysqlite.
  *
@@ -63,17 +63,21 @@
      * used from the same thread it was created in */
     int check_same_thread;
 
+    int initialized;
+
     /* thread identification of the thread the connection was created in */
     long thread_ident;
 
     pysqlite_Cache* statement_cache;
 
-    /* A list of weak references to statements used within this connection */
+    /* Lists of weak references to statements and cursors used within this connection */
     PyObject* statements;
+    PyObject* cursors;
 
-    /* a counter for how many statements were created in the connection. May be
+    /* Counters for how many statements/cursors were created in the connection. May be
      * reset to 0 at certain intervals */
     int created_statements;
+    int created_cursors;
 
     PyObject* row_factory;
 
@@ -120,6 +124,7 @@
 PyObject* pysqlite_connection_new(PyTypeObject* type, PyObject* args, PyObject* kw);
 int pysqlite_connection_init(pysqlite_Connection* self, PyObject* args, PyObject* kwargs);
 
+int pysqlite_connection_register_cursor(pysqlite_Connection* connection, PyObject* cursor);
 int pysqlite_check_thread(pysqlite_Connection* self);
 int pysqlite_check_connection(pysqlite_Connection* con);
 

Modified: python/branches/py3k/Modules/_sqlite/cursor.c
==============================================================================
--- python/branches/py3k/Modules/_sqlite/cursor.c	(original)
+++ python/branches/py3k/Modules/_sqlite/cursor.c	Fri Mar  5 16:20:03 2010
@@ -1,6 +1,6 @@
 /* cursor.c - the cursor type
  *
- * Copyright (C) 2004-2007 Gerhard Häring <gh at ghaering.de>
+ * Copyright (C) 2004-2010 Gerhard Häring <gh at ghaering.de>
  *
  * This file is part of pysqlite.
  *
@@ -36,6 +36,8 @@
 
 PyObject* pysqlite_cursor_iternext(pysqlite_Cursor* self);
 
+static char* errmsg_fetch_across_rollback = "Cursor needed to be reset because of commit/rollback and can no longer be fetched from.";
+
 static pysqlite_StatementKind detect_statement_type(const char* statement)
 {
     char buf[20];
@@ -74,7 +76,7 @@
     }
 }
 
-int pysqlite_cursor_init(pysqlite_Cursor* self, PyObject* args, PyObject* kwargs)
+static int pysqlite_cursor_init(pysqlite_Cursor* self, PyObject* args, PyObject* kwargs)
 {
     pysqlite_Connection* connection;
 
@@ -87,6 +89,7 @@
     self->connection = connection;
     self->statement = NULL;
     self->next_row = NULL;
+    self->in_weakreflist = NULL;
 
     self->row_cast_map = PyList_New(0);
     if (!self->row_cast_map) {
@@ -100,6 +103,8 @@
     self->lastrowid= Py_None;
 
     self->arraysize = 1;
+    self->closed = 0;
+    self->reset = 0;
 
     self->rowcount = -1L;
 
@@ -110,10 +115,16 @@
         return -1;
     }
 
+    if (!pysqlite_connection_register_cursor(connection, (PyObject*)self)) {
+        return -1;
+    }
+
+    self->initialized = 1;
+
     return 0;
 }
 
-void pysqlite_cursor_dealloc(pysqlite_Cursor* self)
+static void pysqlite_cursor_dealloc(pysqlite_Cursor* self)
 {
     int rc;
 
@@ -130,6 +141,10 @@
     Py_XDECREF(self->row_factory);
     Py_XDECREF(self->next_row);
 
+    if (self->in_weakreflist != NULL) {
+        PyObject_ClearWeakRefs((PyObject*)self);
+    }
+
     Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
@@ -281,6 +296,11 @@
     PyObject* buf_bytes;
     PyObject* error_obj;
 
+    if (self->reset) {
+        PyErr_SetString(pysqlite_InterfaceError, errmsg_fetch_across_rollback);
+        return NULL;
+    }
+
     Py_BEGIN_ALLOW_THREADS
     numcols = sqlite3_data_count(self->statement->st);
     Py_END_ALLOW_THREADS
@@ -397,6 +417,26 @@
     return row;
 }
 
+/*
+ * Checks if a cursor object is usable.
+ *
+ * 0 => error; 1 => ok
+ */
+static int check_cursor(pysqlite_Cursor* cur)
+{
+    if (!cur->initialized) {
+        PyErr_SetString(pysqlite_ProgrammingError, "Base Cursor.__init__ not called.");
+        return 0;
+    }
+
+    if (cur->closed) {
+        PyErr_SetString(pysqlite_ProgrammingError, "Cannot operate on a closed cursor.");
+        return 0;
+    } else {
+        return pysqlite_check_thread(cur->connection) && pysqlite_check_connection(cur->connection);
+    }
+}
+
 PyObject* _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* args)
 {
     PyObject* operation;
@@ -416,13 +456,15 @@
     PyObject* second_argument = NULL;
     int allow_8bit_chars;
 
-    if (!pysqlite_check_thread(self->connection) || !pysqlite_check_connection(self->connection)) {
+    if (!check_cursor(self)) {
         return NULL;
     }
 
+    self->reset = 0;
+
     /* Make shooting yourself in the foot with not utf-8 decodable 8-bit-strings harder */
     allow_8bit_chars = ((self->connection->text_factory != (PyObject*)&PyUnicode_Type) &&
-        (self->connection->text_factory != (PyObject*)&PyUnicode_Type && pysqlite_OptimizedUnicode));
+        (self->connection->text_factory != pysqlite_OptimizedUnicode));
 
     Py_XDECREF(self->next_row);
     self->next_row = NULL;
@@ -573,42 +615,6 @@
         }
     }
 
-    func_args = PyTuple_New(1);
-    if (!func_args) {
-        goto error;
-    }
-    Py_INCREF(operation);
-    if (PyTuple_SetItem(func_args, 0, operation) != 0) {
-        goto error;
-    }
-
-    if (self->statement) {
-        (void)pysqlite_statement_reset(self->statement);
-        Py_DECREF(self->statement);
-    }
-
-    self->statement = (pysqlite_Statement*)pysqlite_cache_get(self->connection->statement_cache, func_args);
-    Py_DECREF(func_args);
-
-    if (!self->statement) {
-        goto error;
-    }
-
-    if (self->statement->in_use) {
-        Py_DECREF(self->statement);
-        self->statement = PyObject_New(pysqlite_Statement, &pysqlite_StatementType);
-        if (!self->statement) {
-            goto error;
-        }
-        rc = pysqlite_statement_create(self->statement, self->connection, operation);
-        if (rc != SQLITE_OK) {
-            Py_CLEAR(self->statement);
-            goto error;
-        }
-    }
-
-    pysqlite_statement_reset(self->statement);
-    pysqlite_statement_mark_dirty(self->statement);
 
     while (1) {
         parameters = PyIter_Next(parameters_iter);
@@ -623,11 +629,6 @@
             goto error;
         }
 
-        if (pysqlite_build_row_cast_map(self) != 0) {
-            PyErr_SetString(pysqlite_OperationalError, "Error while building row_cast_map");
-            goto error;
-        }
-
         /* Keep trying the SQL statement until the schema stops changing. */
         while (1) {
             /* Actually execute the SQL statement. */
@@ -671,10 +672,6 @@
         }
 
         if (rc == SQLITE_ROW || (rc == SQLITE_DONE && statement_type == STATEMENT_SELECT)) {
-            Py_BEGIN_ALLOW_THREADS
-            numcols = sqlite3_column_count(self->statement->st);
-            Py_END_ALLOW_THREADS
-
             if (self->description == Py_None) {
                 Py_BEGIN_ALLOW_THREADS
                 numcols = sqlite3_column_count(self->statement->st);
@@ -782,16 +779,17 @@
     sqlite3_stmt* statement;
     int rc;
     PyObject* result;
-    int statement_completed = 0;
 
     if (!PyArg_ParseTuple(args, "O", &script_obj)) {
         return NULL;
     }
 
-    if (!pysqlite_check_thread(self->connection) || !pysqlite_check_connection(self->connection)) {
+    if (!check_cursor(self)) {
         return NULL;
     }
 
+    self->reset = 0;
+
     if (PyUnicode_Check(script_obj)) {
         script_cstr = _PyUnicode_AsString(script_obj);
         if (!script_cstr) {
@@ -810,11 +808,6 @@
     Py_DECREF(result);
 
     while (1) {
-        if (!sqlite3_complete(script_cstr)) {
-            break;
-        }
-        statement_completed = 1;
-
         Py_BEGIN_ALLOW_THREADS
         rc = sqlite3_prepare(self->connection->db,
                              script_cstr,
@@ -845,15 +838,15 @@
             _pysqlite_seterror(self->connection->db, NULL);
             goto error;
         }
+
+        if (*script_cstr == (char)0) {
+            break;
+        }
     }
 
 error:
     Py_XDECREF(script_str);
 
-    if (!statement_completed) {
-        PyErr_SetString(pysqlite_ProgrammingError, "you did not provide a complete SQL statement");
-    }
-
     if (PyErr_Occurred()) {
         return NULL;
     } else {
@@ -874,7 +867,12 @@
     PyObject* next_row;
     int rc;
 
-    if (!pysqlite_check_thread(self->connection) || !pysqlite_check_connection(self->connection)) {
+    if (!check_cursor(self)) {
+        return NULL;
+    }
+
+    if (self->reset) {
+        PyErr_SetString(pysqlite_InterfaceError, errmsg_fetch_across_rollback);
         return NULL;
     }
 
@@ -1017,6 +1015,8 @@
         Py_CLEAR(self->statement);
     }
 
+    self->closed = 1;
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -1077,12 +1077,12 @@
         0,                                              /* tp_getattro */
         0,                                              /* tp_setattro */
         0,                                              /* tp_as_buffer */
-        Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,	/* tp_flags */
+        Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */
         cursor_doc,                                     /* tp_doc */
         0,                                              /* tp_traverse */
         0,                                              /* tp_clear */
         0,                                              /* tp_richcompare */
-        0,                                              /* tp_weaklistoffset */
+        offsetof(pysqlite_Cursor, in_weakreflist),      /* tp_weaklistoffset */
         (getiterfunc)pysqlite_cursor_getiter,           /* tp_iter */
         (iternextfunc)pysqlite_cursor_iternext,         /* tp_iternext */
         cursor_methods,                                 /* tp_methods */

Modified: python/branches/py3k/Modules/_sqlite/cursor.h
==============================================================================
--- python/branches/py3k/Modules/_sqlite/cursor.h	(original)
+++ python/branches/py3k/Modules/_sqlite/cursor.h	Fri Mar  5 16:20:03 2010
@@ -1,6 +1,6 @@
 /* cursor.h - definitions for the cursor type
  *
- * Copyright (C) 2004-2007 Gerhard Häring <gh at ghaering.de>
+ * Copyright (C) 2004-2010 Gerhard Häring <gh at ghaering.de>
  *
  * This file is part of pysqlite.
  *
@@ -40,9 +40,14 @@
     long rowcount;
     PyObject* row_factory;
     pysqlite_Statement* statement;
+    int closed;
+    int reset;
+    int initialized;
 
     /* the next row to be returned, NULL if no next row available */
     PyObject* next_row;
+
+    PyObject* in_weakreflist; /* List of weak references */
 } pysqlite_Cursor;
 
 typedef enum {
@@ -53,8 +58,6 @@
 
 extern PyTypeObject pysqlite_CursorType;
 
-int pysqlite_cursor_init(pysqlite_Cursor* self, PyObject* args, PyObject* kwargs);
-void pysqlite_cursor_dealloc(pysqlite_Cursor* self);
 PyObject* pysqlite_cursor_execute(pysqlite_Cursor* self, PyObject* args);
 PyObject* pysqlite_cursor_executemany(pysqlite_Cursor* self, PyObject* args);
 PyObject* pysqlite_cursor_getiter(pysqlite_Cursor *self);

Modified: python/branches/py3k/Modules/_sqlite/module.c
==============================================================================
--- python/branches/py3k/Modules/_sqlite/module.c	(original)
+++ python/branches/py3k/Modules/_sqlite/module.c	Fri Mar  5 16:20:03 2010
@@ -1,6 +1,6 @@
 /* module.c - the module itself
  *
- * Copyright (C) 2004-2007 Gerhard Häring <gh at ghaering.de>
+ * Copyright (C) 2004-2010 Gerhard Häring <gh at ghaering.de>
  *
  * This file is part of pysqlite.
  *

Modified: python/branches/py3k/Modules/_sqlite/module.h
==============================================================================
--- python/branches/py3k/Modules/_sqlite/module.h	(original)
+++ python/branches/py3k/Modules/_sqlite/module.h	Fri Mar  5 16:20:03 2010
@@ -1,6 +1,6 @@
 /* module.h - definitions for the module
  *
- * Copyright (C) 2004-2007 Gerhard Häring <gh at ghaering.de>
+ * Copyright (C) 2004-2010 Gerhard Häring <gh at ghaering.de>
  *
  * This file is part of pysqlite.
  *
@@ -25,7 +25,7 @@
 #define PYSQLITE_MODULE_H
 #include "Python.h"
 
-#define PYSQLITE_VERSION "2.4.1"
+#define PYSQLITE_VERSION "2.6.0"
 
 extern PyObject* pysqlite_Error;
 extern PyObject* pysqlite_Warning;

Modified: python/branches/py3k/Modules/_sqlite/prepare_protocol.c
==============================================================================
--- python/branches/py3k/Modules/_sqlite/prepare_protocol.c	(original)
+++ python/branches/py3k/Modules/_sqlite/prepare_protocol.c	Fri Mar  5 16:20:03 2010
@@ -1,6 +1,6 @@
 /* prepare_protocol.c - the protocol for preparing values for SQLite
  *
- * Copyright (C) 2005-2006 Gerhard Häring <gh at ghaering.de>
+ * Copyright (C) 2005-2010 Gerhard Häring <gh at ghaering.de>
  *
  * This file is part of pysqlite.
  *
@@ -21,6 +21,7 @@
  * 3. This notice may not be removed or altered from any source distribution.
  */
 
+#include "sqlitecompat.h"
 #include "prepare_protocol.h"
 
 int pysqlite_prepare_protocol_init(pysqlite_PrepareProtocol* self, PyObject* args, PyObject* kwargs)

Modified: python/branches/py3k/Modules/_sqlite/prepare_protocol.h
==============================================================================
--- python/branches/py3k/Modules/_sqlite/prepare_protocol.h	(original)
+++ python/branches/py3k/Modules/_sqlite/prepare_protocol.h	Fri Mar  5 16:20:03 2010
@@ -1,6 +1,6 @@
 /* prepare_protocol.h - the protocol for preparing values for SQLite
  *
- * Copyright (C) 2005-2007 Gerhard Häring <gh at ghaering.de>
+ * Copyright (C) 2005-2010 Gerhard Häring <gh at ghaering.de>
  *
  * This file is part of pysqlite.
  *

Modified: python/branches/py3k/Modules/_sqlite/row.c
==============================================================================
--- python/branches/py3k/Modules/_sqlite/row.c	(original)
+++ python/branches/py3k/Modules/_sqlite/row.c	Fri Mar  5 16:20:03 2010
@@ -1,6 +1,6 @@
 /* row.c - an enhanced tuple for database rows
  *
- * Copyright (C) 2005-2006 Gerhard Häring <gh at ghaering.de>
+ * Copyright (C) 2005-2010 Gerhard Häring <gh at ghaering.de>
  *
  * This file is part of pysqlite.
  *
@@ -172,17 +172,17 @@
 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;
+        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);
-	}
+        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;

Modified: python/branches/py3k/Modules/_sqlite/row.h
==============================================================================
--- python/branches/py3k/Modules/_sqlite/row.h	(original)
+++ python/branches/py3k/Modules/_sqlite/row.h	Fri Mar  5 16:20:03 2010
@@ -1,6 +1,6 @@
 /* row.h - an enhanced tuple for database rows
  *
- * Copyright (C) 2005-2007 Gerhard Häring <gh at ghaering.de>
+ * Copyright (C) 2005-2010 Gerhard Häring <gh at ghaering.de>
  *
  * This file is part of pysqlite.
  *

Modified: python/branches/py3k/Modules/_sqlite/sqlitecompat.h
==============================================================================
--- python/branches/py3k/Modules/_sqlite/sqlitecompat.h	(original)
+++ python/branches/py3k/Modules/_sqlite/sqlitecompat.h	Fri Mar  5 16:20:03 2010
@@ -1,6 +1,6 @@
 /* sqlitecompat.h - compatibility macros
  *
- * Copyright (C) 2006 Gerhard Häring <gh at ghaering.de>
+ * Copyright (C) 2006-2010 Gerhard Häring <gh at ghaering.de>
  *
  * This file is part of pysqlite.
  *
@@ -21,6 +21,8 @@
  * 3. This notice may not be removed or altered from any source distribution.
  */
 
+#include "Python.h"
+
 #ifndef PYSQLITE_COMPAT_H
 #define PYSQLITE_COMPAT_H
 
@@ -31,4 +33,31 @@
 typedef int (*lenfunc)(PyObject*);
 #endif
 
+
+/* define PyDict_CheckExact for pre-2.4 versions of Python */
+#ifndef PyDict_CheckExact
+#define PyDict_CheckExact(op) ((op)->ob_type == &PyDict_Type)
+#endif
+
+/* define Py_CLEAR for pre-2.4 versions of Python */
+#ifndef Py_CLEAR
+#define Py_CLEAR(op)				\
+        do {                            	\
+                if (op) {			\
+                        PyObject *tmp = (PyObject *)(op);	\
+                        (op) = NULL;		\
+                        Py_DECREF(tmp);		\
+                }				\
+        } while (0)
+#endif
+
+#ifndef PyVarObject_HEAD_INIT
+#define PyVarObject_HEAD_INIT(type, size) \
+    PyObject_HEAD_INIT(type) size,
+#endif
+
+#ifndef Py_TYPE
+#define Py_TYPE(ob) ((ob)->ob_type)
+#endif
+
 #endif

Modified: python/branches/py3k/Modules/_sqlite/statement.c
==============================================================================
--- python/branches/py3k/Modules/_sqlite/statement.c	(original)
+++ python/branches/py3k/Modules/_sqlite/statement.c	Fri Mar  5 16:20:03 2010
@@ -1,6 +1,6 @@
 /* statement.c - the statement type
  *
- * Copyright (C) 2005-2007 Gerhard Häring <gh at ghaering.de>
+ * Copyright (C) 2005-2010 Gerhard Häring <gh at ghaering.de>
  *
  * This file is part of pysqlite.
  *

Modified: python/branches/py3k/Modules/_sqlite/statement.h
==============================================================================
--- python/branches/py3k/Modules/_sqlite/statement.h	(original)
+++ python/branches/py3k/Modules/_sqlite/statement.h	Fri Mar  5 16:20:03 2010
@@ -1,6 +1,6 @@
 /* statement.h - definitions for the statement type
  *
- * Copyright (C) 2005-2007 Gerhard Häring <gh at ghaering.de>
+ * Copyright (C) 2005-2010 Gerhard Häring <gh at ghaering.de>
  *
  * This file is part of pysqlite.
  *

Modified: python/branches/py3k/Modules/_sqlite/util.c
==============================================================================
--- python/branches/py3k/Modules/_sqlite/util.c	(original)
+++ python/branches/py3k/Modules/_sqlite/util.c	Fri Mar  5 16:20:03 2010
@@ -1,6 +1,6 @@
 /* util.c - various utility functions
  *
- * Copyright (C) 2005-2007 Gerhard Häring <gh at ghaering.de>
+ * Copyright (C) 2005-2010 Gerhard Häring <gh at ghaering.de>
  *
  * This file is part of pysqlite.
  *

Modified: python/branches/py3k/Modules/_sqlite/util.h
==============================================================================
--- python/branches/py3k/Modules/_sqlite/util.h	(original)
+++ python/branches/py3k/Modules/_sqlite/util.h	Fri Mar  5 16:20:03 2010
@@ -1,6 +1,6 @@
 /* util.h - various utility functions
  *
- * Copyright (C) 2005-2007 Gerhard Häring <gh at ghaering.de>
+ * Copyright (C) 2005-2010 Gerhard Häring <gh at ghaering.de>
  *
  * This file is part of pysqlite.
  *

Modified: python/branches/py3k/setup.py
==============================================================================
--- python/branches/py3k/setup.py	(original)
+++ python/branches/py3k/setup.py	Fri Mar  5 16:20:03 2010
@@ -876,6 +876,8 @@
             else:
                 sqlite_defines.append(('MODULE_NAME', '\\"sqlite3\\"'))
 
+            # Comment this out if you want the sqlite3 module to be able to load extensions.
+            sqlite_defines.append(("SQLITE_OMIT_LOAD_EXTENSION", "1"))
 
             if sys.platform == 'darwin':
                 # In every directory on the search path search for a dynamic


More information about the Python-checkins mailing list