Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(6)

Delta Between Two Patch Sets: Lib/sqlite3/test/factory.py

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

RSS Feeds Recent Issues | This issue
This is Rietveld 894c83f36cb7+