Skip to content

Commit 2a1ee1d

Browse files
authored
[3.9] bpo-35975: Only use cf_feature_version if PyCF_ONLY_AST in cf_flags (#21022)
1 parent dab533d commit 2a1ee1d

File tree

6 files changed

+33
-5
lines changed

6 files changed

+33
-5
lines changed

‎Lib/test/test_capi.py‎

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -626,6 +626,27 @@ def test_subinterps(self):
626626
self.assertNotEqual(pickle.load(f), id(sys.modules))
627627
self.assertNotEqual(pickle.load(f), id(builtins))
628628

629+
def test_subinterps_recent_language_features(self):
630+
r, w = os.pipe()
631+
code = """if 1:
632+
import pickle
633+
with open({:d}, "wb") as f:
634+
635+
@(lambda x:x) # Py 3.9
636+
def noop(x): return x
637+
638+
a = (b := f'1{{2}}3') + noop('x') # Py 3.8 (:=) / 3.6 (f'')
639+
640+
async def foo(arg): return await arg # Py 3.5
641+
642+
pickle.dump(dict(a=a, b=b), f)
643+
""".format(w)
644+
645+
with open(r, "rb") as f:
646+
ret = support.run_in_subinterp(code)
647+
self.assertEqual(ret, 0)
648+
self.assertEqual(pickle.load(f), {'a': '123x', 'b': '123'})
649+
629650
def test_mutate_exception(self):
630651
"""
631652
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
@@ -3468,6 +3468,8 @@ run_in_subinterp(PyObject *self, PyObject *args)
34683468
const char *code;
34693469
int r;
34703470
PyThreadState *substate, *mainstate;
3471+
/* only initialise 'cflags.cf_flags' to test backwards compatibility */
3472+
PyCompilerFlags cflags = {0};
34713473

34723474
if (!PyArg_ParseTuple(args, "s:run_in_subinterp",
34733475
&code))
@@ -3486,7 +3488,7 @@ run_in_subinterp(PyObject *self, PyObject *args)
34863488
PyErr_SetString(PyExc_RuntimeError, "sub-interpreter creation failed");
34873489
return NULL;
34883490
}
3489-
r = PyRun_SimpleString(code);
3491+
r = PyRun_SimpleStringFlags(code, &cflags);
34903492
Py_EndInterpreter(substate);
34913493

34923494
PyThreadState_Swap(mainstate);

‎Parser/pegen/pegen.c‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1041,7 +1041,7 @@ compute_parser_flags(PyCompilerFlags *flags)
10411041
if (flags->cf_flags & PyCF_TYPE_COMMENTS) {
10421042
parser_flags |= PyPARSE_TYPE_COMMENTS;
10431043
}
1044-
if (flags->cf_feature_version < 7) {
1044+
if ((flags->cf_flags & PyCF_ONLY_AST) && flags->cf_feature_version < 7) {
10451045
parser_flags |= PyPARSE_ASYNC_HACKS;
10461046
}
10471047
return parser_flags;
@@ -1214,7 +1214,8 @@ _PyPegen_run_parser_from_string(const char *str, int start_rule, PyObject *filen
12141214
mod_ty result = NULL;
12151215

12161216
int parser_flags = compute_parser_flags(flags);
1217-
int feature_version = flags ? flags->cf_feature_version : PY_MINOR_VERSION;
1217+
int feature_version = flags && (flags->cf_flags & PyCF_ONLY_AST) ?
1218+
flags->cf_feature_version : PY_MINOR_VERSION;
12181219
Parser *p = _PyPegen_Parser_New(tok, start_rule, parser_flags, feature_version,
12191220
NULL, arena);
12201221
if (p == NULL) {

‎Python/ast.c‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -777,7 +777,8 @@ PyAST_FromNodeObject(const node *n, PyCompilerFlags *flags,
777777
/* borrowed reference */
778778
c.c_filename = filename;
779779
c.c_normalize = NULL;
780-
c.c_feature_version = flags ? flags->cf_feature_version : PY_MINOR_VERSION;
780+
c.c_feature_version = flags && (flags->cf_flags & PyCF_ONLY_AST) ?
781+
flags->cf_feature_version : PY_MINOR_VERSION;
781782

782783
if (TYPE(n) == encoding_decl)
783784
n = CHILD(n, 0);

‎Python/pythonrun.c‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1402,7 +1402,7 @@ PyParser_ASTFromStringObject(const char *s, PyObject *filename, int start,
14021402
PyCompilerFlags localflags = _PyCompilerFlags_INIT;
14031403
perrdetail err;
14041404
int iflags = PARSER_FLAGS(flags);
1405-
if (flags && flags->cf_feature_version < 7)
1405+
if (flags && (flags->cf_flags & PyCF_ONLY_AST) && flags->cf_feature_version < 7)
14061406
iflags |= PyPARSE_ASYNC_HACKS;
14071407

14081408
node *n = PyParser_ParseStringObject(s, filename,

0 commit comments

Comments
 (0)