Skip to content

Commit c4368ef

Browse files
committed
Add support for keyword arguments to eval and exec (python#105879)
1 parent 34e93d3 commit c4368ef

File tree

3 files changed

+82
-28
lines changed

3 files changed

+82
-28
lines changed

Lib/test/test_builtin.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@
4646
x, y = 1e16, 2.9999 # use temporary values to defeat peephole optimizer
4747
HAVE_DOUBLE_ROUNDING = (x + y == 1e16 + 4)
4848

49+
# used as proof of globals being used
50+
A_GLOBAL_VALUE = 123
4951

5052
class Squares:
5153

@@ -643,6 +645,11 @@ def __getitem__(self, key):
643645
raise ValueError
644646
self.assertRaises(ValueError, eval, "foo", {}, X())
645647

648+
def test_eval_kwargs(self):
649+
data = {"A_GLOBAL_VALUE": 456}
650+
self.assertEqual(eval("globals()['A_GLOBAL_VALUE']", globals=data), 456)
651+
self.assertEqual(eval("globals()['A_GLOBAL_VALUE']", locals=data), 123)
652+
646653
def test_general_eval(self):
647654
# Tests that general mappings can be used for the locals argument
648655

@@ -736,6 +743,19 @@ def test_exec(self):
736743
del l['__builtins__']
737744
self.assertEqual((g, l), ({'a': 1}, {'b': 2}))
738745

746+
def test_exec_kwargs(self):
747+
g = {}
748+
exec('global z\nz = 1', globals=g)
749+
if '__builtins__' in g:
750+
del g['__builtins__']
751+
self.assertEqual(g, {'z': 1})
752+
753+
# if we only set locals, the global assignment will not
754+
# reach this locals dictionary
755+
g = {}
756+
exec('global z\nz = 1', locals=g)
757+
self.assertEqual(g, {})
758+
739759
def test_exec_globals(self):
740760
code = compile("print('Hello World!')", "", "exec")
741761
# no builtin function

Python/bltinmodule.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -891,7 +891,6 @@ eval as builtin_eval
891891
source: object
892892
globals: object = None
893893
locals: object = None
894-
/
895894
896895
Evaluate the given source in the context of globals and locals.
897896
@@ -905,7 +904,7 @@ If only globals is given, locals defaults to it.
905904
static PyObject *
906905
builtin_eval_impl(PyObject *module, PyObject *source, PyObject *globals,
907906
PyObject *locals)
908-
/*[clinic end generated code: output=0a0824aa70093116 input=11ee718a8640e527]*/
907+
/*[clinic end generated code: output=0a0824aa70093116 input=4cbfb23dd7cbe2a9]*/
909908
{
910909
PyObject *result, *source_copy;
911910
const char *str;
@@ -980,7 +979,6 @@ exec as builtin_exec
980979
source: object
981980
globals: object = None
982981
locals: object = None
983-
/
984982
*
985983
closure: object(c_default="NULL") = None
986984
@@ -998,11 +996,12 @@ when source is a code object requiring exactly that many cellvars.
998996
static PyObject *
999997
builtin_exec_impl(PyObject *module, PyObject *source, PyObject *globals,
1000998
PyObject *locals, PyObject *closure)
1001-
/*[clinic end generated code: output=7579eb4e7646743d input=f13a7e2b503d1d9a]*/
999+
/*[clinic end generated code: output=7579eb4e7646743d input=99951d1832fece9e]*/
10021000
{
10031001
PyObject *v;
10041002

10051003
if (globals == Py_None) {
1004+
10061005
globals = PyEval_GetGlobals();
10071006
if (locals == Py_None) {
10081007
locals = PyEval_GetLocals();

Python/clinic/bltinmodule.c.h

Lines changed: 59 additions & 24 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)