Skip to content

Commit a845949

Browse files
committed
Pass original error to process_tuple exception handler consistently
Instead of relying on exception context, pass the original error to process_tuple exception handler explicitly. This makes exception chain semantically correct.
1 parent ab8471e commit a845949

3 files changed

Lines changed: 14 additions & 15 deletions

File tree

postgresql/driver/pq3.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -417,7 +417,7 @@ def record_io_factory(self,
417417
funpack = tuple(map(get1, column_io))
418418
row_constructor = self.RowTypeFactory(attribute_map = attmap, composite_relid = composite_relid)
419419

420-
def raise_pack_tuple_error(procs, tup, itemnum):
420+
def raise_pack_tuple_error(procs, tup, itemnum, cause = None):
421421
data = repr(tup[itemnum])
422422
if len(data) > 80:
423423
# Be sure not to fill screen with noise.
@@ -428,9 +428,9 @@ def raise_pack_tuple_error(procs, tup, itemnum):
428428
(b'M', fmt_errmsg('pack', itemnum, attnames[itemnum], typnames[itemnum], composite_name),),
429429
(b'W', data,),
430430
(b'P', str(itemnum),)
431-
)))
431+
)), cause = cause)
432432

433-
def raise_unpack_tuple_error(procs, tup, itemnum):
433+
def raise_unpack_tuple_error(procs, tup, itemnum, cause = None):
434434
data = repr(tup[itemnum])
435435
if len(data) > 80:
436436
# Be sure not to fill screen with noise.
@@ -441,7 +441,7 @@ def raise_unpack_tuple_error(procs, tup, itemnum):
441441
(b'M', fmt_errmsg('unpack', itemnum, attnames[itemnum], typnames[itemnum], composite_name),),
442442
(b'W', data,),
443443
(b'P', str(itemnum),),
444-
)))
444+
)), cause = cause)
445445

446446
def unpack_a_record(data,
447447
unpack = io_lib.record_unpack,
@@ -752,7 +752,7 @@ def _process_tuple_chunk_Row(self, x,
752752
def _process_tuple_chunk(self, x, proc = process_chunk):
753753
return proc(self._output_io, x, self._raise_column_tuple_error)
754754

755-
def _raise_column_tuple_error(self, procs, tup, itemnum):
755+
def _raise_column_tuple_error(self, procs, tup, itemnum, cause = None):
756756
'for column processing'
757757
# The element traceback will include the full list of parameters.
758758
data = repr(tup[itemnum])
@@ -775,7 +775,7 @@ def _raise_column_tuple_error(self, procs, tup, itemnum):
775775
(b'H', "Try casting the column to 'text'."),
776776
(b'P', str(itemnum)),
777777
))
778-
self.database.typio.raise_client_error(em, creator = self)
778+
self.database.typio.raise_client_error(em, creator = self, cause = cause)
779779

780780
@property
781781
def state(self):
@@ -1302,7 +1302,7 @@ def _pq_parameters(self, parameters, proc = process_tuple):
13021302
# process_tuple failed(exception). The parameters could not be packed.
13031303
# This function is called with the given information in the context
13041304
# of the original exception(to allow chaining).
1305-
def _raise_parameter_tuple_error(self, procs, tup, itemnum):
1305+
def _raise_parameter_tuple_error(self, procs, tup, itemnum, cause = None):
13061306
# Find the SQL type name. This should *not* hit the server.
13071307
typ = self.database.typio.sql_type_from_oid(
13081308
self.pg_parameter_types[itemnum]
@@ -1325,11 +1325,11 @@ def _raise_parameter_tuple_error(self, procs, tup, itemnum):
13251325
(b'H', "Try casting the parameter to 'text', then to the target type."),
13261326
(b'P', str(itemnum))
13271327
))
1328-
self.database.typio.raise_client_error(em, creator = self)
1328+
self.database.typio.raise_client_error(em, creator = self, cause = cause)
13291329

13301330
##
13311331
# Similar to the parameter variant.
1332-
def _raise_column_tuple_error(self, procs, tup, itemnum):
1332+
def _raise_column_tuple_error(self, procs, tup, itemnum, cause = None):
13331333
# Find the SQL type name. This should *not* hit the server.
13341334
typ = self.database.typio.sql_type_from_oid(
13351335
self.pg_column_types[itemnum]
@@ -1352,7 +1352,7 @@ def _raise_column_tuple_error(self, procs, tup, itemnum):
13521352
(b'H', "Try casting the column to 'text'."),
13531353
(b'P', str(itemnum)),
13541354
))
1355-
self.database.typio.raise_client_error(em, creator = self)
1355+
self.database.typio.raise_client_error(em, creator = self, cause = cause)
13561356

13571357
@property
13581358
def state(self) -> str:

postgresql/python/functools.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,8 @@ def process_tuple(procs, tup, exception_handler, len = len, tuple = tuple):
5656
if ob is None:
5757
continue
5858
r[i] = procs[i](ob)
59-
except Exception:
60-
# relying on __context__
61-
exception_handler(procs, tup, i)
59+
except Exception as e:
60+
exception_handler(procs, tup, i, cause = e)
6261
raise RuntimeError("process_tuple exception handler failed to raise")
6362
return tuple(r)
6463

postgresql/test/test_types.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,7 @@ def testExpectIO(self, samples):
341341

342342
class test_io(unittest.TestCase):
343343
def test_process_tuple(self, pt = process_tuple):
344-
def funpass(procs, tup, col):
344+
def funpass(procs, tup, col, cause):
345345
pass
346346
self.assertEqual(tuple(pt((),(), funpass)), ())
347347
self.assertEqual(tuple(pt((int,),("100",), funpass)), (100,))
@@ -354,7 +354,7 @@ def funpass(procs, tup, col):
354354
class ThisError(Exception):
355355
pass
356356
data = []
357-
def funraise(procs, tup, col):
357+
def funraise(procs, tup, col, cause):
358358
data.append((procs, tup, col))
359359
raise ThisError
360360
self.assertRaises(ThisError, pt, (int,), ("foo",), funraise)

0 commit comments

Comments
 (0)