mirror of
https://github.com/python/cpython.git
synced 2025-10-31 21:51:50 +00:00
bpo-44859: Improve error handling in sqlite3 and and raise more accurate exceptions. (GH-27654)
* MemoryError is now raised instead of sqlite3.Warning when memory is not enough for encoding a statement to UTF-8 in Connection.__call__() and Cursor.execute(). * UnicodEncodeError is now raised instead of sqlite3.Warning when the statement contains surrogate characters in Connection.__call__() and Cursor.execute(). * TypeError is now raised instead of ValueError for non-string script argument in Cursor.executescript(). * ValueError is now raised for script containing the null character instead of truncating it in Cursor.executescript(). * Correctly handle exceptions raised when getting boolean value of the result of the progress handler. * Add many tests covering different corner cases. Co-authored-by: Erlend Egeberg Aasland <erlend.aasland@innova.no>
This commit is contained in:
parent
ebecffdb6d
commit
0eec6276fd
10 changed files with 226 additions and 52 deletions
|
|
@ -33,28 +33,37 @@
|
|||
from test.support import bigmemtest
|
||||
|
||||
|
||||
def with_tracebacks(strings):
|
||||
def with_tracebacks(strings, traceback=True):
|
||||
"""Convenience decorator for testing callback tracebacks."""
|
||||
strings.append('Traceback')
|
||||
if traceback:
|
||||
strings.append('Traceback')
|
||||
|
||||
def decorator(func):
|
||||
@functools.wraps(func)
|
||||
def wrapper(self, *args, **kwargs):
|
||||
# First, run the test with traceback enabled.
|
||||
sqlite.enable_callback_tracebacks(True)
|
||||
buf = io.StringIO()
|
||||
with contextlib.redirect_stderr(buf):
|
||||
with check_tracebacks(self, strings):
|
||||
func(self, *args, **kwargs)
|
||||
tb = buf.getvalue()
|
||||
for s in strings:
|
||||
self.assertIn(s, tb)
|
||||
|
||||
# Then run the test with traceback disabled.
|
||||
sqlite.enable_callback_tracebacks(False)
|
||||
func(self, *args, **kwargs)
|
||||
return wrapper
|
||||
return decorator
|
||||
|
||||
@contextlib.contextmanager
|
||||
def check_tracebacks(self, strings):
|
||||
"""Convenience context manager for testing callback tracebacks."""
|
||||
sqlite.enable_callback_tracebacks(True)
|
||||
try:
|
||||
buf = io.StringIO()
|
||||
with contextlib.redirect_stderr(buf):
|
||||
yield
|
||||
tb = buf.getvalue()
|
||||
for s in strings:
|
||||
self.assertIn(s, tb)
|
||||
finally:
|
||||
sqlite.enable_callback_tracebacks(False)
|
||||
|
||||
def func_returntext():
|
||||
return "foo"
|
||||
def func_returntextwithnull():
|
||||
|
|
@ -408,9 +417,26 @@ def md5sum(t):
|
|||
del x,y
|
||||
gc.collect()
|
||||
|
||||
def test_func_return_too_large_int(self):
|
||||
cur = self.con.cursor()
|
||||
for value in 2**63, -2**63-1, 2**64:
|
||||
self.con.create_function("largeint", 0, lambda value=value: value)
|
||||
with check_tracebacks(self, ['OverflowError']):
|
||||
with self.assertRaises(sqlite.DataError):
|
||||
cur.execute("select largeint()")
|
||||
|
||||
def test_func_return_text_with_surrogates(self):
|
||||
cur = self.con.cursor()
|
||||
self.con.create_function("pychr", 1, chr)
|
||||
for value in 0xd8ff, 0xdcff:
|
||||
with check_tracebacks(self,
|
||||
['UnicodeEncodeError', 'surrogates not allowed']):
|
||||
with self.assertRaises(sqlite.OperationalError):
|
||||
cur.execute("select pychr(?)", (value,))
|
||||
|
||||
@unittest.skipUnless(sys.maxsize > 2**32, 'requires 64bit platform')
|
||||
@bigmemtest(size=2**31, memuse=3, dry_run=False)
|
||||
def test_large_text(self, size):
|
||||
def test_func_return_too_large_text(self, size):
|
||||
cur = self.con.cursor()
|
||||
for size in 2**31-1, 2**31:
|
||||
self.con.create_function("largetext", 0, lambda size=size: "b" * size)
|
||||
|
|
@ -419,7 +445,7 @@ def test_large_text(self, size):
|
|||
|
||||
@unittest.skipUnless(sys.maxsize > 2**32, 'requires 64bit platform')
|
||||
@bigmemtest(size=2**31, memuse=2, dry_run=False)
|
||||
def test_large_blob(self, size):
|
||||
def test_func_return_too_large_blob(self, size):
|
||||
cur = self.con.cursor()
|
||||
for size in 2**31-1, 2**31:
|
||||
self.con.create_function("largeblob", 0, lambda size=size: b"b" * size)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue