mirror of
https://github.com/python/cpython.git
synced 2025-08-03 16:39:00 +00:00
[3.9] bpo-35975: Only use cf_feature_version if PyCF_ONLY_AST in cf_flags (#21022)
This commit is contained in:
parent
dab533d0ee
commit
2a1ee1d970
6 changed files with 33 additions and 5 deletions
|
@ -626,6 +626,27 @@ class SubinterpreterTest(unittest.TestCase):
|
||||||
self.assertNotEqual(pickle.load(f), id(sys.modules))
|
self.assertNotEqual(pickle.load(f), id(sys.modules))
|
||||||
self.assertNotEqual(pickle.load(f), id(builtins))
|
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:
|
||||||
|
|
||||||
|
@(lambda x:x) # Py 3.9
|
||||||
|
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):
|
def test_mutate_exception(self):
|
||||||
"""
|
"""
|
||||||
Exceptions saved in global module state get shared between
|
Exceptions saved in global module state get shared between
|
||||||
|
|
|
@ -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.
|
|
@ -3468,6 +3468,8 @@ run_in_subinterp(PyObject *self, PyObject *args)
|
||||||
const char *code;
|
const char *code;
|
||||||
int r;
|
int r;
|
||||||
PyThreadState *substate, *mainstate;
|
PyThreadState *substate, *mainstate;
|
||||||
|
/* only initialise 'cflags.cf_flags' to test backwards compatibility */
|
||||||
|
PyCompilerFlags cflags = {0};
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "s:run_in_subinterp",
|
if (!PyArg_ParseTuple(args, "s:run_in_subinterp",
|
||||||
&code))
|
&code))
|
||||||
|
@ -3486,7 +3488,7 @@ run_in_subinterp(PyObject *self, PyObject *args)
|
||||||
PyErr_SetString(PyExc_RuntimeError, "sub-interpreter creation failed");
|
PyErr_SetString(PyExc_RuntimeError, "sub-interpreter creation failed");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
r = PyRun_SimpleString(code);
|
r = PyRun_SimpleStringFlags(code, &cflags);
|
||||||
Py_EndInterpreter(substate);
|
Py_EndInterpreter(substate);
|
||||||
|
|
||||||
PyThreadState_Swap(mainstate);
|
PyThreadState_Swap(mainstate);
|
||||||
|
|
|
@ -1041,7 +1041,7 @@ compute_parser_flags(PyCompilerFlags *flags)
|
||||||
if (flags->cf_flags & PyCF_TYPE_COMMENTS) {
|
if (flags->cf_flags & PyCF_TYPE_COMMENTS) {
|
||||||
parser_flags |= PyPARSE_TYPE_COMMENTS;
|
parser_flags |= PyPARSE_TYPE_COMMENTS;
|
||||||
}
|
}
|
||||||
if (flags->cf_feature_version < 7) {
|
if ((flags->cf_flags & PyCF_ONLY_AST) && flags->cf_feature_version < 7) {
|
||||||
parser_flags |= PyPARSE_ASYNC_HACKS;
|
parser_flags |= PyPARSE_ASYNC_HACKS;
|
||||||
}
|
}
|
||||||
return parser_flags;
|
return parser_flags;
|
||||||
|
@ -1214,7 +1214,8 @@ _PyPegen_run_parser_from_string(const char *str, int start_rule, PyObject *filen
|
||||||
mod_ty result = NULL;
|
mod_ty result = NULL;
|
||||||
|
|
||||||
int parser_flags = compute_parser_flags(flags);
|
int parser_flags = compute_parser_flags(flags);
|
||||||
int feature_version = flags ? flags->cf_feature_version : PY_MINOR_VERSION;
|
int feature_version = flags && (flags->cf_flags & PyCF_ONLY_AST) ?
|
||||||
|
flags->cf_feature_version : PY_MINOR_VERSION;
|
||||||
Parser *p = _PyPegen_Parser_New(tok, start_rule, parser_flags, feature_version,
|
Parser *p = _PyPegen_Parser_New(tok, start_rule, parser_flags, feature_version,
|
||||||
NULL, arena);
|
NULL, arena);
|
||||||
if (p == NULL) {
|
if (p == NULL) {
|
||||||
|
|
|
@ -777,7 +777,8 @@ PyAST_FromNodeObject(const node *n, PyCompilerFlags *flags,
|
||||||
/* borrowed reference */
|
/* borrowed reference */
|
||||||
c.c_filename = filename;
|
c.c_filename = filename;
|
||||||
c.c_normalize = NULL;
|
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)
|
if (TYPE(n) == encoding_decl)
|
||||||
n = CHILD(n, 0);
|
n = CHILD(n, 0);
|
||||||
|
|
|
@ -1402,7 +1402,7 @@ PyParser_ASTFromStringObject(const char *s, PyObject *filename, int start,
|
||||||
PyCompilerFlags localflags = _PyCompilerFlags_INIT;
|
PyCompilerFlags localflags = _PyCompilerFlags_INIT;
|
||||||
perrdetail err;
|
perrdetail err;
|
||||||
int iflags = PARSER_FLAGS(flags);
|
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;
|
iflags |= PyPARSE_ASYNC_HACKS;
|
||||||
|
|
||||||
node *n = PyParser_ParseStringObject(s, filename,
|
node *n = PyParser_ParseStringObject(s, filename,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue