mirror of
https://github.com/python/cpython.git
synced 2025-08-04 00:48:58 +00:00
SF Bug #215126: Over restricted type checking on eval() function
The builtin eval() function now accepts any mapping for the locals argument. Time sensitive steps guarded by PyDict_CheckExact() to keep from slowing down the normal case. My timings so no measurable impact.
This commit is contained in:
parent
78bace7442
commit
214b1c3aae
9 changed files with 103 additions and 31 deletions
|
@ -3,7 +3,7 @@
|
|||
import test.test_support, unittest
|
||||
from test.test_support import fcmp, have_unicode, TESTFN, unlink
|
||||
|
||||
import sys, warnings, cStringIO, random
|
||||
import sys, warnings, cStringIO, random, UserDict
|
||||
warnings.filterwarnings("ignore", "hex../oct.. of negative int",
|
||||
FutureWarning, __name__)
|
||||
warnings.filterwarnings("ignore", "integer argument expected",
|
||||
|
@ -262,6 +262,60 @@ class BuiltinTest(unittest.TestCase):
|
|||
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
|
||||
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)
|
||||
|
||||
# Verify that dict subclasses work as well
|
||||
class D(dict):
|
||||
def __getitem__(self, key):
|
||||
if key == 'a':
|
||||
return 12
|
||||
return dict.__getitem__(self, key)
|
||||
def keys(self):
|
||||
return list('xyz')
|
||||
|
||||
d = D()
|
||||
self.assertEqual(eval('a', g, d), 12)
|
||||
self.assertRaises(NameError, eval, 'b', g, d)
|
||||
self.assertEqual(eval('dir()', g, d), list('xyz'))
|
||||
self.assertEqual(eval('globals()', g, d), g)
|
||||
self.assertEqual(eval('locals()', g, d), d)
|
||||
|
||||
# Verify locals stores (used by list comps)
|
||||
eval('[locals() for i in (2,3)]', g, d)
|
||||
eval('[locals() for i in (2,3)]', g, UserDict.UserDict())
|
||||
|
||||
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')
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue