Commit acbfc615 authored by Raymond Hettinger's avatar Raymond Hettinger

Issue #27100: With statement reports missing __enter__ before __exit__. ...

Issue #27100:  With statement reports missing __enter__ before __exit__.  (Contributed by Jonathan Ellington.)
parent cc482dfa
......@@ -109,7 +109,7 @@ class FailureTestCase(unittest.TestCase):
with foo: pass
self.assertRaises(NameError, fooNotDeclared)
def testEnterAttributeError(self):
def testEnterAttributeError1(self):
class LacksEnter(object):
def __exit__(self, type, value, traceback):
pass
......@@ -117,7 +117,16 @@ class FailureTestCase(unittest.TestCase):
def fooLacksEnter():
foo = LacksEnter()
with foo: pass
self.assertRaises(AttributeError, fooLacksEnter)
self.assertRaisesRegexp(AttributeError, '__enter__', fooLacksEnter)
def testEnterAttributeError2(self):
class LacksEnterAndExit(object):
pass
def fooLacksEnterAndExit():
foo = LacksEnterAndExit()
with foo: pass
self.assertRaisesRegexp(AttributeError, '__enter__', fooLacksEnterAndExit)
def testExitAttributeError(self):
class LacksExit(object):
......@@ -127,7 +136,7 @@ class FailureTestCase(unittest.TestCase):
def fooLacksExit():
foo = LacksExit()
with foo: pass
self.assertRaises(AttributeError, fooLacksExit)
self.assertRaisesRegexp(AttributeError, '__exit__', fooLacksExit)
def assertRaisesSyntaxError(self, codestr):
def shouldRaiseSyntaxError(s):
......
......@@ -12,6 +12,10 @@ Core and Builtins
- Issue #28532: Show sys.version when -V option is supplied twice.
- Issue #27100: The with-statement now checks for __enter__ before it
checks for __exit__. This gives less confusing error messages when
both methods are missing. Patch by Jonathan Ellington.
- Issue #28746: Fix the set_inheritable() file descriptor method on platforms
that do not have the ioctl FIOCLEX and FIONCLEX commands.
......
......@@ -3133,15 +3133,15 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
_Py_IDENTIFIER(__exit__);
_Py_IDENTIFIER(__enter__);
PyObject *mgr = TOP();
PyObject *exit = special_lookup(mgr, &PyId___exit__), *enter;
PyObject *enter = special_lookup(mgr, &PyId___enter__), *exit;
PyObject *res;
if (enter == NULL)
goto error;
exit = special_lookup(mgr, &PyId___exit__);
if (exit == NULL)
goto error;
SET_TOP(exit);
enter = special_lookup(mgr, &PyId___enter__);
Py_DECREF(mgr);
if (enter == NULL)
goto error;
res = PyObject_CallFunctionObjArgs(enter, NULL);
Py_DECREF(enter);
if (res == NULL)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment