[Python-checkins] [3.8] bpo-35975: Only use cf_feature_version if PyCF_ONLY_AST in cf_flags (#21023)

Guido van Rossum webhook-mailer at python.org
Sat Jun 27 20:35:09 EDT 2020


https://github.com/python/cpython/commit/e653369e76d7da6bcbcf1f09a141f47fb77df6c3
commit: e653369e76d7da6bcbcf1f09a141f47fb77df6c3
branch: 3.8
author: Guido van Rossum <guido at python.org>
committer: GitHub <noreply at github.com>
date: 2020-06-27T17:35:05-07:00
summary:

[3.8] bpo-35975: Only use cf_feature_version if PyCF_ONLY_AST in cf_flags (#21023)

files:
A Misc/NEWS.d/next/Core and Builtins/2020-06-20-17-21-07.bpo-35975.UDHCHp.rst
M Lib/test/test_capi.py
M Modules/_testcapimodule.c
M Python/ast.c
M Python/pythonrun.c

diff --git a/Lib/test/test_capi.py b/Lib/test/test_capi.py
index 584c104645031..d1506bc17732f 100644
--- a/Lib/test/test_capi.py
+++ b/Lib/test/test_capi.py
@@ -584,6 +584,26 @@ def test_subinterps(self):
             self.assertNotEqual(pickle.load(f), id(sys.modules))
             self.assertNotEqual(pickle.load(f), id(builtins))
 
+    def test_subinterps_recent_language_features(self):
+        r, w = os.pipe()
+        code = """if 1:
+            import pickle
+            with open({:d}, "wb") as f:
+
+                def noop(x): return x
+
+                a = (b := f'1{{2}}3') + noop('x')  # Py 3.8 (:=) / 3.6 (f'')
+
+                async def foo(arg): return await arg  # Py 3.5
+
+                pickle.dump(dict(a=a, b=b), f)
+            """.format(w)
+
+        with open(r, "rb") as f:
+            ret = support.run_in_subinterp(code)
+            self.assertEqual(ret, 0)
+            self.assertEqual(pickle.load(f), {'a': '123x', 'b': '123'})
+
     def test_mutate_exception(self):
         """
         Exceptions saved in global module state get shared between
diff --git a/Misc/NEWS.d/next/Core and Builtins/2020-06-20-17-21-07.bpo-35975.UDHCHp.rst b/Misc/NEWS.d/next/Core and Builtins/2020-06-20-17-21-07.bpo-35975.UDHCHp.rst
new file mode 100644
index 0000000000000..73f4a6da2e5c0
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2020-06-20-17-21-07.bpo-35975.UDHCHp.rst	
@@ -0,0 +1,3 @@
+Stefan Behnel reported that cf_feature_version is used even when
+PyCF_ONLY_AST is not set. This is against the intention and against the
+documented behavior, so it's been fixed.
diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c
index da3579c2cc6fd..f74756163f863 100644
--- a/Modules/_testcapimodule.c
+++ b/Modules/_testcapimodule.c
@@ -3345,6 +3345,8 @@ run_in_subinterp(PyObject *self, PyObject *args)
     const char *code;
     int r;
     PyThreadState *substate, *mainstate;
+    /* only initialise 'cflags.cf_flags' to test backwards compatibility */
+    PyCompilerFlags cflags = {0};
 
     if (!PyArg_ParseTuple(args, "s:run_in_subinterp",
                           &code))
@@ -3363,7 +3365,7 @@ run_in_subinterp(PyObject *self, PyObject *args)
         PyErr_SetString(PyExc_RuntimeError, "sub-interpreter creation failed");
         return NULL;
     }
-    r = PyRun_SimpleString(code);
+    r = PyRun_SimpleStringFlags(code, &cflags);
     Py_EndInterpreter(substate);
 
     PyThreadState_Swap(mainstate);
diff --git a/Python/ast.c b/Python/ast.c
index 5efb690c299ca..7c1d24dea7184 100644
--- a/Python/ast.c
+++ b/Python/ast.c
@@ -808,7 +808,8 @@ PyAST_FromNodeObject(const node *n, PyCompilerFlags *flags,
     /* borrowed reference */
     c.c_filename = filename;
     c.c_normalize = NULL;
-    c.c_feature_version = flags ? flags->cf_feature_version : PY_MINOR_VERSION;
+    c.c_feature_version = flags && (flags->cf_flags & PyCF_ONLY_AST) ?
+        flags->cf_feature_version : PY_MINOR_VERSION;
 
     if (TYPE(n) == encoding_decl)
         n = CHILD(n, 0);
diff --git a/Python/pythonrun.c b/Python/pythonrun.c
index a7da143077a7a..6cdd8ea7a6ab1 100644
--- a/Python/pythonrun.c
+++ b/Python/pythonrun.c
@@ -1337,7 +1337,7 @@ PyParser_ASTFromStringObject(const char *s, PyObject *filename, int start,
     PyCompilerFlags localflags = _PyCompilerFlags_INIT;
     perrdetail err;
     int iflags = PARSER_FLAGS(flags);
-    if (flags && flags->cf_feature_version < 7)
+    if (flags && (flags->cf_flags & PyCF_ONLY_AST) && flags->cf_feature_version < 7)
         iflags |= PyPARSE_ASYNC_HACKS;
 
     node *n = PyParser_ParseStringObject(s, filename,



More information about the Python-checkins mailing list