From 8b9505f932278f97e730b1bf6759a6f7b4d33f4f Mon Sep 17 00:00:00 2001 From: johnslavik Date: Sun, 14 Jun 2026 05:05:27 +0200 Subject: [PATCH 01/13] Fix exception handling in file tokenizer --- Lib/test/test_source_encoding.py | 12 ++++++++++-- .../2026-06-14-05-05-15.gh-issue-151461.5q0s88.rst | 3 +++ Parser/tokenizer/helpers.c | 3 ++- 3 files changed, 15 insertions(+), 3 deletions(-) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-06-14-05-05-15.gh-issue-151461.5q0s88.rst diff --git a/Lib/test/test_source_encoding.py b/Lib/test/test_source_encoding.py index 8ac64b3105708f..2e1802af4abf7c 100644 --- a/Lib/test/test_source_encoding.py +++ b/Lib/test/test_source_encoding.py @@ -387,8 +387,7 @@ def test_utf8_non_utf8_third_line_error(self): b'#third\xa4\n' b'raise RuntimeError\n') self.check_script_error(src, - br"'utf-8' codec can't decode byte|" - br"encoding problem: utf8") + br"'utf-8' codec can't decode byte") def test_crlf(self): src = (b'print(ascii("""\r\n"""))\n') @@ -540,6 +539,15 @@ def check_script_error(self, src, expected, lineno=...): line = line.removeprefix('\ufeff') self.assertIn(line.encode(), err) + def test_coding_spec_unknown_encoding(self): + src = (b'# coding: dict-unpacking-at-home\n' + b'{foo} = {"foo": "bar"}\n') + self.check_script_error(src, br"unknown encoding: dict-unpacking-at-home") + + def test_coding_spec_decode_error(self): + src = (b'# coding: shift-jis\n' + b'print("\xc4\x85")\n') + self.check_script_error(src, br"'shift_jis' codec can't decode byte 0x85") if __name__ == "__main__": diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-06-14-05-05-15.gh-issue-151461.5q0s88.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-06-14-05-05-15.gh-issue-151461.5q0s88.rst new file mode 100644 index 00000000000000..6450e54cdd764e --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-06-14-05-05-15.gh-issue-151461.5q0s88.rst @@ -0,0 +1,3 @@ +Fixed the tokenizer to no longer show a generic ``SyntaxError: encoding +problem`` message and distinguish whether a codec was not found or a file +could not be decoded. Patch by Bartosz Sławecki. diff --git a/Parser/tokenizer/helpers.c b/Parser/tokenizer/helpers.c index c69e66d0ab9b7a..78a7fac23a04a0 100644 --- a/Parser/tokenizer/helpers.c +++ b/Parser/tokenizer/helpers.c @@ -2,6 +2,7 @@ #include "errcode.h" #include "pycore_token.h" +#include "../pegen.h" #include "../lexer/state.h" @@ -419,7 +420,7 @@ _PyTokenizer_check_coding_spec(const char* line, Py_ssize_t size, struct tok_sta assert(tok->decoding_readline == NULL); if (strcmp(cs, "utf-8") != 0 && !set_readline(tok, cs)) { _PyTokenizer_error_ret(tok); - PyErr_Format(PyExc_SyntaxError, "encoding problem: %s", cs); + _PyPegen_raise_tokenizer_init_error(tok->filename); PyMem_Free(cs); return 0; } From fbb7137dd948429e33638ae34c86df30fd17d33e Mon Sep 17 00:00:00 2001 From: johnslavik Date: Sun, 14 Jun 2026 05:30:11 +0200 Subject: [PATCH 02/13] Move `_PyPegen_raise_tokenizer_init_error` to tokenizer helpers as `_PyTokenizer_init_error` --- Parser/pegen.c | 5 ++-- Parser/pegen.h | 1 - Parser/pegen_errors.c | 47 --------------------------------- Parser/tokenizer/helpers.c | 54 +++++++++++++++++++++++++++++++++++++- Parser/tokenizer/helpers.h | 1 + 5 files changed, 57 insertions(+), 51 deletions(-) diff --git a/Parser/pegen.c b/Parser/pegen.c index 569f5afb312008..0555284dd158d0 100644 --- a/Parser/pegen.c +++ b/Parser/pegen.c @@ -9,6 +9,7 @@ #include "lexer/lexer.h" #include "tokenizer/tokenizer.h" +#include "tokenizer/helpers.h" #include "pegen.h" // Internal parser functions @@ -993,7 +994,7 @@ _PyPegen_run_parser_from_file_pointer(FILE *fp, int start_rule, PyObject *filena struct tok_state *tok = _PyTokenizer_FromFile(fp, enc, ps1, ps2); if (tok == NULL) { if (PyErr_Occurred()) { - _PyPegen_raise_tokenizer_init_error(filename_ob); + _PyTokenizer_init_error(filename_ob); return NULL; } return NULL; @@ -1051,7 +1052,7 @@ _PyPegen_run_parser_from_string(const char *str, int start_rule, PyObject *filen } if (tok == NULL) { if (PyErr_Occurred()) { - _PyPegen_raise_tokenizer_init_error(filename_ob); + _PyTokenizer_init_error(filename_ob); } return NULL; } diff --git a/Parser/pegen.h b/Parser/pegen.h index 85c9ada765d9bd..5c461e82a7f0fa 100644 --- a/Parser/pegen.h +++ b/Parser/pegen.h @@ -174,7 +174,6 @@ typedef enum { } TARGETS_TYPE; int _Pypegen_raise_decode_error(Parser *p); -void _PyPegen_raise_tokenizer_init_error(PyObject *filename); int _Pypegen_tokenizer_error(Parser *p); void *_PyPegen_raise_error(Parser *p, PyObject *errtype, int use_mark, const char *errmsg, ...); void *_PyPegen_raise_error_known_location(Parser *p, PyObject *errtype, diff --git a/Parser/pegen_errors.c b/Parser/pegen_errors.c index 312699415efd9a..b13e1c079220a9 100644 --- a/Parser/pegen_errors.c +++ b/Parser/pegen_errors.c @@ -10,53 +10,6 @@ // TOKENIZER ERRORS -void -_PyPegen_raise_tokenizer_init_error(PyObject *filename) -{ - if (!(PyErr_ExceptionMatches(PyExc_LookupError) - || PyErr_ExceptionMatches(PyExc_SyntaxError) - || PyErr_ExceptionMatches(PyExc_ValueError) - || PyErr_ExceptionMatches(PyExc_UnicodeDecodeError))) { - return; - } - PyObject *errstr = NULL; - PyObject *tuple = NULL; - PyObject *type; - PyObject *value; - PyObject *tback; - PyErr_Fetch(&type, &value, &tback); - if (PyErr_GivenExceptionMatches(value, PyExc_SyntaxError)) { - if (PyObject_SetAttr(value, &_Py_ID(filename), filename)) { - goto error; - } - PyErr_Restore(type, value, tback); - return; - } - errstr = PyObject_Str(value); - if (!errstr) { - goto error; - } - - PyObject *tmp = Py_BuildValue("(OiiO)", filename, 0, -1, Py_None); - if (!tmp) { - goto error; - } - - tuple = _PyTuple_FromPair(errstr, tmp); - Py_DECREF(tmp); - if (!tuple) { - goto error; - } - PyErr_SetObject(PyExc_SyntaxError, tuple); - -error: - Py_XDECREF(type); - Py_XDECREF(value); - Py_XDECREF(tback); - Py_XDECREF(errstr); - Py_XDECREF(tuple); -} - static inline void raise_unclosed_parentheses_error(Parser *p) { int error_lineno = p->tok->parenlinenostack[p->tok->level-1]; diff --git a/Parser/tokenizer/helpers.c b/Parser/tokenizer/helpers.c index 78a7fac23a04a0..1d4bc4eeccdf36 100644 --- a/Parser/tokenizer/helpers.c +++ b/Parser/tokenizer/helpers.c @@ -1,6 +1,8 @@ #include "Python.h" #include "errcode.h" +#include "pycore_runtime.h" // _Py_ID() #include "pycore_token.h" +#include "pycore_tuple.h" // _PyTuple_FromPair #include "../pegen.h" #include "../lexer/state.h" @@ -150,6 +152,53 @@ _PyTokenizer_warn_invalid_escape_sequence(struct tok_state *tok, int first_inval return 0; } +void +_PyTokenizer_init_error(PyObject *filename) +{ + if (!(PyErr_ExceptionMatches(PyExc_LookupError) + || PyErr_ExceptionMatches(PyExc_SyntaxError) + || PyErr_ExceptionMatches(PyExc_ValueError) + || PyErr_ExceptionMatches(PyExc_UnicodeDecodeError))) { + return; + } + PyObject *errstr = NULL; + PyObject *tuple = NULL; + PyObject *type; + PyObject *value; + PyObject *tback; + PyErr_Fetch(&type, &value, &tback); + if (PyErr_GivenExceptionMatches(value, PyExc_SyntaxError)) { + if (PyObject_SetAttr(value, &_Py_ID(filename), filename)) { + goto error; + } + PyErr_Restore(type, value, tback); + return; + } + errstr = PyObject_Str(value); + if (!errstr) { + goto error; + } + + PyObject *tmp = Py_BuildValue("(OiiO)", filename, 0, -1, Py_None); + if (!tmp) { + goto error; + } + + tuple = _PyTuple_FromPair(errstr, tmp); + Py_DECREF(tmp); + if (!tuple) { + goto error; + } + PyErr_SetObject(PyExc_SyntaxError, tuple); + +error: + Py_XDECREF(type); + Py_XDECREF(value); + Py_XDECREF(tback); + Py_XDECREF(errstr); + Py_XDECREF(tuple); +} + int _PyTokenizer_parser_warn(struct tok_state *tok, PyObject *category, const char *format, ...) { @@ -420,7 +469,10 @@ _PyTokenizer_check_coding_spec(const char* line, Py_ssize_t size, struct tok_sta assert(tok->decoding_readline == NULL); if (strcmp(cs, "utf-8") != 0 && !set_readline(tok, cs)) { _PyTokenizer_error_ret(tok); - _PyPegen_raise_tokenizer_init_error(tok->filename); + if (!PyErr_Occurred()) { + PyErr_Format(PyExc_SyntaxError, "encoding problem: %s", cs); + } + _PyTokenizer_init_error(tok->filename); PyMem_Free(cs); return 0; } diff --git a/Parser/tokenizer/helpers.h b/Parser/tokenizer/helpers.h index 98f6445d5a3b40..5e3693aae819c4 100644 --- a/Parser/tokenizer/helpers.h +++ b/Parser/tokenizer/helpers.h @@ -15,6 +15,7 @@ int _PyTokenizer_indenterror(struct tok_state *tok); int _PyTokenizer_warn_invalid_escape_sequence(struct tok_state *tok, int first_invalid_escape_char); int _PyTokenizer_parser_warn(struct tok_state *tok, PyObject *category, const char *format, ...); char *_PyTokenizer_error_ret(struct tok_state *tok); +void _PyTokenizer_init_error(PyObject *filename); char *_PyTokenizer_new_string(const char *s, Py_ssize_t len, struct tok_state *tok); char *_PyTokenizer_translate_newlines(const char *s, int exec_input, int preserve_crlf, struct tok_state *tok); From 20df25bb49497a92ee9bf4b047e8354cac6f2a15 Mon Sep 17 00:00:00 2001 From: johnslavik Date: Sun, 14 Jun 2026 05:32:07 +0200 Subject: [PATCH 03/13] Remove `encoding problem` again (somehow it slipped) --- Parser/tokenizer/helpers.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/Parser/tokenizer/helpers.c b/Parser/tokenizer/helpers.c index 1d4bc4eeccdf36..d4661978b84b47 100644 --- a/Parser/tokenizer/helpers.c +++ b/Parser/tokenizer/helpers.c @@ -469,9 +469,6 @@ _PyTokenizer_check_coding_spec(const char* line, Py_ssize_t size, struct tok_sta assert(tok->decoding_readline == NULL); if (strcmp(cs, "utf-8") != 0 && !set_readline(tok, cs)) { _PyTokenizer_error_ret(tok); - if (!PyErr_Occurred()) { - PyErr_Format(PyExc_SyntaxError, "encoding problem: %s", cs); - } _PyTokenizer_init_error(tok->filename); PyMem_Free(cs); return 0; From 538832a0920ba854671424e552804a4a9336c3d1 Mon Sep 17 00:00:00 2001 From: johnslavik Date: Sun, 14 Jun 2026 05:34:09 +0200 Subject: [PATCH 04/13] Fix unnecessary include --- Parser/tokenizer/helpers.c | 1 - 1 file changed, 1 deletion(-) diff --git a/Parser/tokenizer/helpers.c b/Parser/tokenizer/helpers.c index d4661978b84b47..d1ca44ff2b8163 100644 --- a/Parser/tokenizer/helpers.c +++ b/Parser/tokenizer/helpers.c @@ -4,7 +4,6 @@ #include "pycore_token.h" #include "pycore_tuple.h" // _PyTuple_FromPair -#include "../pegen.h" #include "../lexer/state.h" From 4a02a4a877b7dcc246baa043d033cbdba49807f4 Mon Sep 17 00:00:00 2001 From: johnslavik Date: Sun, 14 Jun 2026 05:34:45 +0200 Subject: [PATCH 05/13] Loosen error pattern --- Lib/test/test_source_encoding.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_source_encoding.py b/Lib/test/test_source_encoding.py index 2e1802af4abf7c..711680c4d8f5d1 100644 --- a/Lib/test/test_source_encoding.py +++ b/Lib/test/test_source_encoding.py @@ -547,7 +547,7 @@ def test_coding_spec_unknown_encoding(self): def test_coding_spec_decode_error(self): src = (b'# coding: shift-jis\n' b'print("\xc4\x85")\n') - self.check_script_error(src, br"'shift_jis' codec can't decode byte 0x85") + self.check_script_error(src, br"'shift_jis' codec can't decode byte") if __name__ == "__main__": From abc667283fc91f8fe4fa36de0f39ba02acfb2d7f Mon Sep 17 00:00:00 2001 From: johnslavik Date: Sun, 14 Jun 2026 05:37:19 +0200 Subject: [PATCH 06/13] Better name for the helper --- Parser/pegen.c | 4 ++-- Parser/tokenizer/helpers.c | 4 ++-- Parser/tokenizer/helpers.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Parser/pegen.c b/Parser/pegen.c index 0555284dd158d0..bb222b50fc095f 100644 --- a/Parser/pegen.c +++ b/Parser/pegen.c @@ -994,7 +994,7 @@ _PyPegen_run_parser_from_file_pointer(FILE *fp, int start_rule, PyObject *filena struct tok_state *tok = _PyTokenizer_FromFile(fp, enc, ps1, ps2); if (tok == NULL) { if (PyErr_Occurred()) { - _PyTokenizer_init_error(filename_ob); + _PyTokenizer_raise_init_error(filename_ob); return NULL; } return NULL; @@ -1052,7 +1052,7 @@ _PyPegen_run_parser_from_string(const char *str, int start_rule, PyObject *filen } if (tok == NULL) { if (PyErr_Occurred()) { - _PyTokenizer_init_error(filename_ob); + _PyTokenizer_raise_init_error(filename_ob); } return NULL; } diff --git a/Parser/tokenizer/helpers.c b/Parser/tokenizer/helpers.c index d1ca44ff2b8163..39d82f19238a36 100644 --- a/Parser/tokenizer/helpers.c +++ b/Parser/tokenizer/helpers.c @@ -152,7 +152,7 @@ _PyTokenizer_warn_invalid_escape_sequence(struct tok_state *tok, int first_inval } void -_PyTokenizer_init_error(PyObject *filename) +_PyTokenizer_raise_init_error(PyObject *filename) { if (!(PyErr_ExceptionMatches(PyExc_LookupError) || PyErr_ExceptionMatches(PyExc_SyntaxError) @@ -468,7 +468,7 @@ _PyTokenizer_check_coding_spec(const char* line, Py_ssize_t size, struct tok_sta assert(tok->decoding_readline == NULL); if (strcmp(cs, "utf-8") != 0 && !set_readline(tok, cs)) { _PyTokenizer_error_ret(tok); - _PyTokenizer_init_error(tok->filename); + _PyTokenizer_raise_init_error(tok->filename); PyMem_Free(cs); return 0; } diff --git a/Parser/tokenizer/helpers.h b/Parser/tokenizer/helpers.h index 5e3693aae819c4..34303999a60aff 100644 --- a/Parser/tokenizer/helpers.h +++ b/Parser/tokenizer/helpers.h @@ -15,7 +15,7 @@ int _PyTokenizer_indenterror(struct tok_state *tok); int _PyTokenizer_warn_invalid_escape_sequence(struct tok_state *tok, int first_invalid_escape_char); int _PyTokenizer_parser_warn(struct tok_state *tok, PyObject *category, const char *format, ...); char *_PyTokenizer_error_ret(struct tok_state *tok); -void _PyTokenizer_init_error(PyObject *filename); +void _PyTokenizer_raise_init_error(PyObject *filename); char *_PyTokenizer_new_string(const char *s, Py_ssize_t len, struct tok_state *tok); char *_PyTokenizer_translate_newlines(const char *s, int exec_input, int preserve_crlf, struct tok_state *tok); From caaef7a261bc12aea3464513e3e9381dff569111 Mon Sep 17 00:00:00 2001 From: johnslavik Date: Sun, 14 Jun 2026 05:38:28 +0200 Subject: [PATCH 07/13] Move cleanup below raise --- Parser/tokenizer/helpers.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Parser/tokenizer/helpers.c b/Parser/tokenizer/helpers.c index 39d82f19238a36..62b0971d418c39 100644 --- a/Parser/tokenizer/helpers.c +++ b/Parser/tokenizer/helpers.c @@ -467,8 +467,8 @@ _PyTokenizer_check_coding_spec(const char* line, Py_ssize_t size, struct tok_sta if (tok->encoding == NULL) { assert(tok->decoding_readline == NULL); if (strcmp(cs, "utf-8") != 0 && !set_readline(tok, cs)) { - _PyTokenizer_error_ret(tok); _PyTokenizer_raise_init_error(tok->filename); + _PyTokenizer_error_ret(tok); PyMem_Free(cs); return 0; } From 2589171d67ea7b41bbaef8aa671b543497b94051 Mon Sep 17 00:00:00 2001 From: johnslavik Date: Sun, 14 Jun 2026 06:07:59 +0200 Subject: [PATCH 08/13] Reword the news entry --- .../2026-06-14-05-05-15.gh-issue-151461.5q0s88.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-06-14-05-05-15.gh-issue-151461.5q0s88.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-06-14-05-05-15.gh-issue-151461.5q0s88.rst index 6450e54cdd764e..272acb918d31c4 100644 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-06-14-05-05-15.gh-issue-151461.5q0s88.rst +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-06-14-05-05-15.gh-issue-151461.5q0s88.rst @@ -1,3 +1,3 @@ -Fixed the tokenizer to no longer show a generic ``SyntaxError: encoding -problem`` message and distinguish whether a codec was not found or a file -could not be decoded. Patch by Bartosz Sławecki. +Fix direct execution of files with invalid source encodings to report the +underlying codec lookup or decoding error instead of the generic +``SyntaxError: encoding problem`` message. Patch by Bartosz Sławecki. \ No newline at end of file From 4f034c9b28c99654a1f99ba67b745d071ee3b334 Mon Sep 17 00:00:00 2001 From: johnslavik Date: Sun, 14 Jun 2026 06:09:47 +0200 Subject: [PATCH 09/13] Fix newline in news entry --- .../2026-06-14-05-05-15.gh-issue-151461.5q0s88.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-06-14-05-05-15.gh-issue-151461.5q0s88.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-06-14-05-05-15.gh-issue-151461.5q0s88.rst index 272acb918d31c4..d76a9bc95278bc 100644 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-06-14-05-05-15.gh-issue-151461.5q0s88.rst +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-06-14-05-05-15.gh-issue-151461.5q0s88.rst @@ -1,3 +1,3 @@ Fix direct execution of files with invalid source encodings to report the underlying codec lookup or decoding error instead of the generic -``SyntaxError: encoding problem`` message. Patch by Bartosz Sławecki. \ No newline at end of file +``SyntaxError: encoding problem`` message. Patch by Bartosz Sławecki. From f484ce16ab87a12376666001434d15eff056c866 Mon Sep 17 00:00:00 2001 From: johnslavik Date: Sun, 14 Jun 2026 13:56:20 +0200 Subject: [PATCH 10/13] Remove `dict-unpacking-at-home` --- Lib/test/test_source_encoding.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_source_encoding.py b/Lib/test/test_source_encoding.py index 711680c4d8f5d1..db7ec4f68994c1 100644 --- a/Lib/test/test_source_encoding.py +++ b/Lib/test/test_source_encoding.py @@ -540,9 +540,14 @@ def check_script_error(self, src, expected, lineno=...): self.assertIn(line.encode(), err) def test_coding_spec_unknown_encoding(self): - src = (b'# coding: dict-unpacking-at-home\n' - b'{foo} = {"foo": "bar"}\n') - self.check_script_error(src, br"unknown encoding: dict-unpacking-at-home") + src = (b'# coding: c1252\n' + b'print("Hi!")\n') + self.check_script_error(src, br"unknown encoding: c1252") + + def test_coding_spec_decode_error(self): + src = (b'# coding: shift-jis\n' + b'print("\xc4\x85")\n') + self.check_script_error(src, br"'shift_jis' codec can't decode byte") def test_coding_spec_decode_error(self): src = (b'# coding: shift-jis\n' From 7d0ea60b4a5e60f1b52badfe8efa0803a97654a0 Mon Sep 17 00:00:00 2001 From: johnslavik Date: Sun, 14 Jun 2026 13:56:36 +0200 Subject: [PATCH 11/13] Add a non-text encoding test --- Lib/test/test_source_encoding.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Lib/test/test_source_encoding.py b/Lib/test/test_source_encoding.py index db7ec4f68994c1..5313f13d579d45 100644 --- a/Lib/test/test_source_encoding.py +++ b/Lib/test/test_source_encoding.py @@ -554,6 +554,11 @@ def test_coding_spec_decode_error(self): b'print("\xc4\x85")\n') self.check_script_error(src, br"'shift_jis' codec can't decode byte") + def test_coding_spec_non_text_encoding(self): + src = (b'# coding: hex_codec\n' + b'print("Test")\n') + self.check_script_error(src, br"'hex_codec' is not a text encoding") + if __name__ == "__main__": unittest.main() From 9fda1d14d561b2fff1bf250cfccc59b7db9a1726 Mon Sep 17 00:00:00 2001 From: johnslavik Date: Sun, 14 Jun 2026 14:02:15 +0200 Subject: [PATCH 12/13] Remove doubled test --- Lib/test/test_source_encoding.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Lib/test/test_source_encoding.py b/Lib/test/test_source_encoding.py index 5313f13d579d45..46a10295bd4b4a 100644 --- a/Lib/test/test_source_encoding.py +++ b/Lib/test/test_source_encoding.py @@ -549,11 +549,6 @@ def test_coding_spec_decode_error(self): b'print("\xc4\x85")\n') self.check_script_error(src, br"'shift_jis' codec can't decode byte") - def test_coding_spec_decode_error(self): - src = (b'# coding: shift-jis\n' - b'print("\xc4\x85")\n') - self.check_script_error(src, br"'shift_jis' codec can't decode byte") - def test_coding_spec_non_text_encoding(self): src = (b'# coding: hex_codec\n' b'print("Test")\n') From 9f8c99f168f3ca00d39b56b904efb4c00aa06937 Mon Sep 17 00:00:00 2001 From: johnslavik Date: Sun, 14 Jun 2026 14:04:13 +0200 Subject: [PATCH 13/13] Print eggs --- Lib/test/test_source_encoding.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_source_encoding.py b/Lib/test/test_source_encoding.py index 46a10295bd4b4a..53fffe7cfb56d0 100644 --- a/Lib/test/test_source_encoding.py +++ b/Lib/test/test_source_encoding.py @@ -551,7 +551,7 @@ def test_coding_spec_decode_error(self): def test_coding_spec_non_text_encoding(self): src = (b'# coding: hex_codec\n' - b'print("Test")\n') + b'print("eggs")\n') self.check_script_error(src, br"'hex_codec' is not a text encoding")