summaryrefslogtreecommitdiffstats
path: root/Python
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2021-06-29 08:27:04 (GMT)
committerGitHub <noreply@github.com>2021-06-29 08:27:04 (GMT)
commit20a88004bae8ead66a205a125e1fe979376fc3ea (patch)
tree6b8007ba8c981cfdb52cc0a674e0491588ab50e0 /Python
parent48e3a1d95aee013974121fcafe19816c0e9a41da (diff)
downloadcpython-20a88004bae8ead66a205a125e1fe979376fc3ea.zip
cpython-20a88004bae8ead66a205a125e1fe979376fc3ea.tar.gz
cpython-20a88004bae8ead66a205a125e1fe979376fc3ea.tar.bz2
bpo-12022: Change error type for bad objects in "with" and "async with" (GH-26809)
A TypeError is now raised instead of an AttributeError in "with" and "async with" statements for objects which do not support the context manager or asynchronous context manager protocols correspondingly.
Diffstat (limited to 'Python')
-rw-r--r--Python/ceval.c48
1 files changed, 30 insertions, 18 deletions
diff --git a/Python/ceval.c b/Python/ceval.c
index 3f961f6..2ae36b3 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -82,7 +82,6 @@ static void format_exc_check_arg(PyThreadState *, PyObject *, const char *, PyOb
static void format_exc_unbound(PyThreadState *tstate, PyCodeObject *co, int oparg);
static PyObject * unicode_concatenate(PyThreadState *, PyObject *, PyObject *,
PyFrameObject *, const _Py_CODEUNIT *);
-static PyObject * special_lookup(PyThreadState *, PyObject *, _Py_Identifier *);
static int check_args_iterable(PyThreadState *, PyObject *func, PyObject *vararg);
static void format_kwargs_error(PyThreadState *, PyObject *func, PyObject *kwargs);
static void format_awaitable_error(PyThreadState *, PyTypeObject *, int, int);
@@ -3844,13 +3843,26 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
_Py_IDENTIFIER(__aenter__);
_Py_IDENTIFIER(__aexit__);
PyObject *mgr = TOP();
- PyObject *enter = special_lookup(tstate, mgr, &PyId___aenter__);
PyObject *res;
+ PyObject *enter = _PyObject_LookupSpecial(mgr, &PyId___aenter__);
if (enter == NULL) {
+ if (!_PyErr_Occurred(tstate)) {
+ _PyErr_Format(tstate, PyExc_TypeError,
+ "'%.200s' object does not support the "
+ "asynchronous context manager protocol",
+ Py_TYPE(mgr)->tp_name);
+ }
goto error;
}
- PyObject *exit = special_lookup(tstate, mgr, &PyId___aexit__);
+ PyObject *exit = _PyObject_LookupSpecial(mgr, &PyId___aexit__);
if (exit == NULL) {
+ if (!_PyErr_Occurred(tstate)) {
+ _PyErr_Format(tstate, PyExc_TypeError,
+ "'%.200s' object does not support the "
+ "asynchronous context manager protocol "
+ "(missed __aexit__ method)",
+ Py_TYPE(mgr)->tp_name);
+ }
Py_DECREF(enter);
goto error;
}
@@ -3869,13 +3881,26 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
_Py_IDENTIFIER(__enter__);
_Py_IDENTIFIER(__exit__);
PyObject *mgr = TOP();
- PyObject *enter = special_lookup(tstate, mgr, &PyId___enter__);
PyObject *res;
+ PyObject *enter = _PyObject_LookupSpecial(mgr, &PyId___enter__);
if (enter == NULL) {
+ if (!_PyErr_Occurred(tstate)) {
+ _PyErr_Format(tstate, PyExc_TypeError,
+ "'%.200s' object does not support the "
+ "context manager protocol",
+ Py_TYPE(mgr)->tp_name);
+ }
goto error;
}
- PyObject *exit = special_lookup(tstate, mgr, &PyId___exit__);
+ PyObject *exit = _PyObject_LookupSpecial(mgr, &PyId___exit__);
if (exit == NULL) {
+ if (!_PyErr_Occurred(tstate)) {
+ _PyErr_Format(tstate, PyExc_TypeError,
+ "'%.200s' object does not support the "
+ "context manager protocol "
+ "(missed __exit__ method)",
+ Py_TYPE(mgr)->tp_name);
+ }
Py_DECREF(enter);
goto error;
}
@@ -5110,19 +5135,6 @@ fail:
}
-static PyObject *
-special_lookup(PyThreadState *tstate, PyObject *o, _Py_Identifier *id)
-{
- PyObject *res;
- res = _PyObject_LookupSpecial(o, id);
- if (res == NULL && !_PyErr_Occurred(tstate)) {
- _PyErr_SetObject(tstate, PyExc_AttributeError, _PyUnicode_FromId(id));
- return NULL;
- }
- return res;
-}
-
-
/* Logic for the raise statement (too complicated for inlining).
This *consumes* a reference count to each of its arguments. */
static int