Skip to content

Commit e653369

Browse files
authored
[3.8] bpo-35975: Only use cf_feature_version if PyCF_ONLY_AST in cf_flags (#21023)
1 parent 749d3bc commit e653369

File tree

5 files changed

+29
-3
lines changed

5 files changed

+29
-3
lines changed

Lib/test/test_capi.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -584,6 +584,26 @@ def test_subinterps(self):
584584
self.assertNotEqual(pickle.load(f), id(sys.modules))
585585
self.assertNotEqual(pickle.load(f), id(builtins))
586586

587+
def test_subinterps_recent_language_features(self):
588+
r, w = os.pipe()
589+
code = """if 1:
590+
import pickle
591+
with open({:d}, "wb") as f:
592+
593+
def noop(x): return x
594+
595+
a = (b := f'1{{2}}3') + noop('x') # Py 3.8 (:=) / 3.6 (f'')
596+
597+
async def foo(arg): return await arg # Py 3.5
598+
599+
pickle.dump(dict(a=a, b=b), f)
600+
""".format(w)
601+
602+
with open(r, "rb") as f:
603+
ret = support.run_in_subinterp(code)
604+
self.assertEqual(ret, 0)
605+
self.assertEqual(pickle.load(f), {'a': '123x', 'b': '123'})
606+
587607
def test_mutate_exception(self):
588608
"""
589609
Exceptions saved in global module state get shared between
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Stefan Behnel reported that cf_feature_version is used even when
2+
PyCF_ONLY_AST is not set. This is against the intention and against the
3+
documented behavior, so it's been fixed.

Modules/_testcapimodule.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3345,6 +3345,8 @@ run_in_subinterp(PyObject *self, PyObject *args)
33453345
const char *code;
33463346
int r;
33473347
PyThreadState *substate, *mainstate;
3348+
/* only initialise 'cflags.cf_flags' to test backwards compatibility */
3349+
PyCompilerFlags cflags = {0};
33483350

33493351
if (!PyArg_ParseTuple(args, "s:run_in_subinterp",
33503352
&code))
@@ -3363,7 +3365,7 @@ run_in_subinterp(PyObject *self, PyObject *args)
33633365
PyErr_SetString(PyExc_RuntimeError, "sub-interpreter creation failed");
33643366
return NULL;
33653367
}
3366-
r = PyRun_SimpleString(code);
3368+
r = PyRun_SimpleStringFlags(code, &cflags);
33673369
Py_EndInterpreter(substate);
33683370

33693371
PyThreadState_Swap(mainstate);

Python/ast.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -808,7 +808,8 @@ PyAST_FromNodeObject(const node *n, PyCompilerFlags *flags,
808808
/* borrowed reference */
809809
c.c_filename = filename;
810810
c.c_normalize = NULL;
811-
c.c_feature_version = flags ? flags->cf_feature_version : PY_MINOR_VERSION;
811+
c.c_feature_version = flags && (flags->cf_flags & PyCF_ONLY_AST) ?
812+
flags->cf_feature_version : PY_MINOR_VERSION;
812813

813814
if (TYPE(n) == encoding_decl)
814815
n = CHILD(n, 0);

Python/pythonrun.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1337,7 +1337,7 @@ PyParser_ASTFromStringObject(const char *s, PyObject *filename, int start,
13371337
PyCompilerFlags localflags = _PyCompilerFlags_INIT;
13381338
perrdetail err;
13391339
int iflags = PARSER_FLAGS(flags);
1340-
if (flags && flags->cf_feature_version < 7)
1340+
if (flags && (flags->cf_flags & PyCF_ONLY_AST) && flags->cf_feature_version < 7)
13411341
iflags |= PyPARSE_ASYNC_HACKS;
13421342

13431343
node *n = PyParser_ParseStringObject(s, filename,

0 commit comments

Comments
 (0)