Index: Lib/test/test_builtin.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_builtin.py,v retrieving revision 1.29 diff -c -r1.29 test_builtin.py *** Lib/test/test_builtin.py 12 Feb 2004 17:35:11 -0000 1.29 --- Lib/test/test_builtin.py 27 Jun 2004 09:17:52 -0000 *************** *** 262,267 **** --- 262,301 ---- self.assertRaises(TypeError, eval) self.assertRaises(TypeError, eval, ()) + def test_general_eval(self): + # Tests that general mappings can be used for the locals argument + + class M: + "Test mapping interface versus possible calls from eval()." + def __getitem__(self, key): + if key == 'a': + return 12 + raise KeyError ## why isn't this a name error + def keys(self): + return list('xyz') + + m = M() + g = globals() + self.assertEqual(eval('a', g, m), 12) + self.assertRaises(NameError, eval, 'b', g, m) + self.assertEqual(eval('dir()', g, m), list('xyz')) + self.assertEqual(eval('globals()', g, m), g) + self.assertEqual(eval('locals()', g, m), m) + + class SpreadSheet: + "Sample application showing nested, calculated lookups." + _cells = {} + def __setitem__(self, key, formula): + self._cells[key] = formula + def __getitem__(self, key ): + return eval(self._cells[key], globals(), self) + + ss = SpreadSheet() + ss['a1'] = '5' + ss['a2'] = 'a1*6' + ss['a3'] = 'a2*7' + self.assertEqual(ss['a3'], 210) + # Done outside of the method test_z to get the correct scope z = 0 f = open(TESTFN, 'w') Index: Python/bltinmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/bltinmodule.c,v retrieving revision 2.309 diff -c -r2.309 bltinmodule.c *** Python/bltinmodule.c 29 Mar 2004 11:50:55 -0000 2.309 --- Python/bltinmodule.c 27 Jun 2004 09:17:54 -0000 *************** *** 455,465 **** char *str; PyCompilerFlags cf; ! if (!PyArg_ParseTuple(args, "O|O!O!:eval", &cmd, &PyDict_Type, &globals, ! &PyDict_Type, &locals)) return NULL; if (globals == Py_None) { globals = PyEval_GetGlobals(); if (locals == Py_None) --- 455,469 ---- char *str; PyCompilerFlags cf; ! if (!PyArg_ParseTuple(args, "O|O!O:eval", &cmd, &PyDict_Type, &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) { globals = PyEval_GetGlobals(); if (locals == Py_None) Index: Python/ceval.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/ceval.c,v retrieving revision 2.406 diff -c -r2.406 ceval.c *** Python/ceval.c 26 Jun 2004 04:34:33 -0000 2.406 --- Python/ceval.c 27 Jun 2004 09:17:56 -0000 *************** *** 1735,1748 **** case LOAD_NAME: w = GETITEM(names, oparg); ! if ((x = f->f_locals) == NULL) { PyErr_Format(PyExc_SystemError, "no locals when loading %s", PyObject_REPR(w)); break; } ! x = PyDict_GetItem(x, w); if (x == NULL) { x = PyDict_GetItem(f->f_globals, w); if (x == NULL) { x = PyDict_GetItem(f->f_builtins, w); --- 1735,1756 ---- case LOAD_NAME: w = GETITEM(names, oparg); ! if ((v = f->f_locals) == NULL) { PyErr_Format(PyExc_SystemError, "no locals when loading %s", PyObject_REPR(w)); break; } ! x = PyDict_GetItem(v, w); if (x == NULL) { + if (!PyDict_Check(v)) { + x = PyObject_GetItem(v, w); + if (x != NULL) { + PUSH(x); + continue; + } + PyErr_Clear(); + } x = PyDict_GetItem(f->f_globals, w); if (x == NULL) { x = PyDict_GetItem(f->f_builtins, w); Index: Objects/frameobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/frameobject.c,v retrieving revision 2.78 diff -c -r2.78 frameobject.c *** Objects/frameobject.c 20 Mar 2004 21:10:27 -0000 2.78 --- Objects/frameobject.c 27 Jun 2004 09:17:56 -0000 *************** *** 544,550 **** #ifdef Py_DEBUG if (code == NULL || globals == NULL || !PyDict_Check(globals) || ! (locals != NULL && !PyDict_Check(locals))) { PyErr_BadInternalCall(); return NULL; } --- 544,550 ---- #ifdef Py_DEBUG if (code == NULL || globals == NULL || !PyDict_Check(globals) || ! (locals != NULL && !PyMapping_Check(locals))) { PyErr_BadInternalCall(); return NULL; } Index: Objects/object.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/object.c,v retrieving revision 2.217 diff -c -r2.217 object.c *** Objects/object.c 22 Apr 2004 17:23:49 -0000 2.217 --- Objects/object.c 27 Jun 2004 09:17:56 -0000 *************** *** 1621,1627 **** PyObject *locals = PyEval_GetLocals(); if (locals == NULL) goto error; ! result = PyDict_Keys(locals); if (result == NULL) goto error; } --- 1621,1627 ---- PyObject *locals = PyEval_GetLocals(); if (locals == NULL) goto error; ! result = PyMapping_Keys(locals); if (result == NULL) goto error; }