Skip to content

Commit 1137510

Browse files
committed
added unit tests
1 parent daa2008 commit 1137510

File tree

3 files changed

+28
-20
lines changed

3 files changed

+28
-20
lines changed

Lib/test/test_builtin.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1111,7 +1111,22 @@ def test_exec_filter_syntax_warnings_by_module(self):
11111111
self.assertEqual(wm.filename, '<string>')
11121112
self.assertIs(wm.category, SyntaxWarning)
11131113

1114-
1114+
def test_eval_exec_sync_fast_locals(self):
1115+
def func_assign():
1116+
a = 1
1117+
1118+
def func_read():
1119+
b = a + 1
1120+
1121+
for executor in eval, exec:
1122+
with self.subTest(executor=executor.__name__):
1123+
ns = {}
1124+
executor(func_assign.__code__, {}, ns, sync_fast_locals=True)
1125+
self.assertEqual(ns, {'a': 1})
1126+
ns = {'a': 1}
1127+
executor(func_read.__code__, {}, ns, sync_fast_locals=True)
1128+
self.assertEqual(ns, {'a': 1, 'b': 2})
1129+
11151130
def test_filter(self):
11161131
self.assertEqual(list(filter(lambda c: 'a' <= c <= 'z', 'Hello World')), list('elloorld'))
11171132
self.assertEqual(list(filter(None, [1, 'hello', [], [3], '', None, 9, 0])), [1, 'hello', [3], 9])

Python/bltinmodule.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1041,7 +1041,7 @@ builtin_eval_impl(PyObject *module, PyObject *source, PyObject *globals,
10411041
}
10421042
if (!sync_fast_locals && ((PyCodeObject *)source)->co_flags & CO_OPTIMIZED) {
10431043
Py_DECREF(locals);
1044-
locals = NULL;
1044+
locals = globals;
10451045
}
10461046
result = PyEval_EvalCode(source, globals, locals);
10471047
}

Python/ceval.c

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1530,7 +1530,7 @@ typedef struct {
15301530
} _PyEntryFrame;
15311531

15321532
static int
1533-
_PyEval_SyncMappingToFast(_PyInterpreterFrame *frame)
1533+
_PyEval_SyncLocalsToFast(_PyInterpreterFrame *frame)
15341534
{
15351535
PyObject *mapping = frame->f_locals;
15361536
PyCodeObject *co = _PyFrame_GetCode(frame);
@@ -1543,14 +1543,14 @@ _PyEval_SyncMappingToFast(_PyInterpreterFrame *frame)
15431543
frame->localsplus[i] = PyStackRef_FromPyObjectSteal(value);
15441544
}
15451545
else {
1546-
PyErr_Clear();
1546+
return -1;
15471547
}
15481548
}
15491549
return 0;
15501550
}
15511551

15521552
static int
1553-
_PyEval_SyncFastToMapping(_PyInterpreterFrame *frame)
1553+
_PyEval_SyncFastToLocals(_PyInterpreterFrame *frame)
15541554
{
15551555
PyObject *mapping = frame->f_locals;
15561556
PyCodeObject *co = _PyFrame_GetCode(frame);
@@ -1562,7 +1562,7 @@ _PyEval_SyncFastToMapping(_PyInterpreterFrame *frame)
15621562
PyObject *name = PyTuple_GET_ITEM(names, i);
15631563
PyObject *obj = PyStackRef_AsPyObjectSteal(sref);
15641564
if (PyObject_SetItem(mapping, name, obj) < 0) {
1565-
PyErr_Clear();
1565+
return -1;
15661566
}
15671567
}
15681568
}
@@ -1632,13 +1632,9 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
16321632
tstate->current_frame = frame;
16331633
entry.frame.localsplus[0] = PyStackRef_NULL;
16341634
PyCodeObject *co = _PyFrame_GetCode(frame);
1635-
if ((co->co_flags & CO_OPTIMIZED) &&
1636-
frame->f_locals != NULL &&
1637-
frame->f_locals != frame->f_globals)
1638-
{
1639-
if (_PyEval_SyncMappingToFast(frame) < 0) {
1640-
goto early_exit;
1641-
}
1635+
if ((co->co_flags & CO_OPTIMIZED) && frame->f_locals != NULL &&
1636+
frame->f_locals != frame->f_globals && _PyEval_SyncLocalsToFast(frame) < 0) {
1637+
goto early_exit;
16421638
}
16431639
#ifdef _Py_TIER2
16441640
if (tstate->current_executor != NULL) {
@@ -2427,13 +2423,10 @@ void
24272423
_PyEval_FrameClearAndPop(PyThreadState *tstate, _PyInterpreterFrame * frame)
24282424
{
24292425
PyCodeObject *co = _PyFrame_GetCode(frame);
2430-
if ((co->co_flags & CO_OPTIMIZED) &&
2431-
frame->f_locals != NULL &&
2432-
frame->f_locals != frame->f_globals)
2433-
{
2434-
if (_PyEval_SyncFastToMapping(frame) < 0) {
2435-
PyErr_WriteUnraisable(frame->f_locals);
2436-
}
2426+
if ((co->co_flags & CO_OPTIMIZED) && frame->f_locals != NULL &&
2427+
frame->f_locals != frame->f_globals && _PyEval_SyncFastToLocals(frame) < 0) {
2428+
/* Swallow the error while the frame is in a teardown state */
2429+
PyErr_WriteUnraisable(frame->f_locals);
24372430
}
24382431
// Update last_profiled_frame for remote profiler frame caching.
24392432
// By this point, tstate->current_frame is already set to the parent frame.

0 commit comments

Comments
 (0)