23
23
24
24
import contextlib
25
25
import functools
26
- import gc
27
26
import io
28
27
import re
29
28
import sys
30
29
import unittest
31
30
import unittest .mock
32
31
import sqlite3 as sqlite
33
32
34
- from test .support import bigmemtest , catch_unraisable_exception
33
+ from test .support import bigmemtest , catch_unraisable_exception , gc_collect
34
+
35
35
from test .test_sqlite3 .test_dbapi import cx_limit
36
36
37
37
@@ -94,22 +94,6 @@ def func_memoryerror():
94
94
def func_overflowerror ():
95
95
raise OverflowError
96
96
97
- def func_isstring (v ):
98
- return type (v ) is str
99
- def func_isint (v ):
100
- return type (v ) is int
101
- def func_isfloat (v ):
102
- return type (v ) is float
103
- def func_isnone (v ):
104
- return type (v ) is type (None )
105
- def func_isblob (v ):
106
- return isinstance (v , (bytes , memoryview ))
107
- def func_islonglong (v ):
108
- return isinstance (v , int ) and v >= 1 << 31
109
-
110
- def func (* args ):
111
- return len (args )
112
-
113
97
class AggrNoStep :
114
98
def __init__ (self ):
115
99
pass
@@ -210,17 +194,15 @@ def setUp(self):
210
194
self .con .create_function ("returnnull" , 0 , func_returnnull )
211
195
self .con .create_function ("returnblob" , 0 , func_returnblob )
212
196
self .con .create_function ("returnlonglong" , 0 , func_returnlonglong )
197
+ self .con .create_function ("returnnan" , 0 , lambda : float ("nan" ))
198
+ self .con .create_function ("returntoolargeint" , 0 , lambda : 1 << 65 )
213
199
self .con .create_function ("raiseexception" , 0 , func_raiseexception )
214
200
self .con .create_function ("memoryerror" , 0 , func_memoryerror )
215
201
self .con .create_function ("overflowerror" , 0 , func_overflowerror )
216
202
217
- self .con .create_function ("isstring" , 1 , func_isstring )
218
- self .con .create_function ("isint" , 1 , func_isint )
219
- self .con .create_function ("isfloat" , 1 , func_isfloat )
220
- self .con .create_function ("isnone" , 1 , func_isnone )
221
- self .con .create_function ("isblob" , 1 , func_isblob )
222
- self .con .create_function ("islonglong" , 1 , func_islonglong )
223
- self .con .create_function ("spam" , - 1 , func )
203
+ self .con .create_function ("isblob" , 1 , lambda x : isinstance (x , bytes ))
204
+ self .con .create_function ("isnone" , 1 , lambda x : x is None )
205
+ self .con .create_function ("spam" , - 1 , lambda * x : len (x ))
224
206
self .con .execute ("create table test(t text)" )
225
207
226
208
def tearDown (self ):
@@ -305,6 +287,16 @@ def test_func_return_long_long(self):
305
287
val = cur .fetchone ()[0 ]
306
288
self .assertEqual (val , 1 << 31 )
307
289
290
+ def test_func_return_nan (self ):
291
+ cur = self .con .cursor ()
292
+ cur .execute ("select returnnan()" )
293
+ self .assertIsNone (cur .fetchone ()[0 ])
294
+
295
+ def test_func_return_too_large_int (self ):
296
+ cur = self .con .cursor ()
297
+ self .assertRaisesRegex (sqlite .DataError , "string or blob too big" ,
298
+ self .con .execute , "select returntoolargeint()" )
299
+
308
300
@with_tracebacks (ZeroDivisionError , name = "func_raiseexception" )
309
301
def test_func_exception (self ):
310
302
cur = self .con .cursor ()
@@ -327,44 +319,6 @@ def test_func_overflow_error(self):
327
319
cur .execute ("select overflowerror()" )
328
320
cur .fetchone ()
329
321
330
- def test_param_string (self ):
331
- cur = self .con .cursor ()
332
- for text in ["foo" , str ()]:
333
- with self .subTest (text = text ):
334
- cur .execute ("select isstring(?)" , (text ,))
335
- val = cur .fetchone ()[0 ]
336
- self .assertEqual (val , 1 )
337
-
338
- def test_param_int (self ):
339
- cur = self .con .cursor ()
340
- cur .execute ("select isint(?)" , (42 ,))
341
- val = cur .fetchone ()[0 ]
342
- self .assertEqual (val , 1 )
343
-
344
- def test_param_float (self ):
345
- cur = self .con .cursor ()
346
- cur .execute ("select isfloat(?)" , (3.14 ,))
347
- val = cur .fetchone ()[0 ]
348
- self .assertEqual (val , 1 )
349
-
350
- def test_param_none (self ):
351
- cur = self .con .cursor ()
352
- cur .execute ("select isnone(?)" , (None ,))
353
- val = cur .fetchone ()[0 ]
354
- self .assertEqual (val , 1 )
355
-
356
- def test_param_blob (self ):
357
- cur = self .con .cursor ()
358
- cur .execute ("select isblob(?)" , (memoryview (b"blob" ),))
359
- val = cur .fetchone ()[0 ]
360
- self .assertEqual (val , 1 )
361
-
362
- def test_param_long_long (self ):
363
- cur = self .con .cursor ()
364
- cur .execute ("select islonglong(?)" , (1 << 42 ,))
365
- val = cur .fetchone ()[0 ]
366
- self .assertEqual (val , 1 )
367
-
368
322
def test_any_arguments (self ):
369
323
cur = self .con .cursor ()
370
324
cur .execute ("select spam(?, ?)" , (1 , 2 ))
@@ -375,6 +329,52 @@ def test_empty_blob(self):
375
329
cur = self .con .execute ("select isblob(x'')" )
376
330
self .assertTrue (cur .fetchone ()[0 ])
377
331
332
+ def test_nan_float (self ):
333
+ cur = self .con .execute ("select isnone(?)" , (float ("nan" ),))
334
+ # SQLite has no concept of nan; it is converted to NULL
335
+ self .assertTrue (cur .fetchone ()[0 ])
336
+
337
+ def test_too_large_int (self ):
338
+ err = "Python int too large to convert to SQLite INTEGER"
339
+ self .assertRaisesRegex (OverflowError , err , self .con .execute ,
340
+ "select spam(?)" , (1 << 65 ,))
341
+
342
+ def test_non_contiguous_blob (self ):
343
+ self .assertRaisesRegex (ValueError , "could not convert BLOB to buffer" ,
344
+ self .con .execute , "select spam(?)" ,
345
+ (memoryview (b"blob" )[::2 ],))
346
+
347
+ def test_param_surrogates (self ):
348
+ self .assertRaisesRegex (UnicodeEncodeError , "surrogates not allowed" ,
349
+ self .con .execute , "select spam(?)" ,
350
+ ("\ud803 \ude6d " ,))
351
+
352
+ def test_func_params (self ):
353
+ results = []
354
+ def append_result (arg ):
355
+ results .append ((arg , type (arg )))
356
+ self .con .create_function ("test_params" , 1 , append_result )
357
+
358
+ dataset = [
359
+ (42 , int ),
360
+ (- 1 , int ),
361
+ (1234567890123456789 , int ),
362
+ (4611686018427387905 , int ), # 63-bit int with non-zero low bits
363
+ (3.14 , float ),
364
+ (float ('inf' ), float ),
365
+ ("text" , str ),
366
+ ("1\x00 2" , str ),
367
+ ("\u02e2 q\u02e1 \u2071 \u1d57 \u1d49 " , str ),
368
+ (b"blob" , bytes ),
369
+ (bytearray (range (2 )), bytes ),
370
+ (memoryview (b"blob" ), bytes ),
371
+ (None , type (None )),
372
+ ]
373
+ for val , _ in dataset :
374
+ cur = self .con .execute ("select test_params(?)" , (val ,))
375
+ cur .fetchone ()
376
+ self .assertEqual (dataset , results )
377
+
378
378
# Regarding deterministic functions:
379
379
#
380
380
# Between 3.8.3 and 3.15.0, deterministic functions were only used to
@@ -430,7 +430,7 @@ def md5sum(t):
430
430
y .append (y )
431
431
432
432
del x ,y
433
- gc . collect ()
433
+ gc_collect ()
434
434
435
435
@with_tracebacks (OverflowError )
436
436
def test_func_return_too_large_int (self ):
0 commit comments