Skip to content

Commit 478a1aa

Browse files
committed
Backported issue python#4589 to Python 2.5.3: Propagated an exception thrown by a
context manager's __exit__ method's result while it's being converted to bool.
1 parent 05e9c9d commit 478a1aa

3 files changed

Lines changed: 42 additions & 3 deletions

File tree

‎Lib/test/test_with.py‎

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -505,6 +505,36 @@ def shouldThrow():
505505

506506
self.assertRaises(GeneratorExit, shouldThrow)
507507

508+
def testErrorsInBool(self):
509+
# issue4589: __exit__ return code may raise an exception
510+
# when looking at its truth value.
511+
512+
class cm(object):
513+
def __init__(self, bool_conversion):
514+
class Bool:
515+
def __nonzero__(self):
516+
return bool_conversion()
517+
self.exit_result = Bool()
518+
def __enter__(self):
519+
return 3
520+
def __exit__(self, a, b, c):
521+
return self.exit_result
522+
523+
def trueAsBool():
524+
with cm(lambda: True):
525+
self.fail("Should NOT see this")
526+
trueAsBool()
527+
528+
def falseAsBool():
529+
with cm(lambda: False):
530+
self.fail("Should raise")
531+
self.assertRaises(AssertionError, falseAsBool)
532+
533+
def failAsBool():
534+
with cm(lambda: 1//0):
535+
self.fail("Should NOT see this")
536+
self.assertRaises(ZeroDivisionError, failAsBool)
537+
508538

509539
class NonLocalFlowControlTestCase(unittest.TestCase):
510540

‎Misc/NEWS‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ What's New in Python 2.5.3?
1212
Core and builtins
1313
-----------------
1414

15+
- Issue #4589: Propagated an exception thrown by a context manager's
16+
__exit__ method's result while it's being converted to bool.
17+
1518
- Issue #4317: Fixed a crash in the imageop.rgb2rgb8() function.
1619

1720
- Issue #4230: If ``__getattr__`` is a descriptor, it now functions correctly.

‎Python/ceval.c‎

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2263,9 +2263,16 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
22632263
x = PyObject_CallFunctionObjArgs(x, u, v, w, NULL);
22642264
if (x == NULL)
22652265
break; /* Go to error exit */
2266-
if (u != Py_None && PyObject_IsTrue(x)) {
2266+
if (u != Py_None)
2267+
err = PyObject_IsTrue(x);
2268+
else
2269+
err = 0;
2270+
Py_DECREF(x);
2271+
if (err < 0)
2272+
break; /* Go to error exit */
2273+
else if (err > 0) {
2274+
err = 0;
22672275
/* There was an exception and a true return */
2268-
Py_DECREF(x);
22692276
x = TOP(); /* Again */
22702277
STACKADJ(-3);
22712278
Py_INCREF(Py_None);
@@ -2276,7 +2283,6 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
22762283
Py_DECREF(w);
22772284
} else {
22782285
/* Let END_FINALLY do its thing */
2279-
Py_DECREF(x);
22802286
x = POP();
22812287
Py_DECREF(x);
22822288
}

0 commit comments

Comments
 (0)