diff -r 811d91591f73 Doc/library/sqlite3.rst --- a/Doc/library/sqlite3.rst Mon Aug 20 10:19:12 2012 +1000 +++ b/Doc/library/sqlite3.rst Tue Aug 21 22:47:52 2012 +1000 @@ -645,6 +645,27 @@ 35.14 +NamedTupleRow Objects +--------------------- + +.. function:: NamedTupleRow + + A :func:`NamedTupleRow` instance serves as a + :attr:`~Connection.row_factory` for :class:`Connection` objects. + It returns a :func:`~collections.namedtuple` representation of a + row. + +Using the example above we plug :func:`NamedTupleRow` in:: + + >>> conn.row_factory = sqlite3.NamedTupleRow + >>> c = conn.cursor() + >>> c.execute('select * from stocks') + + >>> r = c.fetchone() + >>> r + Row(date='2006-01-05', trans='BUY', symbol='RHAT', qty=100.0, price=35.14) + + .. _sqlite3-types: SQLite and Python types diff -r 811d91591f73 Lib/sqlite3/__init__.py --- a/Lib/sqlite3/__init__.py Mon Aug 20 10:19:12 2012 +1000 +++ b/Lib/sqlite3/__init__.py Tue Aug 21 22:47:52 2012 +1000 @@ -21,3 +21,4 @@ # 3. This notice may not be removed or altered from any source distribution. from sqlite3.dbapi2 import * +from sqlite3.namedtuple import NamedTupleRow diff -r 811d91591f73 Lib/sqlite3/namedtuple.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Lib/sqlite3/namedtuple.py Tue Aug 21 22:47:52 2012 +1000 @@ -0,0 +1,12 @@ +from functools import lru_cache +from collections import namedtuple + +sql_namedtuple = lru_cache(maxsize=20)(namedtuple) + + +def NamedTupleRow(cursor, row): + """ + Return a namedtuple row factory for connection objects. + """ + fields = tuple(col[0] for col in cursor.description) + return sql_namedtuple("Row", fields)._make(row) diff -r 811d91591f73 Lib/sqlite3/test/factory.py --- a/Lib/sqlite3/test/factory.py Mon Aug 20 10:19:12 2012 +1000 +++ b/Lib/sqlite3/test/factory.py Tue Aug 21 22:47:52 2012 +1000 @@ -151,6 +151,20 @@ self.assertNotEqual(row_1, row_3) self.assertNotEqual(hash(row_1), hash(row_3)) + def CheckSqliteNamedTuple(self): + self.con.row_factory = sqlite.NamedTupleRow + row = self.con.execute("select 1 as a, 2 as b").fetchone() + self.assertTrue(issubclass(row.__class__, tuple), + "row is not instance of Tuple.") + + col1, col2 = row.a, row.b + self.assertTrue(col1 == 1, "by name: wrong result for column 'a'") + self.assertTrue(col2 == 2, "by name: wrong result for column 'a'") + + col1, col2 = row[0], row[1] + self.assertTrue(col1 == 1, "by index: wrong result for column 0") + self.assertTrue(col2 == 2, "by index: wrong result for column 1") + def tearDown(self): self.con.close()