Skip to content

Commit 218f205

Browse files
gh-129354: Use PyErr_FormatUnraisable() function (#129524)
Replace PyErr_WriteUnraisable() with PyErr_FormatUnraisable(). Update test_sqlite3 tests. Co-authored-by: Erlend E. Aasland <[email protected]>
1 parent 04264a2 commit 218f205

File tree

4 files changed

+28
-21
lines changed

4 files changed

+28
-21
lines changed

Lib/test/test_sqlite3/test_hooks.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ def progress():
196196
con.execute("select 1 union select 2 union select 3").fetchall()
197197
self.assertEqual(action, 0, "progress handler was not cleared")
198198

199-
@with_tracebacks(ZeroDivisionError, name="bad_progress")
199+
@with_tracebacks(ZeroDivisionError, msg_regex="bad_progress")
200200
def test_error_in_progress_handler(self):
201201
def bad_progress():
202202
1 / 0
@@ -206,7 +206,7 @@ def bad_progress():
206206
create table foo(a, b)
207207
""")
208208

209-
@with_tracebacks(ZeroDivisionError, name="bad_progress")
209+
@with_tracebacks(ZeroDivisionError, msg_regex="bad_progress")
210210
def test_error_in_progress_handler_result(self):
211211
class BadBool:
212212
def __bool__(self):

Lib/test/test_sqlite3/test_userfunctions.py

+10-10
Original file line numberDiff line numberDiff line change
@@ -254,22 +254,22 @@ def test_func_return_nan(self):
254254
cur.execute("select returnnan()")
255255
self.assertIsNone(cur.fetchone()[0])
256256

257-
@with_tracebacks(ZeroDivisionError, name="func_raiseexception")
257+
@with_tracebacks(ZeroDivisionError, msg_regex="func_raiseexception")
258258
def test_func_exception(self):
259259
cur = self.con.cursor()
260260
with self.assertRaises(sqlite.OperationalError) as cm:
261261
cur.execute("select raiseexception()")
262262
cur.fetchone()
263263
self.assertEqual(str(cm.exception), 'user-defined function raised exception')
264264

265-
@with_tracebacks(MemoryError, name="func_memoryerror")
265+
@with_tracebacks(MemoryError, msg_regex="func_memoryerror")
266266
def test_func_memory_error(self):
267267
cur = self.con.cursor()
268268
with self.assertRaises(MemoryError):
269269
cur.execute("select memoryerror()")
270270
cur.fetchone()
271271

272-
@with_tracebacks(OverflowError, name="func_overflowerror")
272+
@with_tracebacks(OverflowError, msg_regex="func_overflowerror")
273273
def test_func_overflow_error(self):
274274
cur = self.con.cursor()
275275
with self.assertRaises(sqlite.DataError):
@@ -389,7 +389,7 @@ def test_func_return_too_large_int(self):
389389
with self.assertRaisesRegex(sqlite.DataError, msg):
390390
cur.execute("select largeint()")
391391

392-
@with_tracebacks(UnicodeEncodeError, "surrogates not allowed", "chr")
392+
@with_tracebacks(UnicodeEncodeError, "surrogates not allowed")
393393
def test_func_return_text_with_surrogates(self):
394394
cur = self.con.cursor()
395395
self.con.create_function("pychr", 1, chr)
@@ -641,7 +641,7 @@ def test_aggr_error_on_create(self):
641641
with self.assertRaises(sqlite.OperationalError):
642642
self.con.create_function("bla", -100, AggrSum)
643643

644-
@with_tracebacks(AttributeError, name="AggrNoStep")
644+
@with_tracebacks(AttributeError, msg_regex="AggrNoStep")
645645
def test_aggr_no_step(self):
646646
cur = self.con.cursor()
647647
with self.assertRaises(sqlite.OperationalError) as cm:
@@ -656,23 +656,23 @@ def test_aggr_no_finalize(self):
656656
cur.execute("select nofinalize(t) from test")
657657
val = cur.fetchone()[0]
658658

659-
@with_tracebacks(ZeroDivisionError, name="AggrExceptionInInit")
659+
@with_tracebacks(ZeroDivisionError, msg_regex="AggrExceptionInInit")
660660
def test_aggr_exception_in_init(self):
661661
cur = self.con.cursor()
662662
with self.assertRaises(sqlite.OperationalError) as cm:
663663
cur.execute("select excInit(t) from test")
664664
val = cur.fetchone()[0]
665665
self.assertEqual(str(cm.exception), "user-defined aggregate's '__init__' method raised error")
666666

667-
@with_tracebacks(ZeroDivisionError, name="AggrExceptionInStep")
667+
@with_tracebacks(ZeroDivisionError, msg_regex="AggrExceptionInStep")
668668
def test_aggr_exception_in_step(self):
669669
cur = self.con.cursor()
670670
with self.assertRaises(sqlite.OperationalError) as cm:
671671
cur.execute("select excStep(t) from test")
672672
val = cur.fetchone()[0]
673673
self.assertEqual(str(cm.exception), "user-defined aggregate's 'step' method raised error")
674674

675-
@with_tracebacks(ZeroDivisionError, name="AggrExceptionInFinalize")
675+
@with_tracebacks(ZeroDivisionError, msg_regex="AggrExceptionInFinalize")
676676
def test_aggr_exception_in_finalize(self):
677677
cur = self.con.cursor()
678678
with self.assertRaises(sqlite.OperationalError) as cm:
@@ -822,11 +822,11 @@ def authorizer_cb(action, arg1, arg2, dbname, source):
822822
raise ValueError
823823
return sqlite.SQLITE_OK
824824

825-
@with_tracebacks(ValueError, name="authorizer_cb")
825+
@with_tracebacks(ValueError, msg_regex="authorizer_cb")
826826
def test_table_access(self):
827827
super().test_table_access()
828828

829-
@with_tracebacks(ValueError, name="authorizer_cb")
829+
@with_tracebacks(ValueError, msg_regex="authorizer_cb")
830830
def test_column_access(self):
831831
super().test_table_access()
832832

Lib/test/test_sqlite3/util.py

+10-6
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,16 @@ def cx_limit(cx, category=sqlite3.SQLITE_LIMIT_SQL_LENGTH, limit=128):
2222
cx.setlimit(category, _prev)
2323

2424

25-
def with_tracebacks(exc, regex="", name=""):
25+
def with_tracebacks(exc, regex="", name="", msg_regex=""):
2626
"""Convenience decorator for testing callback tracebacks."""
2727
def decorator(func):
28-
_regex = re.compile(regex) if regex else None
28+
exc_regex = re.compile(regex) if regex else None
29+
_msg_regex = re.compile(msg_regex) if msg_regex else None
2930
@functools.wraps(func)
3031
def wrapper(self, *args, **kwargs):
3132
with test.support.catch_unraisable_exception() as cm:
3233
# First, run the test with traceback enabled.
33-
with check_tracebacks(self, cm, exc, _regex, name):
34+
with check_tracebacks(self, cm, exc, exc_regex, _msg_regex, name):
3435
func(self, *args, **kwargs)
3536

3637
# Then run the test with traceback disabled.
@@ -40,7 +41,7 @@ def wrapper(self, *args, **kwargs):
4041

4142

4243
@contextlib.contextmanager
43-
def check_tracebacks(self, cm, exc, regex, obj_name):
44+
def check_tracebacks(self, cm, exc, exc_regex, msg_regex, obj_name):
4445
"""Convenience context manager for testing callback tracebacks."""
4546
sqlite3.enable_callback_tracebacks(True)
4647
try:
@@ -49,9 +50,12 @@ def check_tracebacks(self, cm, exc, regex, obj_name):
4950
yield
5051

5152
self.assertEqual(cm.unraisable.exc_type, exc)
52-
if regex:
53+
if exc_regex:
5354
msg = str(cm.unraisable.exc_value)
54-
self.assertIsNotNone(regex.search(msg))
55+
self.assertIsNotNone(exc_regex.search(msg), (exc_regex, msg))
56+
if msg_regex:
57+
msg = cm.unraisable.err_msg
58+
self.assertIsNotNone(msg_regex.search(msg), (msg_regex, msg))
5559
if obj_name:
5660
self.assertEqual(cm.unraisable.object.__name__, obj_name)
5761
finally:

Modules/_sqlite/connection.c

+6-3
Original file line numberDiff line numberDiff line change
@@ -497,7 +497,8 @@ connection_finalize(PyObject *self)
497497
if (PyErr_ResourceWarning(self, 1, "unclosed database in %R", self)) {
498498
/* Spurious errors can appear at shutdown */
499499
if (PyErr_ExceptionMatches(PyExc_Warning)) {
500-
PyErr_WriteUnraisable(self);
500+
PyErr_FormatUnraisable("Exception ignored while finalizing "
501+
"database connection %R", self);
501502
}
502503
}
503504
}
@@ -506,7 +507,8 @@ connection_finalize(PyObject *self)
506507
PyErr_Clear();
507508
}
508509
else {
509-
PyErr_WriteUnraisable((PyObject *)self);
510+
PyErr_FormatUnraisable("Exception ignored while closing database %R",
511+
self);
510512
}
511513
}
512514

@@ -893,7 +895,8 @@ print_or_clear_traceback(callback_context *ctx)
893895
assert(ctx != NULL);
894896
assert(ctx->state != NULL);
895897
if (ctx->state->enable_callback_tracebacks) {
896-
PyErr_WriteUnraisable(ctx->callable);
898+
PyErr_FormatUnraisable("Exception ignored on sqlite3 callback %R",
899+
ctx->callable);
897900
}
898901
else {
899902
PyErr_Clear();

0 commit comments

Comments
 (0)