[3.8] bpo-35975: Only use cf_feature_version if PyCF_ONLY_AST in cf_f… · python/cpython@e653369 (original) (raw)

File tree

5 files changed

lines changed

5 files changed

lines changed

Original file line number Diff line number Diff line change
@@ -584,6 +584,26 @@ def test_subinterps(self):
584 584 self.assertNotEqual(pickle.load(f), id(sys.modules))
585 585 self.assertNotEqual(pickle.load(f), id(builtins))
586 586
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 +
587 607 def test_mutate_exception(self):
588 608 """
589 609 Exceptions saved in global module state get shared between
Original file line number Diff line number Diff 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.
Original file line number Diff line number Diff line change
@@ -3345,6 +3345,8 @@ run_in_subinterp(PyObject *self, PyObject *args)
3345 3345 const char *code;
3346 3346 int r;
3347 3347 PyThreadState *substate, *mainstate;
3348 +/* only initialise 'cflags.cf_flags' to test backwards compatibility */
3349 +PyCompilerFlags cflags = {0};
3348 3350
3349 3351 if (!PyArg_ParseTuple(args, "s:run_in_subinterp",
3350 3352 &code))
@@ -3363,7 +3365,7 @@ run_in_subinterp(PyObject *self, PyObject *args)
3363 3365 PyErr_SetString(PyExc_RuntimeError, "sub-interpreter creation failed");
3364 3366 return NULL;
3365 3367 }
3366 -r = PyRun_SimpleString(code);
3368 +r = PyRun_SimpleStringFlags(code, &cflags);
3367 3369 Py_EndInterpreter(substate);
3368 3370
3369 3371 PyThreadState_Swap(mainstate);
Original file line number Diff line number Diff line change
@@ -808,7 +808,8 @@ PyAST_FromNodeObject(const node *n, PyCompilerFlags *flags,
808 808 /* borrowed reference */
809 809 c.c_filename = filename;
810 810 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;
812 813
813 814 if (TYPE(n) == encoding_decl)
814 815 n = CHILD(n, 0);
Original file line number Diff line number Diff line change
@@ -1337,7 +1337,7 @@ PyParser_ASTFromStringObject(const char *s, PyObject *filename, int start,
1337 1337 PyCompilerFlags localflags = _PyCompilerFlags_INIT;
1338 1338 perrdetail err;
1339 1339 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)
1341 1341 iflags |= PyPARSE_ASYNC_HACKS;
1342 1342
1343 1343 node *n = PyParser_ParseStringObject(s, filename,