[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
- Misc/NEWS.d/next/Core and Builtins
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, |