Index: Tools/scripts/serve.py =================================================================== --- Tools/scripts/serve.py (revision 81601) +++ Tools/scripts/serve.py (working copy) @@ -1,4 +1,4 @@ -#!/usr/bin/env python3 +#!/usr/bin/env python ''' Small wsgiref based web server. Takes a path to serve from and an optional port number (defaults to 8000), then tries to serve files. @@ -28,5 +28,5 @@ path = sys.argv[1] port = int(sys.argv[2]) if len(sys.argv) > 2 else 8000 httpd = simple_server.make_server('', port, app) - print("Serving {} on port {}".format(path, port)) + print("Serving {0} on port {1}".format(path, port)) httpd.serve_forever() Index: Doc/whatsnew/3.2.rst =================================================================== --- Doc/whatsnew/3.2.rst (revision 81601) +++ Doc/whatsnew/3.2.rst (working copy) @@ -100,6 +100,18 @@ (Contributed by Tarek Ziade.) +* The *sqlite3* module has some new features: + + * XXX *enable_load_extension* + + * XXX *load_extension* + + * New :class:`~sqlite3.Connection` attribute + :attr:`~sqlite3.Connection.in_transaction` is :const:`True` when there + are uncommitted changes, and :const:`False` otherwise. (Contributed + by R. David Murray and Shashwat Anand, :issue:`8845`.) + + Multi-threading =============== Index: Doc/library/sqlite3.rst =================================================================== --- Doc/library/sqlite3.rst (revision 81601) +++ Doc/library/sqlite3.rst (working copy) @@ -227,7 +227,14 @@ one of "DEFERRED", "IMMEDIATE" or "EXCLUSIVE". See section :ref:`sqlite3-controlling-transactions` for a more detailed explanation. +.. attribute:: Connection.in_transaction + .. versionadded:: 3.2 + + :cont:`True` if a transaction is active (there are uncommitted changes), + :const:`False` otherwise. Read-only attribute. + + .. method:: Connection.cursor([cursorClass]) The cursor method accepts a single optional parameter *cursorClass*. If @@ -806,7 +813,8 @@ before executing that command. There are two reasons for doing that. The first is that some of these commands don't work within transactions. The other reason is that sqlite3 needs to keep track of the transaction state (if a transaction -is active or not). +is active or not). The current transaction state is exposed through the +:attr:`Connection.in_transaction` attribute of the connection object. You can control which kind of ``BEGIN`` statements sqlite3 implicitly executes (or none at all) via the *isolation_level* parameter to the :func:`connect` Index: Lib/sqlite3/test/dbapi.py =================================================================== --- Lib/sqlite3/test/dbapi.py (revision 81601) +++ Lib/sqlite3/test/dbapi.py (working copy) @@ -84,6 +84,7 @@ "NotSupportedError is not a subclass of DatabaseError") class ConnectionTests(unittest.TestCase): + def setUp(self): self.cx = sqlite.connect(":memory:") cu = self.cx.cursor() @@ -140,6 +141,28 @@ self.assertEqual(self.cx.ProgrammingError, sqlite.ProgrammingError) self.assertEqual(self.cx.NotSupportedError, sqlite.NotSupportedError) + def CheckInTransaction(self): + # Can't use db from setUp because we want to test initial state. + cx = sqlite.connect(":memory:") + cu = cx.cursor() + self.assertEqual(cx.in_transaction, False) + cu.execute("create table transactiontest(id integer primary key, name text)") + self.assertEqual(cx.in_transaction, False) + cu.execute("insert into transactiontest(name) values (?)", ("foo",)) + self.assertEqual(cx.in_transaction, True) + cu.execute("select name from transactiontest where name=?", ["foo"]) + row = cu.fetchone() + self.assertEqual(cx.in_transaction, True) + cx.commit() + self.assertEqual(cx.in_transaction, False) + cu.execute("select name from transactiontest where name=?", ["foo"]) + row = cu.fetchone() + self.assertEqual(cx.in_transaction, False) + + def CheckInTransactionRO(self): + with self.assertRaises(AttributeError): + self.cx.in_transaction = True + class CursorTests(unittest.TestCase): def setUp(self): self.cx = sqlite.connect(":memory:") Index: Modules/_sqlite/connection.c =================================================================== --- Modules/_sqlite/connection.c (revision 81601) +++ Modules/_sqlite/connection.c (working copy) @@ -23,6 +23,7 @@ #include "cache.h" #include "module.h" +#include "structmember.h" #include "connection.h" #include "statement.h" #include "cursor.h" @@ -1551,6 +1552,7 @@ {"NotSupportedError", T_OBJECT, offsetof(pysqlite_Connection, NotSupportedError), READONLY}, {"row_factory", T_OBJECT, offsetof(pysqlite_Connection, row_factory)}, {"text_factory", T_OBJECT, offsetof(pysqlite_Connection, text_factory)}, + {"in_transaction", T_BOOL, offsetof(pysqlite_Connection, inTransaction), READONLY}, {NULL} };