diff --git a/Doc/library/csv.rst b/Doc/library/csv.rst index 36db964a8bbfe4..81949261c563d0 100644 --- a/Doc/library/csv.rst +++ b/Doc/library/csv.rst @@ -322,6 +322,12 @@ The :mod:`!csv` module defines the following classes: in particular if it is a single column, so there is no delimiter to find. + If several combinations fit the sample equally well --- + for example if both ``','`` and ``';'`` split every row consistently --- + the delimiters ``','``, ``'\t'``, ``';'``, ``' '`` and ``':'`` + are preferred, in this order, + no matter how many times each of them occurs. + .. versionchanged:: next The dialect is now deduced by trial parsing and the results may differ from those of earlier Python versions. diff --git a/Doc/library/warnings.rst b/Doc/library/warnings.rst index 9063bea96ccb0a..d5f89102d5853b 100644 --- a/Doc/library/warnings.rst +++ b/Doc/library/warnings.rst @@ -566,7 +566,7 @@ Available Functions and calls to :func:`simplefilter`. -.. decorator:: deprecated(msg, *, category=DeprecationWarning, stacklevel=1) +.. decorator:: deprecated(message, /, *, category=DeprecationWarning, stacklevel=1) Decorator to indicate that a class, function or overload is deprecated. diff --git a/Doc/using/mac.rst b/Doc/using/mac.rst index 6cf945de5b3f3b..a01dabbf2475aa 100644 --- a/Doc/using/mac.rst +++ b/Doc/using/mac.rst @@ -29,8 +29,8 @@ Installation steps For `current Python versions `_ (other than those in ``security`` status), the release team produces a **Python for macOS** installer package for each new release. -A list of available installers -is available `here `_. +A list of available installers is provided on the +`macOS downloads page `__. We recommend using the most recent supported Python version where possible. Current installers provide a `universal2 binary `_ build @@ -39,14 +39,14 @@ supported by a wide range of macOS versions, currently typically from at least **macOS 10.15 Catalina** on. The downloaded file is a standard macOS installer package file (``.pkg``). -File integrity information (checksum, size, sigstore signature, etc) for each file is included +File integrity information (such as checksum, size, and Sigstore signature) for each file is included on the release download page. Installer packages and their contents are signed and notarized with ``Python Software Foundation`` Apple Developer ID certificates to meet `macOS Gatekeeper requirements `_. For a default installation, double-click on the downloaded installer package file. This should launch the standard macOS Installer app and display the first of several -installer windows steps. +installer steps. .. image:: mac_installer_01_introduction.png @@ -73,8 +73,8 @@ display. For most uses, the standard set of installation operations is appropria By pressing the **Customize** button, you can choose to omit or select certain package components of the installer. Click on each package name to see a description of what it installs. -To also install support for the optional free-threaded feature, -see :ref:`install-freethreaded-macos`. +For details of the optional free-threaded feature, which is installed +by default, see :ref:`install-freethreaded-macos`. .. image:: mac_installer_05_custom_install.png @@ -98,7 +98,7 @@ for its use. .. image:: mac_installer_08_install_certificates.png -If ``Successfully installed certifi`` and ``update complete`` appears +If ``Successfully installed certifi`` and ``update complete`` appear in the terminal window, the installation is complete. Close this terminal window and the installer window. @@ -171,7 +171,7 @@ be certain of what you are about to run. .. _alternative_bundles: -Alternative Distributions +Alternative distributions ========================= Besides the standard ``python.org`` for macOS installer, there are third-party @@ -199,7 +199,7 @@ other libraries, and are not maintained or supported by the core Python team. .. _mac-package-manager: -Installing Additional Python Packages +Installing additional Python packages ===================================== Refer to the `Python Packaging User Guide`_ for more information. @@ -211,7 +211,7 @@ Refer to the `Python Packaging User Guide`_ for more information. .. _gui-programming-on-the-mac: -GUI Programming +GUI programming =============== There are several options for building GUI applications on the Mac with Python. @@ -241,19 +241,22 @@ A number of alternative macOS GUI toolkits are available including: supports desktop operating systems. -Advanced Topics +Advanced topics =============== .. _install-freethreaded-macos: -Installing Free-threaded Binaries +Installing free-threaded binaries --------------------------------- .. versionadded:: 3.13 +.. versionchanged:: 3.15 + Free-threading support is now installed by default. + The ``python.org`` :ref:`Python for macOS ` -installer package can optionally install an additional build of -Python |version| that supports :pep:`703`, the free-threading feature +installer package installs, by default, an additional build of +Python |version| that supports :term:`free threading` (running with the :term:`global interpreter lock` disabled). Check the release page on ``python.org`` for possible updated information. @@ -262,14 +265,15 @@ there is some additional overhead in single-threaded workloads compared to the regular build. Additionally, third-party packages, in particular ones with an :term:`extension module`, may not be ready for use in a free-threaded build, and will re-enable the :term:`GIL`. -Therefore, the support for free-threading -is not installed by default. It is packaged as a separate install option, -available by clicking the **Customize** button on the **Installation Type** +As of Python 3.15, free-threading support is installed by default. +It is packaged as a separate install option, which can be deselected +by clicking the **Customize** button on the **Installation Type** step of the installer as described above. .. image:: mac_installer_09_custom_install_free_threaded.png -If the box next to the **Free-threaded Python** package name is checked, +If the box next to the **Free-threaded Python** package name is checked +(as it is by default), a separate :file:`PythonT.framework` will also be installed alongside the normal :file:`Python.framework` in :file:`/Library/Frameworks`. This configuration allows a free-threaded Python |version| build to co-exist @@ -284,7 +288,7 @@ Known cautions and limitations: the free-threaded interpreter, and |python_x_dot_y_t_literal_config|, a configuration utility which may be useful for package builders. Since :file:`/usr/local/bin` is typically included in your shell ``PATH``, - in most cases no changes to your ``PATH`` environment variables should + in most cases no changes to your ``PATH`` environment variable should be needed to use |python_x_dot_y_t_literal|. - For this release, the **Shell profile updater** package and the @@ -367,8 +371,8 @@ the macOS command line :command:`installer` utility lets you select non-default options, too. If you are not familiar with :command:`installer`, it can be somewhat cryptic (see :command:`man installer` for more information). As an example, the following shell snippet shows one way to do it, -using the |x_dot_y_b2_literal| release and selecting the free-threaded interpreter -option: +using the |x_dot_y_b2_literal| release and deselecting the free-threaded +interpreter option: .. parsed-literal:: @@ -378,7 +382,7 @@ option: curl -O \https://www.python.org/ftp/python/\ |version|\ .0/${RELEASE} # create installer choicechanges to customize the install: - # enable the PythonTFramework-\ |version|\ package + # disable the PythonTFramework-\ |version|\ package # while accepting the other defaults (install all other packages) cat > ./choicechanges.plist < @@ -387,7 +391,7 @@ option: attributeSetting - 1 + 0 choiceAttribute selected choiceIdentifier @@ -400,7 +404,7 @@ option: sudo installer -pkg ./${RELEASE} -applyChoiceChangesXML ./choicechanges.plist -target / -You can then test that both installer builds are now available with something like: +After a default install, you can test that both builds are available with something like: .. parsed-literal:: @@ -425,7 +429,7 @@ You can then test that both installer builds are now available with something li .. _distributing-python-applications-on-the-mac: -Distributing Python Applications +Distributing Python applications -------------------------------- A range of tools exist for converting your Python code into a standalone @@ -442,7 +446,7 @@ distributable application: * `PyInstaller `_: A cross-platform packaging tool that creates a single file or folder as a distributable artifact. -App Store Compliance +App Store compliance -------------------- Apps submitted for distribution through the macOS App Store must pass Apple's @@ -464,7 +468,7 @@ This patch is not normally required to use CPython on a Mac; nor is it required if you are distributing an app *outside* the macOS App Store. It is *only* required if you are using the macOS App Store as a distribution channel. -Other Resources +Other resources =============== The `python.org Help page `_ has links to many useful resources. diff --git a/Doc/using/mac_installer_01_introduction.png b/Doc/using/mac_installer_01_introduction.png index 1999f3a3759093..81e1f4e5ac5c32 100644 Binary files a/Doc/using/mac_installer_01_introduction.png and b/Doc/using/mac_installer_01_introduction.png differ diff --git a/Doc/using/mac_installer_02_readme.png b/Doc/using/mac_installer_02_readme.png index a36efaf7d50fd6..7e4a9b15cf94f6 100644 Binary files a/Doc/using/mac_installer_02_readme.png and b/Doc/using/mac_installer_02_readme.png differ diff --git a/Doc/using/mac_installer_03_license.png b/Doc/using/mac_installer_03_license.png index 598c22a13d9e62..153daa780efa9e 100644 Binary files a/Doc/using/mac_installer_03_license.png and b/Doc/using/mac_installer_03_license.png differ diff --git a/Doc/using/mac_installer_04_installation_type.png b/Doc/using/mac_installer_04_installation_type.png index 9498fd06240a4e..1fc597c2427ab7 100644 Binary files a/Doc/using/mac_installer_04_installation_type.png and b/Doc/using/mac_installer_04_installation_type.png differ diff --git a/Doc/using/mac_installer_05_custom_install.png b/Doc/using/mac_installer_05_custom_install.png index 3a201d2f44655a..c70d93bbcee70a 100644 Binary files a/Doc/using/mac_installer_05_custom_install.png and b/Doc/using/mac_installer_05_custom_install.png differ diff --git a/Doc/using/mac_installer_06_summary.png b/Doc/using/mac_installer_06_summary.png index 1af6eee2c668cd..f8a67052ef0447 100644 Binary files a/Doc/using/mac_installer_06_summary.png and b/Doc/using/mac_installer_06_summary.png differ diff --git a/Doc/using/mac_installer_07_applications.png b/Doc/using/mac_installer_07_applications.png index c8b3aa1099adfc..c39741f33ac807 100644 Binary files a/Doc/using/mac_installer_07_applications.png and b/Doc/using/mac_installer_07_applications.png differ diff --git a/Doc/using/mac_installer_08_install_certificates.png b/Doc/using/mac_installer_08_install_certificates.png index c125eeb18aa0c1..f476c7f37d245d 100644 Binary files a/Doc/using/mac_installer_08_install_certificates.png and b/Doc/using/mac_installer_08_install_certificates.png differ diff --git a/Doc/using/mac_installer_09_custom_install_free_threaded.png b/Doc/using/mac_installer_09_custom_install_free_threaded.png index 0f69c55eddb228..e867e422e42e48 100644 Binary files a/Doc/using/mac_installer_09_custom_install_free_threaded.png and b/Doc/using/mac_installer_09_custom_install_free_threaded.png differ diff --git a/Include/internal/pycore_interp_structs.h b/Include/internal/pycore_interp_structs.h index 0623adce693d46..3d577ff717cc6e 100644 --- a/Include/internal/pycore_interp_structs.h +++ b/Include/internal/pycore_interp_structs.h @@ -977,6 +977,7 @@ struct _is { struct _obmalloc_state *obmalloc; PyObject *audit_hooks; + PyMutex audit_hooks_mutex; PyType_WatchCallback type_watchers[TYPE_MAX_WATCHERS]; PyCode_WatchCallback code_watchers[CODE_MAX_WATCHERS]; PyContext_WatchCallback context_watchers[CONTEXT_MAX_WATCHERS]; diff --git a/Lib/csv.py b/Lib/csv.py index 505e9e501e6772..a84234f110dd70 100644 --- a/Lib/csv.py +++ b/Lib/csv.py @@ -260,6 +260,10 @@ def sniff(self, sample, delimiters=None): beginning, then, after eliminating the combinations which are clearly worse than the leader, a several times larger part, and so on. + + If several combinations fit the sample equally well, the + delimiters listed in the preferred attribute are preferred, in + that order, no matter how many times each of them occurs. """ import re from collections import defaultdict diff --git a/Lib/stat.py b/Lib/stat.py index 214c7917b5e048..76f02d7aa33d16 100644 --- a/Lib/stat.py +++ b/Lib/stat.py @@ -1,7 +1,4 @@ -"""Constants/functions for interpreting results of os.stat() and os.lstat(). - -Suggested usage: from stat import * -""" +"""Constants/functions for interpreting results of os.stat() and os.lstat().""" # Indices for stat struct members in the tuple returned by os.stat() diff --git a/Lib/test/test_free_threading/test_sys.py b/Lib/test/test_free_threading/test_sys.py index 271fdd13c62b66..b8ba933cb01adc 100644 --- a/Lib/test/test_free_threading/test_sys.py +++ b/Lib/test/test_free_threading/test_sys.py @@ -44,6 +44,20 @@ def worker(worker_id): workers = [lambda: worker(i) for i in range(5)] threading_helper.run_concurrently(workers) + def test_sys_audit_hooks(self): + def _hook(*args): + return None + + def adder(): + for _ in range(100): + sys.addaudithook(_hook) + + def auditor(): + for _ in range(2000): + sys.audit("fusil.tsan.test") + + threading_helper.run_concurrently([adder, auditor]) + if __name__ == "__main__": unittest.main() diff --git a/Misc/NEWS.d/next/Library/2026-07-22-12-42-53.gh-issue-154431.U2kXXZ.rst b/Misc/NEWS.d/next/Library/2026-07-22-12-42-53.gh-issue-154431.U2kXXZ.rst new file mode 100644 index 00000000000000..a56c3b3a6f21f3 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-07-22-12-42-53.gh-issue-154431.U2kXXZ.rst @@ -0,0 +1 @@ +Fixes a data race in free-threading build in :func:`sys.addaudithook`. diff --git a/Misc/NEWS.d/next/Library/2026-07-22-13-00-00.gh-issue-154460.wCsFtM.rst b/Misc/NEWS.d/next/Library/2026-07-22-13-00-00.gh-issue-154460.wCsFtM.rst new file mode 100644 index 00000000000000..b0a7058f0519ff --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-07-22-13-00-00.gh-issue-154460.wCsFtM.rst @@ -0,0 +1,2 @@ +Fix :func:`time.strftime` and :meth:`datetime.datetime.strftime` returning a +wrong ISO 8601 week number (``%V``) on OpenBSD. diff --git a/Modules/timemodule.c b/Modules/timemodule.c index d90bf1f2ef90ed..70d7e1b3713687 100644 --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -763,6 +763,13 @@ Other codes may be available on your platform. See documentation for\n\ the C library strftime function.\n" #ifdef HAVE_STRFTIME +// gh-154460: OpenBSD's wcsftime() computes %V incorrectly: it returns 53 +// whenever the ISO 8601 week belongs to a different year than tm_year. +// strftime() is not affected. +#ifdef __OpenBSD__ +# undef HAVE_WCSFTIME +#endif + #ifdef HAVE_WCSFTIME #define time_char wchar_t #define format_time wcsftime diff --git a/Python/pystate.c b/Python/pystate.c index d10b38def32911..b6c34552e94337 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -578,6 +578,7 @@ init_interpreter(PyInterpreterState *interp, llist_init(&interp->mem_free_queue.head); llist_init(&interp->asyncio_tasks_head); interp->asyncio_tasks_lock = (PyMutex){0}; + interp->audit_hooks_mutex = (PyMutex){0}; for (int i = 0; i < _PY_MONITORING_UNGROUPED_EVENTS; i++) { interp->monitors.tools[i] = 0; } diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 9442472b53abbe..207ccbce41d71d 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -236,7 +236,7 @@ should_audit(PyInterpreterState *interp) return 0; } return (interp->runtime->audit_hooks.head - || interp->audit_hooks + || FT_ATOMIC_LOAD_PTR_ACQUIRE(interp->audit_hooks) || PyDTrace_AUDIT_ENABLED()); } @@ -306,13 +306,14 @@ sys_audit_tstate(PyThreadState *ts, const char *event, } /* Call interpreter hooks */ - if (is->audit_hooks) { + PyObject *audit_hooks = FT_ATOMIC_LOAD_PTR_ACQUIRE(is->audit_hooks); + if (audit_hooks) { eventName = PyUnicode_FromString(event); if (!eventName) { goto exit; } - hooks = PyObject_GetIter(is->audit_hooks); + hooks = PyObject_GetIter(audit_hooks); if (!hooks) { goto exit; } @@ -536,20 +537,29 @@ sys_addaudithook_impl(PyObject *module, PyObject *hook) } PyInterpreterState *interp = tstate->interp; + PyMutex mutex = interp->audit_hooks_mutex; + PyMutex_Lock(&mutex); + if (interp->audit_hooks == NULL) { - interp->audit_hooks = PyList_New(0); - if (interp->audit_hooks == NULL) { - return NULL; + PyObject *new_list = PyList_New(0); + if (new_list == NULL) { + goto error; } /* Avoid having our list of hooks show up in the GC module */ - PyObject_GC_UnTrack(interp->audit_hooks); + PyObject_GC_UnTrack(new_list); + FT_ATOMIC_STORE_PTR_RELEASE(interp->audit_hooks, new_list); } if (PyList_Append(interp->audit_hooks, hook) < 0) { - return NULL; + goto error; } + PyMutex_Unlock(&mutex); Py_RETURN_NONE; + +error: + PyMutex_Unlock(&mutex); + return NULL; } /*[clinic input] diff --git a/configure b/configure index 58f3dfc119ec13..08b493311a3f92 100755 --- a/configure +++ b/configure @@ -1102,6 +1102,7 @@ enable_framework with_app_store_compliance enable_wasm_dynamic_linking enable_wasm_pthreads +enable_emscripten_syscalls with_suffix enable_shared with_static_libpython @@ -1843,6 +1844,10 @@ Optional Features: loader to handle imports --enable-wasm-pthreads Enable pthread emulation for WebAssembly (default is no) + --disable-emscripten-syscalls + Disable the Emscripten syscall overrides in + Python/emscripten_syscalls.c (default is enabled for + Emscripten) --enable-shared enable building a shared Python library (default is no) --enable-static-libpython-for-interpreter @@ -7620,6 +7625,30 @@ fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $enable_wasm_pthreads" >&5 printf "%s\n" "$enable_wasm_pthreads" >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for --enable-emscripten-syscalls" >&5 +printf %s "checking for --enable-emscripten-syscalls... " >&6; } +# Check whether --enable-emscripten-syscalls was given. +if test ${enable_emscripten_syscalls+y} +then : + enableval=$enable_emscripten_syscalls; + case $ac_sys_system in #( + Emscripten) : + ;; #( + *) : + as_fn_error $? "--enable-emscripten-syscalls only applies to Emscripten" "$LINENO" 5 + ;; +esac + +else case e in #( + e) + enable_emscripten_syscalls=yes + ;; +esac +fi + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $enable_emscripten_syscalls" >&5 +printf "%s\n" "$enable_emscripten_syscalls" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for --with-suffix" >&5 printf %s "checking for --with-suffix... " >&6; } @@ -20159,7 +20188,13 @@ PLATFORM_OBJS= case $ac_sys_system in #( Emscripten) : - as_fn_append PLATFORM_OBJS ' Python/emscripten_signal.o Python/emscripten_trampoline.o Python/emscripten_trampoline_wasm.o Python/emscripten_syscalls.o' + as_fn_append PLATFORM_OBJS ' Python/emscripten_signal.o Python/emscripten_trampoline.o Python/emscripten_trampoline_wasm.o' + if test "x$enable_emscripten_syscalls" = xyes +then : + + as_fn_append PLATFORM_OBJS ' Python/emscripten_syscalls.o' + +fi as_fn_append PLATFORM_HEADERS ' $(srcdir)/Include/internal/pycore_emscripten_signal.h $(srcdir)/Include/internal/pycore_emscripten_trampoline.h' ;; #( *) : diff --git a/configure.ac b/configure.ac index 273a64814f9a1f..f40db5bc82e24a 100644 --- a/configure.ac +++ b/configure.ac @@ -1365,6 +1365,20 @@ AC_ARG_ENABLE([wasm-pthreads], ]) AC_MSG_RESULT([$enable_wasm_pthreads]) +AC_MSG_CHECKING([for --enable-emscripten-syscalls]) +AC_ARG_ENABLE([emscripten-syscalls], + [AS_HELP_STRING([--disable-emscripten-syscalls], + [Disable the Emscripten syscall overrides in Python/emscripten_syscalls.c (default is enabled for Emscripten)])], +[ + AS_CASE([$ac_sys_system], + [Emscripten], [], + [AC_MSG_ERROR([--enable-emscripten-syscalls only applies to Emscripten])] + ) +], [ + enable_emscripten_syscalls=yes +]) +AC_MSG_RESULT([$enable_emscripten_syscalls]) + AC_MSG_CHECKING([for --with-suffix]) AC_ARG_WITH([suffix], [AS_HELP_STRING([--with-suffix=SUFFIX], [set executable suffix to SUFFIX (default is empty, yes is mapped to '.exe')])], @@ -5380,7 +5394,10 @@ PLATFORM_OBJS= AS_CASE([$ac_sys_system], [Emscripten], [ - AS_VAR_APPEND([PLATFORM_OBJS], [' Python/emscripten_signal.o Python/emscripten_trampoline.o Python/emscripten_trampoline_wasm.o Python/emscripten_syscalls.o']) + AS_VAR_APPEND([PLATFORM_OBJS], [' Python/emscripten_signal.o Python/emscripten_trampoline.o Python/emscripten_trampoline_wasm.o']) + AS_VAR_IF([enable_emscripten_syscalls], [yes], [ + AS_VAR_APPEND([PLATFORM_OBJS], [' Python/emscripten_syscalls.o']) + ]) AS_VAR_APPEND([PLATFORM_HEADERS], [' $(srcdir)/Include/internal/pycore_emscripten_signal.h $(srcdir)/Include/internal/pycore_emscripten_trampoline.h']) ], )