From 8615f3bac3d18aaac9f125fd1bb836103df23db8 Mon Sep 17 00:00:00 2001 From: Pablo Galindo Salgado Date: Tue, 16 Nov 2021 20:30:47 +0000 Subject: [PATCH] bpo-45822: Respect PEP 263's coding cookies in the parser even if flags are not provided (GH-29582) (cherry picked from commit da20d7401de97b425897d3069f71f77b039eb16f) --- Lib/test/test_capi.py | 8 ++++++++ .../2021-11-16-19-41-04.bpo-45822.OT6ueS.rst | 2 ++ Modules/_testcapimodule.c | 14 ++++++++++++++ Parser/pegen/pegen.c | 2 +- 4 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2021-11-16-19-41-04.bpo-45822.OT6ueS.rst diff --git a/Lib/test/test_capi.py b/Lib/test/test_capi.py index 6b2fe2f1580c36..23e65df67190c0 100644 --- a/Lib/test/test_capi.py +++ b/Lib/test/test_capi.py @@ -926,6 +926,14 @@ def test_state_access(self): with self.assertRaises(TypeError): increment_count(1, 2, 3) + def test_Py_CompileString(self): + # Check that Py_CompileString respects the coding cookie + _compile = _testcapi.Py_CompileString + code = b"# -*- coding: latin1 -*-\nprint('\xc2\xa4')\n" + result = _compile(code) + expected = compile(code, "", "exec") + self.assertEqual(result.co_consts, expected.co_consts) + if __name__ == "__main__": unittest.main() diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-11-16-19-41-04.bpo-45822.OT6ueS.rst b/Misc/NEWS.d/next/Core and Builtins/2021-11-16-19-41-04.bpo-45822.OT6ueS.rst new file mode 100644 index 00000000000000..1ac7a8becee40d --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-11-16-19-41-04.bpo-45822.OT6ueS.rst @@ -0,0 +1,2 @@ +Fixed a bug in the parser that was causing it to not respect :pep:`263` +coding cookies when no flags are provided. Patch by Pablo Galindo diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index ae1284178dc60e..d1f756395373da 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -329,6 +329,19 @@ static PyTypeObject _HashInheritanceTester_Type = { PyType_GenericNew, /* tp_new */ }; +static PyObject* +pycompilestring(PyObject* self, PyObject *obj) { + if (PyBytes_CheckExact(obj) == 0) { + PyErr_SetString(PyExc_ValueError, "Argument must be a bytes object"); + return NULL; + } + const char *the_string = PyBytes_AsString(obj); + if (the_string == NULL) { + return NULL; + } + return Py_CompileString(the_string, "blech", Py_file_input); +} + static PyObject* test_lazy_hash_inheritance(PyObject* self, PyObject *Py_UNUSED(ignored)) { @@ -5537,6 +5550,7 @@ static PyMethodDef TestMethods[] = { return_null_without_error, METH_NOARGS}, {"return_result_with_error", return_result_with_error, METH_NOARGS}, + {"Py_CompileString", pycompilestring, METH_O}, {"PyTime_FromSeconds", test_pytime_fromseconds, METH_VARARGS}, {"PyTime_FromSecondsObject", test_pytime_fromsecondsobject, METH_VARARGS}, {"PyTime_AsSecondsDouble", test_pytime_assecondsdouble, METH_VARARGS}, diff --git a/Parser/pegen/pegen.c b/Parser/pegen/pegen.c index efcf9ac1ebd742..2e986c5294f199 100644 --- a/Parser/pegen/pegen.c +++ b/Parser/pegen/pegen.c @@ -1225,7 +1225,7 @@ _PyPegen_run_parser_from_string(const char *str, int start_rule, PyObject *filen int exec_input = start_rule == Py_file_input; struct tok_state *tok; - if (flags == NULL || flags->cf_flags & PyCF_IGNORE_COOKIE) { + if (flags != NULL && flags->cf_flags & PyCF_IGNORE_COOKIE) { tok = PyTokenizer_FromUTF8(str, exec_input); } else { tok = PyTokenizer_FromString(str, exec_input);