1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 | Lib/sqlite3/test/factory.py
#-*- coding: ISO-8859-1 -*- # pysqlite2/test/factory.py: tests for the various factories in pysqlite # # Copyright (C) 2005-2007 Gerhard Häring <gh@ghaering.de> # # This file is part of pysqlite. # # This software is provided 'as-is', without any express or implied # warranty. In no event will the authors be held liable for any damages # arising from the use of this software. # # Permission is granted to anyone to use this software for any purpose, # including commercial applications, and to alter it and redistribute it # freely, subject to the following restrictions: # # 1. The origin of this software must not be misrepresented; you must not # claim that you wrote the original software. If you use this software # in a product, an acknowledgment in the product documentation would be # appreciated but is not required. # 2. Altered source versions must be plainly marked as such, and must not be # misrepresented as being the original software. # 3. This notice may not be removed or altered from any source distribution. import unittest import sqlite3 as sqlite from collections import Sequence class MyConnection(sqlite.Connection): def __init__(self, *args, **kwargs): sqlite.Connection.__init__(self, *args, **kwargs) def dict_factory(cursor, row): d = {} for idx, col in enumerate(cursor.description): d[col[0]] = row[idx] return d class MyCursor(sqlite.Cursor): def __init__(self, *args, **kwargs): sqlite.Cursor.__init__(self, *args, **kwargs) self.row_factory = dict_factory class ConnectionFactoryTests(unittest.TestCase): def setUp(self): self.con = sqlite.connect(":memory:", factory=MyConnection) def tearDown(self): self.con.close() def CheckIsInstance(self): self.assertIsInstance(self.con, MyConnection) class CursorFactoryTests(unittest.TestCase): def setUp(self): self.con = sqlite.connect(":memory:") def tearDown(self): self.con.close() def CheckIsInstance(self): cur = self.con.cursor(factory=MyCursor) self.assertIsInstance(cur, MyCursor) class RowFactoryTestsBackwardsCompat(unittest.TestCase): def setUp(self): self.con = sqlite.connect(":memory:") def CheckIsProducedByFactory(self): cur = self.con.cursor(factory=MyCursor) cur.execute("select 4+5 as foo") row = cur.fetchone() self.assertIsInstance(row, dict) cur.close() def tearDown(self): self.con.close() class RowFactoryTests(unittest.TestCase): def setUp(self): self.con = sqlite.connect(":memory:") def CheckCustomFactory(self): self.con.row_factory = lambda cur, row: list(row) row = self.con.execute("select 1, 2").fetchone() self.assertIsInstance(row, list) def CheckSqliteRowIndex(self): self.con.row_factory = sqlite.Row row = self.con.execute("select 1 as a, 2 as b").fetchone() self.assertIsInstance(row, sqlite.Row) col1, col2 = row["a"], row["b"] self.assertEqual(col1, 1, "by name: wrong result for column 'a'") self.assertEqual(col2, 2, "by name: wrong result for column 'a'") col1, col2 = row["A"], row["B"] self.assertEqual(col1, 1, "by name: wrong result for column 'A'") self.assertEqual(col2, 2, "by name: wrong result for column 'B'") self.assertEqual(row[0], 1, "by index: wrong result for column 0") self.assertEqual(row[0L], 1, "by index: wrong result for column 0") self.assertEqual(row[1], 2, "by index: wrong result for column 1") self.assertEqual(row[1L], 2, "by index: wrong result for column 1") self.assertEqual(row[-1], 2, "by index: wrong result for column -1") self.assertEqual(row[-1L], 2, "by index: wrong result for column -1") self.assertEqual(row[-2], 1, "by index: wrong result for column -2") self.assertEqual(row[-2L], 1, "by index: wrong result for column -2") with self.assertRaises(IndexError): row['c'] with self.assertRaises(IndexError): row[2] with self.assertRaises(IndexError): row[2L] with self.assertRaises(IndexError): row[-3] with self.assertRaises(IndexError): row[-3L] with self.assertRaises(IndexError): row[2**1000] def CheckSqliteRowIter(self): """Checks if the row object is iterable""" self.con.row_factory = sqlite.Row row = self.con.execute("select 1 as a, 2 as b").fetchone() for col in row: pass def CheckSqliteRowAsTuple(self): """Checks if the row object can be converted to a tuple""" self.con.row_factory = sqlite.Row row = self.con.execute("select 1 as a, 2 as b").fetchone() t = tuple(row) self.assertEqual(t, (row['a'], row['b'])) def CheckSqliteRowAsDict(self): """Checks if the row object can be correctly converted to a dictionary""" self.con.row_factory = sqlite.Row row = self.con.execute("select 1 as a, 2 as b").fetchone() d = dict(row) self.assertEqual(d["a"], row["a"]) self.assertEqual(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.assertEqual(row_1, row_1) self.assertEqual(row_1, row_2) self.assertTrue(row_2 != row_3) self.assertFalse(row_1 != row_1) self.assertFalse(row_1 != row_2) self.assertFalse(row_2 == row_3) self.assertEqual(row_1, row_2) self.assertEqual(hash(row_1), hash(row_2)) self.assertNotEqual(row_1, row_3) self.assertNotEqual(hash(row_1), hash(row_3)) def CheckSqliteRowAsSequence(self): """ Checks if the row object can act like a sequence """ self.con.row_factory = sqlite.Row row = self.con.execute("select 1 as a, 2 as b").fetchone() as_tuple = tuple(row) self.assertEqual(list(reversed(row)), list(reversed(as_tuple))) self.assertIsInstance(row, Sequence) def CheckFakeCursorClass(self): # Issue #24257: Incorrect use of PyObject_IsInstance() caused # segmentation fault. class FakeCursor(str): __class__ = sqlite.Cursor cur = self.con.cursor(factory=FakeCursor) self.assertRaises(TypeError, sqlite.Row, cur, ()) def tearDown(self): self.con.close() class TextFactoryTests(unittest.TestCase): def setUp(self): self.con = sqlite.connect(":memory:") def CheckUnicode(self): austria = unicode("Österreich", "latin1") row = self.con.execute("select ?", (austria,)).fetchone() self.assertEqual(type(row[0]), unicode, "type of row[0] must be unicode") def CheckString(self): self.con.text_factory = str austria = unicode("Österreich", "latin1") row = self.con.execute("select ?", (austria,)).fetchone() self.assertEqual(type(row[0]), str, "type of row[0] must be str") self.assertEqual(row[0], austria.encode("utf-8"), "column must equal original data in UTF-8") def CheckCustom(self): self.con.text_factory = lambda x: unicode(x, "utf-8", "ignore") austria = unicode("Österreich", "latin1") row = self.con.execute("select ?", (austria.encode("latin1"),)).fetchone() self.assertEqual(type(row[0]), unicode, "type of row[0] must be unicode") self.assertTrue(row[0].endswith(u"reich"), "column must contain original data") def CheckOptimizedUnicode(self): self.con.text_factory = sqlite.OptimizedUnicode austria = unicode("Österreich", "latin1") germany = unicode("Deutchland") a_row = self.con.execute("select ?", (austria,)).fetchone() d_row = self.con.execute("select ?", (germany,)).fetchone() self.assertEqual(type(a_row[0]), unicode, "type of non-ASCII row must be unicode") self.assertEqual(type(d_row[0]), str, "type of ASCII-only row must be str") def tearDown(self): self.con.close() class TextFactoryTestsWithEmbeddedZeroBytes(unittest.TestCase): def setUp(self): self.con = sqlite.connect(":memory:") self.con.execute("create table test (value text)") self.con.execute("insert into test (value) values (?)", ("a\x00b",)) def CheckString(self): # text_factory defaults to unicode row = self.con.execute("select value from test").fetchone() self.assertIs(type(row[0]), unicode) self.assertEqual(row[0], "a\x00b") def CheckCustom(self): # A custom factory should receive an str argument self.con.text_factory = lambda x: x row = self.con.execute("select value from test").fetchone() self.assertIs(type(row[0]), str) self.assertEqual(row[0], "a\x00b") def CheckOptimizedUnicodeAsString(self): # ASCII -> str argument self.con.text_factory = sqlite.OptimizedUnicode row = self.con.execute("select value from test").fetchone() self.assertIs(type(row[0]), str) self.assertEqual(row[0], "a\x00b") def CheckOptimizedUnicodeAsUnicode(self): # Non-ASCII -> unicode argument self.con.text_factory = sqlite.OptimizedUnicode self.con.execute("delete from test") self.con.execute("insert into test (value) values (?)", (u'ä\0ö',)) row = self.con.execute("select value from test").fetchone() self.assertIs(type(row[0]), unicode) self.assertEqual(row[0], u"ä\x00ö") def tearDown(self): self.con.close() def suite(): connection_suite = unittest.makeSuite(ConnectionFactoryTests, "Check") cursor_suite = unittest.makeSuite(CursorFactoryTests, "Check") row_suite_compat = unittest.makeSuite(RowFactoryTestsBackwardsCompat, "Check") row_suite = unittest.makeSuite(RowFactoryTests, "Check") text_suite = unittest.makeSuite(TextFactoryTests, "Check") text_zero_bytes_suite = unittest.makeSuite(TextFactoryTestsWithEmbeddedZeroBytes, "Check") return unittest.TestSuite((connection_suite, cursor_suite, row_suite_compat, row_suite, text_suite, text_zero_bytes_suite)) def test(): runner = unittest.TextTestRunner() runner.run(suite()) if __name__ == "__main__": test() |