summaryrefslogtreecommitdiffstats
path: root/Python
diff options
context:
space:
mode:
Diffstat (limited to 'Python')
-rw-r--r--Python/bltinmodule.c19
-rw-r--r--Python/ceval.c20
2 files changed, 29 insertions, 10 deletions
diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c
index b3c8b09..f4f8b7a 100644
--- a/Python/bltinmodule.c
+++ b/Python/bltinmodule.c
@@ -455,11 +455,17 @@ builtin_eval(PyObject *self, PyObject *args)
char *str;
PyCompilerFlags cf;
- if (!PyArg_ParseTuple(args, "O|O!O!:eval",
- &cmd,
- &PyDict_Type, &globals,
- &PyDict_Type, &locals))
+ if (!PyArg_UnpackTuple(args, "eval", 1, 3, &cmd, &globals, &locals))
return NULL;
+ if (locals != Py_None && !PyMapping_Check(locals)) {
+ PyErr_SetString(PyExc_TypeError, "locals must be a mapping");
+ return NULL;
+ }
+ if (globals != Py_None && !PyDict_Check(globals)) {
+ PyErr_SetString(PyExc_TypeError, PyMapping_Check(globals) ?
+ "globals must be a real dict; try eval(expr, {}, mapping)"
+ : "globals must be a dict");
+ }
if (globals == Py_None) {
globals = PyEval_GetGlobals();
if (locals == Py_None)
@@ -517,8 +523,9 @@ PyDoc_STRVAR(eval_doc,
Evaluate the source in the context of globals and locals.\n\
The source may be a string representing a Python expression\n\
or a code object as returned by compile().\n\
-The globals and locals are dictionaries, defaulting to the current\n\
-globals and locals. If only globals is given, locals defaults to it.");
+The globals must be a dictionary and locals can be any mappping,\n\
+defaulting to the current globals and locals.\n\
+If only globals is given, locals defaults to it.\n");
static PyObject *
diff --git a/Python/ceval.c b/Python/ceval.c
index ca7cea8..0c3a93d 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -1643,7 +1643,10 @@ PyEval_EvalFrame(PyFrameObject *f)
w = GETITEM(names, oparg);
v = POP();
if ((x = f->f_locals) != NULL) {
- err = PyDict_SetItem(x, w, v);
+ if (PyDict_CheckExact(v))
+ err = PyDict_SetItem(x, w, v);
+ else
+ err = PyObject_SetItem(x, w, v);
Py_DECREF(v);
if (err == 0) continue;
break;
@@ -1656,7 +1659,7 @@ PyEval_EvalFrame(PyFrameObject *f)
case DELETE_NAME:
w = GETITEM(names, oparg);
if ((x = f->f_locals) != NULL) {
- if ((err = PyDict_DelItem(x, w)) != 0)
+ if ((err = PyObject_DelItem(x, w)) != 0)
format_exc_check_arg(PyExc_NameError,
NAME_ERROR_MSG ,w);
break;
@@ -1733,13 +1736,22 @@ PyEval_EvalFrame(PyFrameObject *f)
case LOAD_NAME:
w = GETITEM(names, oparg);
- if ((x = f->f_locals) == NULL) {
+ if ((v = f->f_locals) == NULL) {
PyErr_Format(PyExc_SystemError,
"no locals when loading %s",
PyObject_REPR(w));
break;
}
- x = PyDict_GetItem(x, w);
+ if (PyDict_CheckExact(v))
+ x = PyDict_GetItem(v, w);
+ else {
+ x = PyObject_GetItem(v, w);
+ if (x == NULL && PyErr_Occurred()) {
+ if (!PyErr_ExceptionMatches(PyExc_KeyError))
+ break;
+ PyErr_Clear();
+ }
+ }
if (x == NULL) {
x = PyDict_GetItem(f->f_globals, w);
if (x == NULL) {