From 8e2f4b448380b4c835442534d566618f06e32573 Mon Sep 17 00:00:00 2001 From: Facundo Batista Date: Wed, 16 Jul 2025 08:55:31 -0300 Subject: [PATCH 1/8] Improved venv docs to indicate that isolation is the default. (#136698) * Improved venv docs to note that isolation is the default. * Insert "that" so that a sentence reads better. * Improved wording. --------- Co-authored-by: Vinay Sajip --- Doc/library/venv.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Doc/library/venv.rst b/Doc/library/venv.rst index f16e24eac08343..de427fbafe71dc 100644 --- a/Doc/library/venv.rst +++ b/Doc/library/venv.rst @@ -22,10 +22,10 @@ The :mod:`!venv` module supports creating lightweight "virtual environments", each with their own independent set of Python packages installed in their :mod:`site` directories. A virtual environment is created on top of an existing -Python installation, known as the virtual environment's "base" Python, and may -optionally be isolated from the packages in the base environment, -so only those explicitly installed in the virtual environment are available. -See :ref:`sys-path-init-virtual-environments` and :mod:`site`'s +Python installation, known as the virtual environment's "base" Python, and by +default is isolated from the packages in the base environment, +so that only those explicitly installed in the virtual environment are +available. See :ref:`sys-path-init-virtual-environments` and :mod:`site`'s :ref:`virtual environments documentation ` for more information. From 12e52cad718723636a96042f9399634392285c44 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Wed, 16 Jul 2025 15:33:15 +0200 Subject: [PATCH 2/8] gh-127146: Emscripten: Make os.umask() actually work (#136706) Provide a stub implementation of umask that is enough to get some tests passing. More work is needed upstream in Emscripten to make all umask tests to pass. --- Lib/test/test_os.py | 6 ++---- Python/emscripten_syscalls.c | 22 +++++++++++++++++++++- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py index 1e50dc43c35f5c..de3a17fe893170 100644 --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -1918,11 +1918,9 @@ def test_makedir(self): support.is_wasi, "WASI's umask is a stub." ) - @unittest.skipIf( - support.is_emscripten, - "TODO: Fails in buildbot; see #135783" - ) def test_mode(self): + # Note: in some cases, the umask might already be 2 in which case this + # will pass even if os.umask is actually broken. with os_helper.temp_umask(0o002): base = os_helper.TESTFN parent = os.path.join(base, 'dir1') diff --git a/Python/emscripten_syscalls.c b/Python/emscripten_syscalls.c index 7875bfc8fe56ae..bb80f979420ec1 100644 --- a/Python/emscripten_syscalls.c +++ b/Python/emscripten_syscalls.c @@ -7,7 +7,7 @@ // defined with weak linkage so we can override it. EM_JS(int, __syscall_getuid32_js, (void), { // If we're in node and we can, report the native uid - if (typeof process !== "undefined" && typeof process.getuid === "function") { + if (ENVIRONMENT_IS_NODE) { return process.getuid(); } // Fall back to the stub case of returning 0. @@ -17,3 +17,23 @@ EM_JS(int, __syscall_getuid32_js, (void), { int __syscall_getuid32(void) { return __syscall_getuid32_js(); } + +EM_JS(int, __syscall_umask_js, (int mask), { + // If we're in node and we can, call native process.umask() + if (ENVIRONMENT_IS_NODE) { + try { + return process.umask(mask); + } catch(e) { + // oops... + // NodeJS docs: "In Worker threads, process.umask(mask) will throw an exception." + // umask docs: "This system call always succeeds" + return 0; + } + } + // Fall back to the stub case of returning 0. + return 0; +}) + +int __syscall_umask(int mask) { + return __syscall_umask_js(mask); +} From c730952aa64b790c75c437cb63a1242dc08c2e97 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Wed, 16 Jul 2025 16:02:25 +0200 Subject: [PATCH 3/8] gh-127146: Emscripten: more regular stack overflow skips (#136708) Makes the Emscripten stack overflow skip message consistent with WASI, and replaces some ad-hoc skips. --- Lib/test/support/__init__.py | 2 +- Lib/test/test_descr.py | 2 +- Lib/test/test_xml_etree_c.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index fd39d3f7c95368..196a2e5c600e24 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -570,7 +570,7 @@ def skip_android_selinux(name): is_wasi = sys.platform == "wasi" def skip_emscripten_stack_overflow(): - return unittest.skipIf(is_emscripten, "Exhausts limited stack on Emscripten") + return unittest.skipIf(is_emscripten, "Exhausts stack on Emscripten") def skip_wasi_stack_overflow(): return unittest.skipIf(is_wasi, "Exhausts stack on WASI") diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py index f6ec2cf5ce8b5c..8da6647c3f71fc 100644 --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -3942,7 +3942,7 @@ def __del__(self): # it as a leak. del C.__del__ - @unittest.skipIf(support.is_emscripten, "Seems to works in Pyodide?") + @support.skip_emscripten_stack_overflow() @support.skip_wasi_stack_overflow() def test_slots_trash(self): # Testing slot trash... diff --git a/Lib/test/test_xml_etree_c.py b/Lib/test/test_xml_etree_c.py index 9ed0f4096a45e3..270b9d6da8e7b9 100644 --- a/Lib/test/test_xml_etree_c.py +++ b/Lib/test/test_xml_etree_c.py @@ -58,7 +58,7 @@ def test_del_attribute(self): self.assertEqual(element.attrib, {'A': 'B', 'C': 'D'}) @support.skip_wasi_stack_overflow() - @unittest.skipIf(support.is_emscripten, "segfaults") + @support.skip_emscripten_stack_overflow() def test_trashcan(self): # If this test fails, it will most likely die via segfault. e = root = cET.Element('root') From 2f0db9b05f0598548c0c136571c31065ecf961e5 Mon Sep 17 00:00:00 2001 From: sobolevn Date: Wed, 16 Jul 2025 17:35:15 +0300 Subject: [PATCH 4/8] Add `.gram` file to the `.editorconfig` (#136680) --- .editorconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.editorconfig b/.editorconfig index 5b04b32a89e3d2..25bc5935258bd1 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,11 +1,11 @@ root = true -[*.{py,c,cpp,h,js,rst,md,yml,yaml}] +[*.{py,c,cpp,h,js,rst,md,yml,yaml,gram}] trim_trailing_whitespace = true insert_final_newline = true indent_style = space -[*.{py,c,cpp,h}] +[*.{py,c,cpp,h,gram}] indent_size = 4 [*.rst] From bde808ad6ba5eee8a6201983cf071449d7ce7e39 Mon Sep 17 00:00:00 2001 From: Harmen Stoppels Date: Wed, 16 Jul 2025 17:30:10 +0200 Subject: [PATCH 5/8] gh-136710: Fix bad indentation in `os.chdir` docstring (GH-136709) --- Modules/clinic/posixmodule.c.h | 4 ++-- Modules/posixmodule.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Modules/clinic/posixmodule.c.h b/Modules/clinic/posixmodule.c.h index 22f426c5192bf2..65f5f8c9267b6c 100644 --- a/Modules/clinic/posixmodule.c.h +++ b/Modules/clinic/posixmodule.c.h @@ -380,7 +380,7 @@ PyDoc_STRVAR(os_chdir__doc__, "\n" "path may always be specified as a string.\n" "On some platforms, path may also be specified as an open file descriptor.\n" -" If this functionality is unavailable, using it raises an exception."); +"If this functionality is unavailable, using it raises an exception."); #define OS_CHDIR_METHODDEF \ {"chdir", _PyCFunction_CAST(os_chdir), METH_FASTCALL|METH_KEYWORDS, os_chdir__doc__}, @@ -13440,4 +13440,4 @@ os__emscripten_debugger(PyObject *module, PyObject *Py_UNUSED(ignored)) #ifndef OS__EMSCRIPTEN_DEBUGGER_METHODDEF #define OS__EMSCRIPTEN_DEBUGGER_METHODDEF #endif /* !defined(OS__EMSCRIPTEN_DEBUGGER_METHODDEF) */ -/*[clinic end generated code: output=5341daae6581a62b input=a9049054013a1b77]*/ +/*[clinic end generated code: output=6cfddb3b77dc7a40 input=a9049054013a1b77]*/ diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index b570f81b7cf7c2..47eaf5cd428a53 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -3477,12 +3477,12 @@ Change the current working directory to the specified path. path may always be specified as a string. On some platforms, path may also be specified as an open file descriptor. - If this functionality is unavailable, using it raises an exception. +If this functionality is unavailable, using it raises an exception. [clinic start generated code]*/ static PyObject * os_chdir_impl(PyObject *module, path_t *path) -/*[clinic end generated code: output=3be6400eee26eaae input=1a4a15b4d12cb15d]*/ +/*[clinic end generated code: output=3be6400eee26eaae input=a74ceab5d72adf74]*/ { int result; From dcd27aace180737adaddc79c00c181816fc6e162 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Wed, 16 Jul 2025 17:53:47 +0200 Subject: [PATCH 6/8] gh-127146: Emscripten: Don't need to avoid unpaired surrogate anymore (#136707) This might have been fixed by gh-136624, or by some Emscripten change. In any case, it no longer seems to be needed. --- Lib/test/test_warnings/__init__.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/Lib/test/test_warnings/__init__.py b/Lib/test/test_warnings/__init__.py index 5c3b1250ceb045..f89e94449b3031 100644 --- a/Lib/test/test_warnings/__init__.py +++ b/Lib/test/test_warnings/__init__.py @@ -555,13 +555,7 @@ def test_warn_explicit_non_ascii_filename(self): with self.module.catch_warnings(record=True) as w: self.module.resetwarnings() self.module.filterwarnings("always", category=UserWarning) - filenames = ["nonascii\xe9\u20ac"] - if not support.is_emscripten: - # JavaScript does not like surrogates. - # Invalid UTF-8 leading byte 0x80 encountered when - # deserializing a UTF-8 string in wasm memory to a JS - # string! - filenames.append("surrogate\udc80") + filenames = ["nonascii\xe9\u20ac", "surrogate\udc80"] for filename in filenames: try: os.fsencode(filename) From 69d8fe50ddc4dbe757c9929a532e2e882f0261ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartosz=20S=C5=82awecki?= Date: Wed, 16 Jul 2025 18:34:14 +0200 Subject: [PATCH 7/8] gh-126548: Add a thread-unsafety warning for `importlib.reload()` (GH-136704) --- Doc/library/importlib.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Doc/library/importlib.rst b/Doc/library/importlib.rst index ea5a77028683b3..4f374be778d6b3 100644 --- a/Doc/library/importlib.rst +++ b/Doc/library/importlib.rst @@ -206,6 +206,10 @@ Functions :exc:`ModuleNotFoundError` is raised when the module being reloaded lacks a :class:`~importlib.machinery.ModuleSpec`. + .. warning:: + This function is not thread-safe. Calling it from multiple threads can result + in unexpected behavior. It's recommended to use the :class:`threading.Lock` + or other synchronization primitives for thread-safe module reloading. :mod:`importlib.abc` -- Abstract base classes related to import --------------------------------------------------------------- From b7d722547bcc9e92dca4837b9fdbe7457788820b Mon Sep 17 00:00:00 2001 From: Kumar Aditya Date: Wed, 16 Jul 2025 22:09:08 +0530 Subject: [PATCH 8/8] gh-136669: build `_asyncio` as static module (#136670) `_asyncio` is now built as a static module so that thread states can be accessed directly via registers and avoids the overhead of function call. --- .../Library/2025-07-15-16-37-34.gh-issue-136669.Yexwah.rst | 1 + Modules/Setup.stdlib.in | 7 ++++++- Modules/_remote_debugging_module.c | 6 +++--- 3 files changed, 10 insertions(+), 4 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2025-07-15-16-37-34.gh-issue-136669.Yexwah.rst diff --git a/Misc/NEWS.d/next/Library/2025-07-15-16-37-34.gh-issue-136669.Yexwah.rst b/Misc/NEWS.d/next/Library/2025-07-15-16-37-34.gh-issue-136669.Yexwah.rst new file mode 100644 index 00000000000000..0d93397ff35d0b --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-07-15-16-37-34.gh-issue-136669.Yexwah.rst @@ -0,0 +1 @@ +:mod:`!_asyncio` is now statically linked for improved performance. diff --git a/Modules/Setup.stdlib.in b/Modules/Setup.stdlib.in index 3a38a60a152e8c..86c8eb27c0a6c7 100644 --- a/Modules/Setup.stdlib.in +++ b/Modules/Setup.stdlib.in @@ -32,7 +32,6 @@ ############################################################################ # Modules that should always be present (POSIX and Windows): @MODULE_ARRAY_TRUE@array arraymodule.c -@MODULE__ASYNCIO_TRUE@_asyncio _asynciomodule.c @MODULE__BISECT_TRUE@_bisect _bisectmodule.c @MODULE__CSV_TRUE@_csv _csv.c @MODULE__HEAPQ_TRUE@_heapq _heapqmodule.c @@ -193,3 +192,9 @@ # Limited API template modules; must be built as shared modules. @MODULE_XXLIMITED_TRUE@xxlimited xxlimited.c @MODULE_XXLIMITED_35_TRUE@xxlimited_35 xxlimited_35.c + + +# for performance +*static* + +@MODULE__ASYNCIO_TRUE@_asyncio _asynciomodule.c diff --git a/Modules/_remote_debugging_module.c b/Modules/_remote_debugging_module.c index d72031137e0a4e..b50e5e403a1a19 100644 --- a/Modules/_remote_debugging_module.c +++ b/Modules/_remote_debugging_module.c @@ -811,7 +811,7 @@ _Py_RemoteDebug_GetAsyncioDebugAddress(proc_handle_t* handle) } #elif defined(__linux__) // On Linux, search for asyncio debug in executable or DLL - address = search_linux_map_for_section(handle, "AsyncioDebug", "_asyncio.cpython"); + address = search_linux_map_for_section(handle, "AsyncioDebug", "python"); if (address == 0) { // Error out: 'python' substring covers both executable and DLL PyObject *exc = PyErr_GetRaisedException(); @@ -820,10 +820,10 @@ _Py_RemoteDebug_GetAsyncioDebugAddress(proc_handle_t* handle) } #elif defined(__APPLE__) && TARGET_OS_OSX // On macOS, try libpython first, then fall back to python - address = search_map_for_section(handle, "AsyncioDebug", "_asyncio.cpython"); + address = search_map_for_section(handle, "AsyncioDebug", "libpython"); if (address == 0) { PyErr_Clear(); - address = search_map_for_section(handle, "AsyncioDebug", "_asyncio.cpython"); + address = search_map_for_section(handle, "AsyncioDebug", "python"); } if (address == 0) { // Error out: 'python' substring covers both executable and DLL