From c8da735f4f051e34ae95a7d50522466e08848136 Mon Sep 17 00:00:00 2001 From: "Gregory P. Smith" <68491+gpshead@users.noreply.github.com> Date: Mon, 7 Sep 2026 18:32:36 -0700 Subject: [PATCH 1/3] gh-157142: Fix linking _freeze_module with built-in test modules (GH-157143) Programs/_freeze_module is linked with Modules/getpath_noop.o rather than Modules/getpath.o, and getpath_noop.c only defined _PyConfig_InitPathConfig(). With MODULE_BUILDTYPE=static (the default on wasm), _testinternalcapi.o is part of LIBRARY_OBJS_OMIT_FROZEN and its get_getpath_codeobject() left _Py_Get_Getpath_CodeObject() as an undefined reference. Define a stub for it. --- .../2026-09-07-23-40-00.gh-issue-157142.gpnoop.rst | 4 ++++ Modules/getpath_noop.c | 13 ++++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Build/2026-09-07-23-40-00.gh-issue-157142.gpnoop.rst diff --git a/Misc/NEWS.d/next/Build/2026-09-07-23-40-00.gh-issue-157142.gpnoop.rst b/Misc/NEWS.d/next/Build/2026-09-07-23-40-00.gh-issue-157142.gpnoop.rst new file mode 100644 index 00000000000000..ac2890b5324ba4 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2026-09-07-23-40-00.gh-issue-157142.gpnoop.rst @@ -0,0 +1,4 @@ +Fix the link of ``Programs/_freeze_module`` when extension modules are built +in (``MODULE_BUILDTYPE=static``) and the test modules are enabled: +``Modules/getpath_noop.c`` now defines ``_Py_Get_Getpath_CodeObject()``, +which ``_testinternalcapi`` uses. diff --git a/Modules/getpath_noop.c b/Modules/getpath_noop.c index c10e41d07f27c9..25ca25bd42c251 100644 --- a/Modules/getpath_noop.c +++ b/Modules/getpath_noop.c @@ -1,10 +1,21 @@ /* Implements the getpath API for compiling with no functionality */ #include "Python.h" -#include "pycore_pathconfig.h" +#include "pycore_initconfig.h" // _Py_Get_Getpath_CodeObject() +#include "pycore_pathconfig.h" // _PyConfig_InitPathConfig() PyStatus _PyConfig_InitPathConfig(PyConfig *config, int compute_path_config) { return PyStatus_Error("path configuration is unsupported"); } + +/* Used by _testinternalcapi, which is linked into Programs/_freeze_module + when extension modules are built in (MODULE_BUILDTYPE=static). */ +PyObject * +_Py_Get_Getpath_CodeObject(void) +{ + PyErr_SetString(PyExc_RuntimeError, + "path configuration is unsupported"); + return NULL; +} From 0b4c7da5c401154af7b7cb89a6467365cadc2653 Mon Sep 17 00:00:00 2001 From: Shardul Deshpande Date: Tue, 8 Sep 2026 09:34:21 +0530 Subject: [PATCH 2/3] gh-150922: Fix test_cmd libedit assertion in test_bang_completion_without_do_shell (GH-156623) GNU readline retypes the full completed word after tab completion, but libedit redraws only the untyped suffix following a cursor-forward escape sequence. Assert on the common suffix ('ello') instead of the literal 'hello' bytes so the test passes on both backends. --- Lib/test/test_cmd.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_cmd.py b/Lib/test/test_cmd.py index dbfec42fc21988..ed3336994edaeb 100644 --- a/Lib/test/test_cmd.py +++ b/Lib/test/test_cmd.py @@ -316,7 +316,10 @@ def default(self, line): for input in [b"! h\t\n", b"!h\t\n"]: with self.subTest(input=input): output = run_pty(script, input) - self.assertIn(b'hello', output) + # libedit redraws only the untyped suffix after a + # cursor-forward escape, unlike GNU readline which retypes + # the whole completed word, so check the common suffix. + self.assertIn(b'ello', output) self.assertIn(b'tab completion success', output) def load_tests(loader, tests, pattern): From 5ddd59fc474a7e0b77b6f8cb0ba678254171b106 Mon Sep 17 00:00:00 2001 From: "Gregory P. Smith" <68491+gpshead@users.noreply.github.com> Date: Mon, 7 Sep 2026 21:58:03 -0700 Subject: [PATCH 3/3] gh-157159: improve the tabnanny usage message (GH-157160) The usage message embedded sys.argv[0], which under `python -m tabnanny` is the absolute path of tabnanny.py, and a meaningless virtual path when the standard library is in a zip archive or embedded in an executable. Print f"Usage: {sys.executable} -m tabnanny [-v] file_or_directory ..." instead, and make the test expect that fixed form. --- Lib/tabnanny.py | 2 +- Lib/test/test_tabnanny.py | 7 +++---- .../Library/2026-09-08-09-30-00.gh-issue-157159.tabNny.rst | 2 ++ 3 files changed, 6 insertions(+), 5 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2026-09-08-09-30-00.gh-issue-157159.tabNny.rst diff --git a/Lib/tabnanny.py b/Lib/tabnanny.py index 272e8e33e0c46a..04c5baf7b52d9a 100644 --- a/Lib/tabnanny.py +++ b/Lib/tabnanny.py @@ -47,7 +47,7 @@ def main(): if o == '-v': verbose = verbose + 1 if not args: - errprint("Usage:", sys.argv[0], "[-v] file_or_directory ...") + errprint(f"Usage: {sys.executable} -m tabnanny [-v] file_or_directory ...") for arg in args: check(arg) diff --git a/Lib/test/test_tabnanny.py b/Lib/test/test_tabnanny.py index e575aac037e917..85e3e76e9007ca 100644 --- a/Lib/test/test_tabnanny.py +++ b/Lib/test/test_tabnanny.py @@ -7,12 +7,12 @@ from unittest import TestCase, main, mock import errno import os +import sys import tabnanny import tokenize import tempfile import textwrap -from test.support import (captured_stderr, captured_stdout, script_helper, - findfile) +from test.support import captured_stderr, captured_stdout, script_helper from test.support.os_helper import unlink @@ -328,8 +328,7 @@ def test_with_error_free_file(self): def test_command_usage(self): """Should display usage on no arguments.""" - path = findfile('tabnanny.py') - stderr = f"Usage: {path} [-v] file_or_directory ..." + stderr = f"Usage: {sys.executable} -m tabnanny [-v] file_or_directory ..." self.validate_cmd(stderr=stderr, expect_failure=True) def test_quiet_flag(self): diff --git a/Misc/NEWS.d/next/Library/2026-09-08-09-30-00.gh-issue-157159.tabNny.rst b/Misc/NEWS.d/next/Library/2026-09-08-09-30-00.gh-issue-157159.tabNny.rst new file mode 100644 index 00000000000000..982c4afb43dac1 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-09-08-09-30-00.gh-issue-157159.tabNny.rst @@ -0,0 +1,2 @@ +The usage message printed by ``python -m tabnanny`` when no arguments are +given now suggests ``python -m`` instead of the source file.