diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 8bc40fcb9e8999..e8f4a4693a814c 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -13,6 +13,8 @@ # Build system configure* @erlend-aasland @corona10 +Makefile.pre.in @erlend-aasland +Modules/Setup* @erlend-aasland # asyncio **/*asyncio* @1st1 @asvetlov @gvanrossum @kumaraditya303 @willingc @@ -40,7 +42,7 @@ Python/bytecodes.c @markshannon Python/optimizer*.c @markshannon Python/optimizer_analysis.c @Fidget-Spinner Python/optimizer_bytecodes.c @Fidget-Spinner -Python/symtable.c @JelleZijlstra @carljm +Python/symtable.c @JelleZijlstra @carljm Lib/_pyrepl/* @pablogsal @lysnikolaou @ambv Lib/test/test_patma.py @brandtbucher Lib/test/test_type_*.py @JelleZijlstra @@ -199,7 +201,6 @@ Doc/c-api/stable.rst @encukou **/*itertools* @rhettinger **/*collections* @rhettinger **/*random* @rhettinger -**/*queue* @rhettinger **/*bisect* @rhettinger **/*heapq* @rhettinger **/*functools* @rhettinger @@ -210,6 +211,7 @@ Doc/c-api/stable.rst @encukou **/*ensurepip* @pfmoore @pradyunsg **/*idlelib* @terryjreedy +/Doc/library/idle.rst @terryjreedy **/*typing* @JelleZijlstra @AlexWaygood diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index eb325ac2f9ee1b..750aa1ed87bca1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -54,7 +54,7 @@ jobs: # into the PR branch anyway. # # https://github.com/python/core-workflow/issues/373 - git diff --name-only origin/$GITHUB_BASE_REF.. | grep -qvE '(\.rst$|^Doc|^Misc|^\.pre-commit-config\.yaml$|\.ruff\.toml$)' && echo "run_tests=true" >> $GITHUB_OUTPUT || true + git diff --name-only origin/$GITHUB_BASE_REF.. | grep -qvE '(\.rst$|^Doc|^Misc|^\.pre-commit-config\.yaml$|\.ruff\.toml$|\.md$|mypy\.ini$)' && echo "run_tests=true" >> $GITHUB_OUTPUT || true fi # Check if we should run hypothesis tests diff --git a/.github/workflows/jit.yml b/.github/workflows/jit.yml index 8c760a81d52662..5e3ac9e9e0fada 100644 --- a/.github/workflows/jit.yml +++ b/.github/workflows/jit.yml @@ -133,17 +133,15 @@ jobs: make all --jobs 4 ./python.exe -m test --multiprocess 0 --timeout 4500 --verbose2 --verbose3 - # --with-lto has been removed temporarily as a result of an open issue in LLVM 18 (see https://github.com/llvm/llvm-project/issues/87553) - name: Native Linux if: runner.os == 'Linux' && matrix.architecture == 'x86_64' run: | sudo bash -c "$(wget -O - https://apt.llvm.org/llvm.sh)" ./llvm.sh ${{ matrix.llvm }} export PATH="$(llvm-config-${{ matrix.llvm }} --bindir):$PATH" - ./configure --enable-experimental-jit ${{ matrix.debug && '--with-pydebug' || '--enable-optimizations' }} + ./configure --enable-experimental-jit ${{ matrix.debug && '--with-pydebug' || '--enable-optimizations --with-lto' }} make all --jobs 4 ./python -m test --multiprocess 0 --timeout 4500 --verbose2 --verbose3 - # --with-lto has been removed temporarily as a result of an open issue in LLVM 18 (see https://github.com/llvm/llvm-project/issues/87553) - name: Emulated Linux if: runner.os == 'Linux' && matrix.architecture != 'x86_64' # The --ignorefile on ./python -m test is used to exclude tests known to fail when running on an emulated Linux. @@ -161,7 +159,7 @@ jobs: CC="${{ matrix.compiler == 'clang' && 'clang --target=$HOST' || '$HOST-gcc' }}" \ CPP="$CC --preprocess" \ HOSTRUNNER=qemu-${{ matrix.architecture }} \ - ./configure --enable-experimental-jit ${{ matrix.debug && '--with-pydebug' || '--enable-optimizations ' }} --build=x86_64-linux-gnu --host="$HOST" --with-build-python=../build/bin/python3 --with-pkg-config=no ac_cv_buggy_getaddrinfo=no ac_cv_file__dev_ptc=no ac_cv_file__dev_ptmx=yes + ./configure --enable-experimental-jit ${{ matrix.debug && '--with-pydebug' || '--enable-optimizations --with-lto' }} --build=x86_64-linux-gnu --host="$HOST" --with-build-python=../build/bin/python3 --with-pkg-config=no ac_cv_buggy_getaddrinfo=no ac_cv_file__dev_ptc=no ac_cv_file__dev_ptmx=yes make all --jobs 4 ./python -m test --ignorefile=Tools/jit/ignore-tests-emulated-linux.txt --multiprocess 0 --timeout 4500 --verbose2 --verbose3 diff --git a/.readthedocs.yml b/.readthedocs.yml index 59830c79a404e0..d0d0c3b93ed207 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -26,6 +26,9 @@ build: exit 183; fi + - asdf plugin add uv + - asdf install uv latest + - asdf global uv latest - make -C Doc venv html - mkdir _readthedocs - mv Doc/build/html _readthedocs/html diff --git a/Doc/Makefile b/Doc/Makefile index 1cbfc722b010f5..c70768754834dd 100644 --- a/Doc/Makefile +++ b/Doc/Makefile @@ -152,7 +152,7 @@ htmlview: html .PHONY: ensure-sphinx-autobuild ensure-sphinx-autobuild: venv - $(VENVDIR)/bin/sphinx-autobuild --version > /dev/null || $(VENVDIR)/bin/python3 -m pip install sphinx-autobuild + $(call ensure_package,sphinx-autobuild) .PHONY: htmllive htmllive: SPHINXBUILD = $(VENVDIR)/bin/sphinx-autobuild @@ -174,10 +174,15 @@ venv: echo "To recreate it, remove it first with \`make clean-venv'."; \ else \ echo "Creating venv in $(VENVDIR)"; \ - $(PYTHON) -m venv $(VENVDIR); \ - $(VENVDIR)/bin/python3 -m pip install --upgrade pip; \ - $(VENVDIR)/bin/python3 -m pip install -r $(REQUIREMENTS); \ - echo "The venv has been created in the $(VENVDIR) directory"; \ + if uv --version > /dev/null; then \ + uv venv $(VENVDIR); \ + VIRTUAL_ENV=$(VENVDIR) uv pip install -r $(REQUIREMENTS); \ + else \ + $(PYTHON) -m venv $(VENVDIR); \ + $(VENVDIR)/bin/python3 -m pip install --upgrade pip; \ + $(VENVDIR)/bin/python3 -m pip install -r $(REQUIREMENTS); \ + echo "The venv has been created in the $(VENVDIR) directory"; \ + fi; \ fi .PHONY: dist @@ -235,9 +240,17 @@ dist: rm -r dist/python-$(DISTVERSION)-docs-texinfo rm dist/python-$(DISTVERSION)-docs-texinfo.tar +define ensure_package + if uv --version > /dev/null; then \ + $(VENVDIR)/bin/python3 -m $(1) --version > /dev/null || VIRTUAL_ENV=$(VENVDIR) uv pip install $(1); \ + else \ + $(VENVDIR)/bin/python3 -m $(1) --version > /dev/null || $(VENVDIR)/bin/python3 -m pip install $(1); \ + fi +endef + .PHONY: check check: venv - $(VENVDIR)/bin/python3 -m pre_commit --version > /dev/null || $(VENVDIR)/bin/python3 -m pip install pre-commit + $(call ensure_package,pre_commit) $(VENVDIR)/bin/python3 -m pre_commit run --all-files .PHONY: serve diff --git a/Doc/README.rst b/Doc/README.rst index a3bb5fa5445c23..efcee0db428908 100644 --- a/Doc/README.rst +++ b/Doc/README.rst @@ -28,7 +28,7 @@ install the tools into there. Using make ---------- -To get started on UNIX, you can create a virtual environment and build +To get started on Unix, you can create a virtual environment and build documentation with the commands:: make venv @@ -40,13 +40,13 @@ If you'd like to create the virtual environment in a different location, you can specify it using the ``VENVDIR`` variable. You can also skip creating the virtual environment altogether, in which case -the Makefile will look for instances of ``sphinx-build`` and ``blurb`` +the ``Makefile`` will look for instances of ``sphinx-build`` and ``blurb`` installed on your process ``PATH`` (configurable with the ``SPHINXBUILD`` and ``BLURB`` variables). -On Windows, we try to emulate the Makefile as closely as possible with a +On Windows, we try to emulate the ``Makefile`` as closely as possible with a ``make.bat`` file. If you need to specify the Python interpreter to use, -set the PYTHON environment variable. +set the ``PYTHON`` environment variable. Available make targets are: @@ -62,15 +62,19 @@ Available make targets are: * "htmlview", which re-uses the "html" builder, but then opens the main page in your default web browser. +* "htmllive", which re-uses the "html" builder, rebuilds the docs, + starts a local server, and automatically reloads the page in your browser + when you make changes to reST files (Unix only). + * "htmlhelp", which builds HTML files and a HTML Help project file usable to convert them into a single Compiled HTML (.chm) file -- these are popular under Microsoft Windows, but very handy on every platform. To create the CHM file, you need to run the Microsoft HTML Help Workshop - over the generated project (.hhp) file. The make.bat script does this for + over the generated project (.hhp) file. The ``make.bat`` script does this for you on Windows. -* "latex", which builds LaTeX source files as input to "pdflatex" to produce +* "latex", which builds LaTeX source files as input to ``pdflatex`` to produce PDF documents. * "text", which builds a plain text file for each source file. @@ -95,8 +99,6 @@ Available make targets are: * "check", which checks for frequent markup errors. -* "serve", which serves the build/html directory on port 8000. - * "dist", (Unix only) which creates distributable archives of HTML, text, PDF, and EPUB builds. diff --git a/Doc/c-api/dict.rst b/Doc/c-api/dict.rst index 49a78583a6fe26..b4fdf47bc915bd 100644 --- a/Doc/c-api/dict.rst +++ b/Doc/c-api/dict.rst @@ -290,6 +290,17 @@ Dictionary Objects Py_DECREF(o); } + The function is not thread-safe in the :term:`free-threaded ` + build without external synchronization. You can use + :c:macro:`Py_BEGIN_CRITICAL_SECTION` to lock the dictionary while iterating + over it:: + + Py_BEGIN_CRITICAL_SECTION(self->dict); + while (PyDict_Next(self->dict, &pos, &key, &value)) { + ... + } + Py_END_CRITICAL_SECTION(); + .. c:function:: int PyDict_Merge(PyObject *a, PyObject *b, int override) diff --git a/Doc/c-api/init.rst b/Doc/c-api/init.rst index 9e118d4f36145f..1fab3f577f2f89 100644 --- a/Doc/c-api/init.rst +++ b/Doc/c-api/init.rst @@ -55,6 +55,11 @@ The following functions can be safely called before Python is initialized: * :c:func:`PyMem_RawCalloc` * :c:func:`PyMem_RawFree` +* Synchronization: + + * :c:func:`PyMutex_Lock` + * :c:func:`PyMutex_Unlock` + .. note:: The following functions **should not be called** before @@ -391,9 +396,16 @@ Initializing and finalizing the interpreter :c:func:`Py_NewInterpreter` below) that were created and not yet destroyed since the last call to :c:func:`Py_Initialize`. Ideally, this frees all memory allocated by the Python interpreter. This is a no-op when called for a second - time (without calling :c:func:`Py_Initialize` again first). Normally the - return value is ``0``. If there were errors during finalization - (flushing buffered data), ``-1`` is returned. + time (without calling :c:func:`Py_Initialize` again first). + + Since this is the reverse of :c:func:`Py_Initialize`, it should be called + in the same thread with the same interpreter active. That means + the main thread and the main interpreter. + This should never be called while :c:func:`Py_RunMain` is running. + + Normally the return value is ``0``. + If there were errors during finalization (flushing buffered data), + ``-1`` is returned. This function is provided for a number of reasons. An embedding application might want to restart Python without having to restart the application itself. @@ -2152,3 +2164,145 @@ be used in new code. .. c:function:: void PyThread_delete_key_value(int key) .. c:function:: void PyThread_ReInitTLS() +Synchronization Primitives +========================== + +The C-API provides a basic mutual exclusion lock. + +.. c:type:: PyMutex + + A mutual exclusion lock. The :c:type:`!PyMutex` should be initialized to + zero to represent the unlocked state. For example:: + + PyMutex mutex = {0}; + + Instances of :c:type:`!PyMutex` should not be copied or moved. Both the + contents and address of a :c:type:`!PyMutex` are meaningful, and it must + remain at a fixed, writable location in memory. + + .. note:: + + A :c:type:`!PyMutex` currently occupies one byte, but the size should be + considered unstable. The size may change in future Python releases + without a deprecation period. + + .. versionadded:: 3.13 + +.. c:function:: void PyMutex_Lock(PyMutex *m) + + Lock mutex *m*. If another thread has already locked it, the calling + thread will block until the mutex is unlocked. While blocked, the thread + will temporarily release the :term:`GIL` if it is held. + + .. versionadded:: 3.13 + +.. c:function:: void PyMutex_Unlock(PyMutex *m) + + Unlock mutex *m*. The mutex must be locked --- otherwise, the function will + issue a fatal error. + + .. versionadded:: 3.13 + +.. _python-critical-section-api: + +Python Critical Section API +--------------------------- + +The critical section API provides a deadlock avoidance layer on top of +per-object locks for :term:`free-threaded ` CPython. They are +intended to replace reliance on the :term:`global interpreter lock`, and are +no-ops in versions of Python with the global interpreter lock. + +Critical sections avoid deadlocks by implicitly suspending active critical +sections and releasing the locks during calls to :c:func:`PyEval_SaveThread`. +When :c:func:`PyEval_RestoreThread` is called, the most recent critical section +is resumed, and its locks reacquired. This means the critical section API +provides weaker guarantees than traditional locks -- they are useful because +their behavior is similar to the :term:`GIL`. + +The functions and structs used by the macros are exposed for cases +where C macros are not available. They should only be used as in the +given macro expansions. Note that the sizes and contents of the structures may +change in future Python versions. + +.. note:: + + Operations that need to lock two objects at once must use + :c:macro:`Py_BEGIN_CRITICAL_SECTION2`. You *cannot* use nested critical + sections to lock more than one object at once, because the inner critical + section may suspend the outer critical sections. This API does not provide + a way to lock more than two objects at once. + +Example usage:: + + static PyObject * + set_field(MyObject *self, PyObject *value) + { + Py_BEGIN_CRITICAL_SECTION(self); + Py_SETREF(self->field, Py_XNewRef(value)); + Py_END_CRITICAL_SECTION(); + Py_RETURN_NONE; + } + +In the above example, :c:macro:`Py_SETREF` calls :c:macro:`Py_DECREF`, which +can call arbitrary code through an object's deallocation function. The critical +section API avoids potentital deadlocks due to reentrancy and lock ordering +by allowing the runtime to temporarily suspend the critical section if the +code triggered by the finalizer blocks and calls :c:func:`PyEval_SaveThread`. + +.. c:macro:: Py_BEGIN_CRITICAL_SECTION(op) + + Acquires the per-object lock for the object *op* and begins a + critical section. + + In the free-threaded build, this macro expands to:: + + { + PyCriticalSection _py_cs; + PyCriticalSection_Begin(&_py_cs, (PyObject*)(op)) + + In the default build, this macro expands to ``{``. + + .. versionadded:: 3.13 + +.. c:macro:: Py_END_CRITICAL_SECTION() + + Ends the critical section and releases the per-object lock. + + In the free-threaded build, this macro expands to:: + + PyCriticalSection_End(&_py_cs); + } + + In the default build, this macro expands to ``}``. + + .. versionadded:: 3.13 + +.. c:macro:: Py_BEGIN_CRITICAL_SECTION2(a, b) + + Acquires the per-objects locks for the objects *a* and *b* and begins a + critical section. The locks are acquired in a consistent order (lowest + address first) to avoid lock ordering deadlocks. + + In the free-threaded build, this macro expands to:: + + { + PyCriticalSection2 _py_cs2; + PyCriticalSection_Begin2(&_py_cs2, (PyObject*)(a), (PyObject*)(b)) + + In the default build, this macro expands to ``{``. + + .. versionadded:: 3.13 + +.. c:macro:: Py_END_CRITICAL_SECTION2() + + Ends the critical section and releases the per-object locks. + + In the free-threaded build, this macro expands to:: + + PyCriticalSection_End2(&_py_cs2); + } + + In the default build, this macro expands to ``}``. + + .. versionadded:: 3.13 diff --git a/Doc/c-api/typeobj.rst b/Doc/c-api/typeobj.rst index a6a2c437ea4e16..c9ef076c78c66a 100644 --- a/Doc/c-api/typeobj.rst +++ b/Doc/c-api/typeobj.rst @@ -1328,8 +1328,8 @@ and :c:data:`PyType_Type` effectively act as defaults.) To indicate that a class has changed call :c:func:`PyType_Modified` .. warning:: - This flag is present in header files, but is an internal feature and should - not be used. It will be removed in a future version of CPython + This flag is present in header files, but is not be used. + It will be removed in a future version of CPython .. c:member:: const char* PyTypeObject.tp_doc diff --git a/Doc/c-api/unicode.rst b/Doc/c-api/unicode.rst index 7320d035bab513..246cf47df62e78 100644 --- a/Doc/c-api/unicode.rst +++ b/Doc/c-api/unicode.rst @@ -1502,3 +1502,125 @@ They all return ``NULL`` or ``-1`` if an exception occurs. :c:func:`PyUnicode_InternInPlace`, returning either a new Unicode string object that has been interned, or a new ("owned") reference to an earlier interned string object with the same value. + +PyUnicodeWriter +^^^^^^^^^^^^^^^ + +The :c:type:`PyUnicodeWriter` API can be used to create a Python :class:`str` +object. + +.. versionadded:: 3.14 + +.. c:type:: PyUnicodeWriter + + A Unicode writer instance. + + The instance must be destroyed by :c:func:`PyUnicodeWriter_Finish` on + success, or :c:func:`PyUnicodeWriter_Discard` on error. + +.. c:function:: PyUnicodeWriter* PyUnicodeWriter_Create(Py_ssize_t length) + + Create a Unicode writer instance. + + Set an exception and return ``NULL`` on error. + +.. c:function:: PyObject* PyUnicodeWriter_Finish(PyUnicodeWriter *writer) + + Return the final Python :class:`str` object and destroy the writer instance. + + Set an exception and return ``NULL`` on error. + +.. c:function:: void PyUnicodeWriter_Discard(PyUnicodeWriter *writer) + + Discard the internal Unicode buffer and destroy the writer instance. + +.. c:function:: int PyUnicodeWriter_WriteChar(PyUnicodeWriter *writer, Py_UCS4 ch) + + Write the single Unicode character *ch* into *writer*. + + On success, return ``0``. + On error, set an exception, leave the writer unchanged, and return ``-1``. + +.. c:function:: int PyUnicodeWriter_WriteUTF8(PyUnicodeWriter *writer, const char *str, Py_ssize_t size) + + Decode the string *str* from UTF-8 in strict mode and write the output into *writer*. + + *size* is the string length in bytes. If *size* is equal to ``-1``, call + ``strlen(str)`` to get the string length. + + On success, return ``0``. + On error, set an exception, leave the writer unchanged, and return ``-1``. + + See also :c:func:`PyUnicodeWriter_DecodeUTF8Stateful`. + +.. c:function:: int PyUnicodeWriter_WriteWideChar(PyUnicodeWriter *writer, const wchar_t *str, Py_ssize_t size) + + Writer the wide string *str* into *writer*. + + *size* is a number of wide characters. If *size* is equal to ``-1``, call + ``wcslen(str)`` to get the string length. + + On success, return ``0``. + On error, set an exception, leave the writer unchanged, and return ``-1``. + +.. c:function:: int PyUnicodeWriter_WriteUCS4(PyUnicodeWriter *writer, Py_UCS4 *str, Py_ssize_t size) + + Writer the UCS4 string *str* into *writer*. + + *size* is a number of UCS4 characters. + + On success, return ``0``. + On error, set an exception, leave the writer unchanged, and return ``-1``. + +.. c:function:: int PyUnicodeWriter_WriteStr(PyUnicodeWriter *writer, PyObject *obj) + + Call :c:func:`PyObject_Str` on *obj* and write the output into *writer*. + + On success, return ``0``. + On error, set an exception, leave the writer unchanged, and return ``-1``. + +.. c:function:: int PyUnicodeWriter_WriteRepr(PyUnicodeWriter *writer, PyObject *obj) + + Call :c:func:`PyObject_Repr` on *obj* and write the output into *writer*. + + On success, return ``0``. + On error, set an exception, leave the writer unchanged, and return ``-1``. + +.. c:function:: int PyUnicodeWriter_WriteSubstring(PyUnicodeWriter *writer, PyObject *str, Py_ssize_t start, Py_ssize_t end) + + Write the substring ``str[start:end]`` into *writer*. + + *str* must be Python :class:`str` object. *start* must be greater than or + equal to 0, and less than or equal to *end*. *end* must be less than or + equal to *str* length. + + On success, return ``0``. + On error, set an exception, leave the writer unchanged, and return ``-1``. + +.. c:function:: int PyUnicodeWriter_Format(PyUnicodeWriter *writer, const char *format, ...) + + Similar to :c:func:`PyUnicode_FromFormat`, but write the output directly into *writer*. + + On success, return ``0``. + On error, set an exception, leave the writer unchanged, and return ``-1``. + +.. c:function:: int PyUnicodeWriter_DecodeUTF8Stateful(PyUnicodeWriter *writer, const char *string, Py_ssize_t length, const char *errors, Py_ssize_t *consumed) + + Decode the string *str* from UTF-8 with *errors* error handler and write the + output into *writer*. + + *size* is the string length in bytes. If *size* is equal to ``-1``, call + ``strlen(str)`` to get the string length. + + *errors* is an error handler name, such as ``"replace"``. If *errors* is + ``NULL``, use the strict error handler. + + If *consumed* is not ``NULL``, set *\*consumed* to the number of decoded + bytes on success. + If *consumed* is ``NULL``, treat trailing incomplete UTF-8 byte sequences + as an error. + + On success, return ``0``. + On error, set an exception, leave the writer unchanged, and return ``-1``. + + See also :c:func:`PyUnicodeWriter_WriteUTF8`. diff --git a/Doc/c-api/weakref.rst b/Doc/c-api/weakref.rst index ae0699383900c4..8f233e16fb17cf 100644 --- a/Doc/c-api/weakref.rst +++ b/Doc/c-api/weakref.rst @@ -96,3 +96,19 @@ as much as it can. This iterates through the weak references for *object* and calls callbacks for those references which have one. It returns when all callbacks have been attempted. + + +.. c:function:: void PyUnstable_Object_ClearWeakRefsNoCallbacks(PyObject *object) + + Clears the weakrefs for *object* without calling the callbacks. + + This function is called by the :c:member:`~PyTypeObject.tp_dealloc` handler + for types with finalizers (i.e., :meth:`~object.__del__`). The handler for + those objects first calls :c:func:`PyObject_ClearWeakRefs` to clear weakrefs + and call their callbacks, then the finalizer, and finally this function to + clear any weakrefs that may have been created by the finalizer. + + In most circumstances, it's more appropriate to use + :c:func:`PyObject_ClearWeakRefs` to clear weakrefs instead of this function. + + .. versionadded:: 3.13 diff --git a/Doc/data/stable_abi.dat b/Doc/data/stable_abi.dat index 76a035f194d911..1f7af436a4150b 100644 --- a/Doc/data/stable_abi.dat +++ b/Doc/data/stable_abi.dat @@ -226,7 +226,6 @@ var,PyExc_GeneratorExit,3.2,, var,PyExc_IOError,3.2,, var,PyExc_ImportError,3.2,, var,PyExc_ImportWarning,3.2,, -var,PyExc_IncompleteInputError,3.13,, var,PyExc_IndentationError,3.2,, var,PyExc_IndexError,3.2,, var,PyExc_InterruptedError,3.7,, @@ -877,6 +876,7 @@ function,Py_ReprLeave,3.2,, function,Py_SetProgramName,3.2,, function,Py_SetPythonHome,3.2,, function,Py_SetRecursionLimit,3.2,, +function,Py_TYPE,3.14,, type,Py_UCS4,3.2,, macro,Py_UNBLOCK_THREADS,3.2,, var,Py_UTF8Mode,3.8,, diff --git a/Doc/glossary.rst b/Doc/glossary.rst index 8685369117fd87..281dde30dc78ed 100644 --- a/Doc/glossary.rst +++ b/Doc/glossary.rst @@ -694,6 +694,9 @@ Glossary CPython does not consistently apply the requirement that an iterator define :meth:`~iterator.__iter__`. + And also please note that the free-threading CPython does not guarantee + the thread-safety of iterator operations. + key function A key function or collation function is a callable that returns a value diff --git a/Doc/howto/descriptor.rst b/Doc/howto/descriptor.rst index 51f9f4a6556e57..b29488be39a0a3 100644 --- a/Doc/howto/descriptor.rst +++ b/Doc/howto/descriptor.rst @@ -787,7 +787,7 @@ Invocation from super --------------------- The logic for super's dotted lookup is in the :meth:`__getattribute__` method for -object returned by :class:`super()`. +object returned by :func:`super`. A dotted lookup such as ``super(A, obj).m`` searches ``obj.__class__.__mro__`` for the base class ``B`` immediately following ``A`` and then returns diff --git a/Doc/howto/enum.rst b/Doc/howto/enum.rst index 30be15230fc088..18e13fcf9f59bd 100644 --- a/Doc/howto/enum.rst +++ b/Doc/howto/enum.rst @@ -1,3 +1,5 @@ +.. _enum-howto: + ========== Enum HOWTO ========== @@ -1150,6 +1152,14 @@ the following are true: >>> (Color.RED | Color.GREEN).name 'RED|GREEN' + >>> class Perm(IntFlag): + ... R = 4 + ... W = 2 + ... X = 1 + ... + >>> (Perm.R & Perm.W).name is None # effectively Perm(0) + True + - multi-bit flags, aka aliases, can be returned from operations:: >>> Color.RED | Color.BLUE diff --git a/Doc/howto/free-threading-extensions.rst b/Doc/howto/free-threading-extensions.rst new file mode 100644 index 00000000000000..1ba91b09516f9c --- /dev/null +++ b/Doc/howto/free-threading-extensions.rst @@ -0,0 +1,272 @@ +.. highlight:: c + +.. _freethreading-extensions-howto: + +****************************************** +C API Extension Support for Free Threading +****************************************** + +Starting with the 3.13 release, CPython has experimental support for running +with the :term:`global interpreter lock` (GIL) disabled in a configuration +called :term:`free threading`. This document describes how to adapt C API +extensions to support free threading. + + +Identifying the Free-Threaded Build in C +======================================== + +The CPython C API exposes the ``Py_GIL_DISABLED`` macro: in the free-threaded +build it's defined to ``1``, and in the regular build it's not defined. +You can use it to enable code that only runs under the free-threaded build:: + + #ifdef Py_GIL_DISABLED + /* code that only runs in the free-threaded build */ + #endif + +Module Initialization +===================== + +Extension modules need to explicitly indicate that they support running with +the GIL disabled; otherwise importing the extension will raise a warning and +enable the GIL at runtime. + +There are two ways to indicate that an extension module supports running with +the GIL disabled depending on whether the extension uses multi-phase or +single-phase initialization. + +Multi-Phase Initialization +.......................... + +Extensions that use multi-phase initialization (i.e., +:c:func:`PyModuleDef_Init`) should add a :c:data:`Py_mod_gil` slot in the +module definition. If your extension supports older versions of CPython, +you should guard the slot with a :c:data:`PY_VERSION_HEX` check. + +:: + + static struct PyModuleDef_Slot module_slots[] = { + ... + #if PY_VERSION_HEX >= 0x030D0000 + {Py_mod_gil, Py_MOD_GIL_NOT_USED}, + #endif + {0, NULL} + }; + + static struct PyModuleDef moduledef = { + PyModuleDef_HEAD_INIT, + .m_slots = module_slots, + ... + }; + + +Single-Phase Initialization +........................... + +Extensions that use single-phase initialization (i.e., +:c:func:`PyModule_Create`) should call :c:func:`PyUnstable_Module_SetGIL` to +indicate that they support running with the GIL disabled. The function is +only defined in the free-threaded build, so you should guard the call with +``#ifdef Py_GIL_DISABLED`` to avoid compilation errors in the regular build. + +:: + + static struct PyModuleDef moduledef = { + PyModuleDef_HEAD_INIT, + ... + }; + + PyMODINIT_FUNC + PyInit_mymodule(void) + { + PyObject *m = PyModule_Create(&moduledef); + if (m == NULL) { + return NULL; + } + #ifdef Py_GIL_DISABLED + PyUnstable_Module_SetGIL(m, Py_MOD_GIL_NOT_USED); + #endif + return m; + } + + +General API Guidelines +====================== + +Most of the C API is thread-safe, but there are some exceptions. + +* **Struct Fields**: Accessing fields in Python C API objects or structs + directly is not thread-safe if the field may be concurrently modified. +* **Macros**: Accessor macros like :c:macro:`PyList_GET_ITEM` and + :c:macro:`PyList_SET_ITEM` do not perform any error checking or locking. + These macros are not thread-safe if the container object may be modified + concurrently. +* **Borrowed References**: C API functions that return + :term:`borrowed references ` may not be thread-safe if + the containing object is modified concurrently. See the section on + :ref:`borrowed references ` for more information. + + +Container Thread Safety +....................... + +Containers like :c:struct:`PyListObject`, +:c:struct:`PyDictObject`, and :c:struct:`PySetObject` perform internal locking +in the free-threaded build. For example, the :c:func:`PyList_Append` will +lock the list before appending an item. + +.. _PyDict_Next: + +``PyDict_Next`` +''''''''''''''' + +A notable exception is :c:func:`PyDict_Next`, which does not lock the +dictionary. You should use :c:macro:`Py_BEGIN_CRITICAL_SECTION` to protect +the dictionary while iterating over it if the dictionary may be concurrently +modified:: + + Py_BEGIN_CRITICAL_SECTION(dict); + PyObject *key, *value; + Py_ssize_t pos = 0; + while (PyDict_Next(dict, &pos, &key, &value)) { + ... + } + Py_END_CRITICAL_SECTION(); + + +Borrowed References +=================== + +.. _borrowed-references: + +Some C API functions return :term:`borrowed references `. +These APIs are not thread-safe if the containing object is modified +concurrently. For example, it's not safe to use :c:func:`PyList_GetItem` +if the list may be modified concurrently. + +The following table lists some borrowed reference APIs and their replacements +that return :term:`strong references `. + ++-----------------------------------+-----------------------------------+ +| Borrowed reference API | Strong reference API | ++===================================+===================================+ +| :c:func:`PyList_GetItem` | :c:func:`PyList_GetItemRef` | ++-----------------------------------+-----------------------------------+ +| :c:func:`PyDict_GetItem` | :c:func:`PyDict_GetItemRef` | ++-----------------------------------+-----------------------------------+ +| :c:func:`PyDict_GetItemWithError` | :c:func:`PyDict_GetItemRef` | ++-----------------------------------+-----------------------------------+ +| :c:func:`PyDict_GetItemString` | :c:func:`PyDict_GetItemStringRef` | ++-----------------------------------+-----------------------------------+ +| :c:func:`PyDict_SetDefault` | :c:func:`PyDict_SetDefaultRef` | ++-----------------------------------+-----------------------------------+ +| :c:func:`PyDict_Next` | none (see :ref:`PyDict_Next`) | ++-----------------------------------+-----------------------------------+ +| :c:func:`PyWeakref_GetObject` | :c:func:`PyWeakref_GetRef` | ++-----------------------------------+-----------------------------------+ +| :c:func:`PyWeakref_GET_OBJECT` | :c:func:`PyWeakref_GetRef` | ++-----------------------------------+-----------------------------------+ +| :c:func:`PyImport_AddModule` | :c:func:`PyImport_AddModuleRef` | ++-----------------------------------+-----------------------------------+ + +Not all APIs that return borrowed references are problematic. For +example, :c:func:`PyTuple_GetItem` is safe because tuples are immutable. +Similarly, not all uses of the above APIs are problematic. For example, +:c:func:`PyDict_GetItem` is often used for parsing keyword argument +dictionaries in function calls; those keyword argument dictionaries are +effectively private (not accessible by other threads), so using borrowed +references in that context is safe. + +Some of these functions were added in Python 3.13. You can use the +`pythoncapi-compat `_ package +to provide implementations of these functions for older Python versions. + + +Memory Allocation APIs +====================== + +Python's memory management C API provides functions in three different +:ref:`allocation domains `: "raw", "mem", and "object". +For thread-safety, the free-threaded build requires that only Python objects +are allocated using the object domain, and that all Python object are +allocated using that domain. This differes from the prior Python versions, +where this was only a best practice and not a hard requirement. + +.. note:: + + Search for uses of :c:func:`PyObject_Malloc` in your + extension and check that the allocated memory is used for Python objects. + Use :c:func:`PyMem_Malloc` to allocate buffers instead of + :c:func:`PyObject_Malloc`. + + +Thread State and GIL APIs +========================= + +Python provides a set of functions and macros to manage thread state and the +GIL, such as: + +* :c:func:`PyGILState_Ensure` and :c:func:`PyGILState_Release` +* :c:func:`PyEval_SaveThread` and :c:func:`PyEval_RestoreThread` +* :c:macro:`Py_BEGIN_ALLOW_THREADS` and :c:macro:`Py_END_ALLOW_THREADS` + +These functions should still be used in the free-threaded build to manage +thread state even when the :term:`GIL` is disabled. For example, if you +create a thread outside of Python, you must call :c:func:`PyGILState_Ensure` +before calling into the Python API to ensure that the thread has a valid +Python thread state. + +You should continue to call :c:func:`PyEval_SaveThread` or +:c:macro:`Py_BEGIN_ALLOW_THREADS` around blocking operations, such as I/O or +lock acquisitions, to allow other threads to run the +:term:`cyclic garbage collector `. + + +Protecting Internal Extension State +=================================== + +Your extension may have internal state that was previously protected by the +GIL. You may need to add locking to protect this state. The approach will +depend on your extension, but some common patterns include: + +* **Caches**: global caches are a common source of shared state. Consider + using a lock to protect the cache or disabling it in the free-threaded build + if the cache is not critical for performance. +* **Global State**: global state may need to be protected by a lock or moved + to thread local storage. C11 and C++11 provide the ``thread_local`` or + ``_Thread_local`` for + `thread-local storage `_. + + +Building Extensions for the Free-Threaded Build +=============================================== + +C API extensions need to be built specifically for the free-threaded build. +The wheels, shared libraries, and binaries are indicated by a ``t`` suffix. + +* `pypa/manylinux `_ supports the + free-threaded build, with the ``t`` suffix, such as ``python3.13t``. +* `pypa/cibuildwheel `_ supports the + free-threaded build if you set + `CIBW_FREE_THREADED_SUPPORT `_. + +Limited C API and Stable ABI +............................ + +The free-threaded build does not currently support the +:ref:`Limited C API ` or the stable ABI. If you use +`setuptools `_ to build +your extension and currently set ``py_limited_api=True`` you can use +``py_limited_api=not sysconfig.get_config_var("Py_GIL_DISABLED")`` to opt out +of the limited API when building with the free-threaded build. + +.. note:: + You will need to build separate wheels specifically for the free-threaded + build. If you currently use the stable ABI, you can continue to build a + single wheel for multiple non-free-threaded Python versions. + + +Windows +....... + +Due to a limitation of the official Windows installer, you will need to +manually define ``Py_GIL_DISABLED=1`` when building extensions from source. diff --git a/Doc/howto/functional.rst b/Doc/howto/functional.rst index b0f9d22d74f0e3..1f0608fb0fc53f 100644 --- a/Doc/howto/functional.rst +++ b/Doc/howto/functional.rst @@ -1,3 +1,5 @@ +.. _functional-howto: + ******************************** Functional Programming HOWTO ******************************** diff --git a/Doc/howto/index.rst b/Doc/howto/index.rst index 065071e39a06c5..a882f1747084fe 100644 --- a/Doc/howto/index.rst +++ b/Doc/howto/index.rst @@ -2,16 +2,14 @@ Python HOWTOs *************** -Python HOWTOs are documents that cover a single, specific topic, -and attempt to cover it fairly completely. Modelled on the Linux -Documentation Project's HOWTO collection, this collection is an +Python HOWTOs are documents that cover a specific topic in-depth. +Modeled on the Linux Documentation Project's HOWTO collection, this collection is an effort to foster documentation that's more detailed than the Python Library Reference. -Currently, the HOWTOs are: - .. toctree:: :maxdepth: 1 + :hidden: cporting.rst curses.rst @@ -34,4 +32,35 @@ Currently, the HOWTOs are: isolating-extensions.rst timerfd.rst mro.rst + free-threading-extensions.rst + +General: + +* :ref:`annotations-howto` +* :ref:`argparse-tutorial` +* :ref:`descriptorhowto` +* :ref:`enum-howto` +* :ref:`functional-howto` +* :ref:`ipaddress-howto` +* :ref:`logging-howto` +* :ref:`logging-cookbook` +* :ref:`regex-howto` +* :ref:`sortinghowto` +* :ref:`unicode-howto` +* :ref:`urllib-howto` + +Advanced development: + +* :ref:`curses-howto` +* :ref:`freethreading-extensions-howto` +* :ref:`isolating-extensions-howto` +* :ref:`python_2.3_mro` +* :ref:`socket-howto` +* :ref:`timerfd-howto` +* :ref:`cporting-howto` + +Debugging and profiling: +* :ref:`gdb` +* :ref:`instrumentation` +* :ref:`perf_profiling` diff --git a/Doc/howto/logging.rst b/Doc/howto/logging.rst index ab758a885b3556..cf5b693d8e3851 100644 --- a/Doc/howto/logging.rst +++ b/Doc/howto/logging.rst @@ -1,3 +1,5 @@ +.. _logging-howto: + ============= Logging HOWTO ============= diff --git a/Doc/library/ast.rst b/Doc/library/ast.rst index 9ee56b92431b57..f7e8afa7000392 100644 --- a/Doc/library/ast.rst +++ b/Doc/library/ast.rst @@ -891,9 +891,13 @@ Statements An assignment with a type annotation. ``target`` is a single node and can be a :class:`Name`, a :class:`Attribute` or a :class:`Subscript`. ``annotation`` is the annotation, such as a :class:`Constant` or :class:`Name` - node. ``value`` is a single optional node. ``simple`` is a boolean integer - set to True for a :class:`Name` node in ``target`` that do not appear in - between parenthesis and are hence pure names and not expressions. + node. ``value`` is a single optional node. + + ``simple`` is always either 0 (indicating a "complex" target) or 1 + (indicating a "simple" target). A "simple" target consists solely of a + :class:`Name` node that does not appear between parentheses; all other + targets are considered complex. Only simple targets appear in + the :attr:`__annotations__` dictionary of modules and classes. .. doctest:: diff --git a/Doc/library/asyncio-eventloop.rst b/Doc/library/asyncio-eventloop.rst index 374e789e91e790..1d79f78e8e1b67 100644 --- a/Doc/library/asyncio-eventloop.rst +++ b/Doc/library/asyncio-eventloop.rst @@ -1155,6 +1155,14 @@ DNS Asynchronous version of :meth:`socket.getnameinfo`. +.. note:: + Both *getaddrinfo* and *getnameinfo* internally utilize their synchronous + versions through the loop's default thread pool executor. + When this executor is saturated, these methods may experience delays, + which higher-level networking libraries may report as increased timeouts. + To mitigate this, consider using a custom executor for other user tasks, + or setting a default executor with a larger number of workers. + .. versionchanged:: 3.7 Both *getaddrinfo* and *getnameinfo* methods were always documented to return a coroutine, but prior to Python 3.7 they were, in fact, diff --git a/Doc/library/asyncio-platforms.rst b/Doc/library/asyncio-platforms.rst index 19ec726c1be060..a2a3114ad6e4c5 100644 --- a/Doc/library/asyncio-platforms.rst +++ b/Doc/library/asyncio-platforms.rst @@ -77,11 +77,6 @@ Subprocess Support on Windows On Windows, the default event loop :class:`ProactorEventLoop` supports subprocesses, whereas :class:`SelectorEventLoop` does not. -The :meth:`policy.set_child_watcher() -` function is also -not supported, as :class:`ProactorEventLoop` has a different mechanism -to watch child processes. - macOS ===== diff --git a/Doc/library/asyncio-policy.rst b/Doc/library/asyncio-policy.rst index 346b740a8f757a..837ccc6606786e 100644 --- a/Doc/library/asyncio-policy.rst +++ b/Doc/library/asyncio-policy.rst @@ -79,25 +79,6 @@ The abstract event loop policy base class is defined as follows: This method should never return ``None``. - .. method:: get_child_watcher() - - Get a child process watcher object. - - Return a watcher object implementing the - :class:`AbstractChildWatcher` interface. - - This function is Unix specific. - - .. deprecated:: 3.12 - - .. method:: set_child_watcher(watcher) - - Set the current child process watcher to *watcher*. - - This function is Unix specific. - - .. deprecated:: 3.12 - .. _asyncio-policy-builtin: @@ -139,172 +120,6 @@ asyncio ships with the following built-in policies: .. availability:: Windows. -.. _asyncio-watchers: - -Process Watchers -================ - -A process watcher allows customization of how an event loop monitors -child processes on Unix. Specifically, the event loop needs to know -when a child process has exited. - -In asyncio, child processes are created with -:func:`create_subprocess_exec` and :meth:`loop.subprocess_exec` -functions. - -asyncio defines the :class:`AbstractChildWatcher` abstract base class, which child -watchers should implement, and has four different implementations: -:class:`ThreadedChildWatcher` (configured to be used by default), -:class:`MultiLoopChildWatcher`, :class:`SafeChildWatcher`, and -:class:`FastChildWatcher`. - -See also the :ref:`Subprocess and Threads ` -section. - -The following two functions can be used to customize the child process watcher -implementation used by the asyncio event loop: - -.. function:: get_child_watcher() - - Return the current child watcher for the current policy. - - .. deprecated:: 3.12 - -.. function:: set_child_watcher(watcher) - - Set the current child watcher to *watcher* for the current - policy. *watcher* must implement methods defined in the - :class:`AbstractChildWatcher` base class. - - .. deprecated:: 3.12 - -.. note:: - Third-party event loops implementations might not support - custom child watchers. For such event loops, using - :func:`set_child_watcher` might be prohibited or have no effect. - -.. class:: AbstractChildWatcher - - .. method:: add_child_handler(pid, callback, *args) - - Register a new child handler. - - Arrange for ``callback(pid, returncode, *args)`` to be called - when a process with PID equal to *pid* terminates. Specifying - another callback for the same process replaces the previous - handler. - - The *callback* callable must be thread-safe. - - .. method:: remove_child_handler(pid) - - Removes the handler for process with PID equal to *pid*. - - The function returns ``True`` if the handler was successfully - removed, ``False`` if there was nothing to remove. - - .. method:: attach_loop(loop) - - Attach the watcher to an event loop. - - If the watcher was previously attached to an event loop, then - it is first detached before attaching to the new loop. - - Note: loop may be ``None``. - - .. method:: is_active() - - Return ``True`` if the watcher is ready to use. - - Spawning a subprocess with *inactive* current child watcher raises - :exc:`RuntimeError`. - - .. versionadded:: 3.8 - - .. method:: close() - - Close the watcher. - - This method has to be called to ensure that underlying - resources are cleaned-up. - - .. deprecated:: 3.12 - - -.. class:: ThreadedChildWatcher - - This implementation starts a new waiting thread for every subprocess spawn. - - It works reliably even when the asyncio event loop is run in a non-main OS thread. - - There is no noticeable overhead when handling a big number of children (*O*\ (1) each - time a child terminates), but starting a thread per process requires extra memory. - - This watcher is used by default. - - .. versionadded:: 3.8 - -.. class:: MultiLoopChildWatcher - - This implementation registers a :py:data:`SIGCHLD` signal handler on - instantiation. That can break third-party code that installs a custom handler for - :py:data:`SIGCHLD` signal. - - The watcher avoids disrupting other code spawning processes - by polling every process explicitly on a :py:data:`SIGCHLD` signal. - - There is no limitation for running subprocesses from different threads once the - watcher is installed. - - The solution is safe but it has a significant overhead when - handling a big number of processes (*O*\ (*n*) each time a - :py:data:`SIGCHLD` is received). - - .. versionadded:: 3.8 - - .. deprecated:: 3.12 - -.. class:: SafeChildWatcher - - This implementation uses active event loop from the main thread to handle - :py:data:`SIGCHLD` signal. If the main thread has no running event loop another - thread cannot spawn a subprocess (:exc:`RuntimeError` is raised). - - The watcher avoids disrupting other code spawning processes - by polling every process explicitly on a :py:data:`SIGCHLD` signal. - - This solution is as safe as :class:`MultiLoopChildWatcher` and has the same *O*\ (*n*) - complexity but requires a running event loop in the main thread to work. - - .. deprecated:: 3.12 - -.. class:: FastChildWatcher - - This implementation reaps every terminated processes by calling - ``os.waitpid(-1)`` directly, possibly breaking other code spawning - processes and waiting for their termination. - - There is no noticeable overhead when handling a big number of - children (*O*\ (1) each time a child terminates). - - This solution requires a running event loop in the main thread to work, as - :class:`SafeChildWatcher`. - - .. deprecated:: 3.12 - -.. class:: PidfdChildWatcher - - This implementation polls process file descriptors (pidfds) to await child - process termination. In some respects, :class:`PidfdChildWatcher` is a - "Goldilocks" child watcher implementation. It doesn't require signals or - threads, doesn't interfere with any processes launched outside the event - loop, and scales linearly with the number of subprocesses launched by the - event loop. The main disadvantage is that pidfds are specific to Linux, and - only work on recent (5.3+) kernels. - - .. versionadded:: 3.9 - - .. _asyncio-custom-policies: Custom Policies diff --git a/Doc/library/asyncio-subprocess.rst b/Doc/library/asyncio-subprocess.rst index 817a6ff3052f4a..b477a7fa2d37ef 100644 --- a/Doc/library/asyncio-subprocess.rst +++ b/Doc/library/asyncio-subprocess.rst @@ -316,18 +316,6 @@ default. On Windows subprocesses are provided by :class:`ProactorEventLoop` only (default), :class:`SelectorEventLoop` has no subprocess support. -On UNIX *child watchers* are used for subprocess finish waiting, see -:ref:`asyncio-watchers` for more info. - - -.. versionchanged:: 3.8 - - UNIX switched to use :class:`ThreadedChildWatcher` for spawning subprocesses from - different threads without any limitation. - - Spawning a subprocess with *inactive* current child watcher raises - :exc:`RuntimeError`. - Note that alternative event loop implementations might have own limitations; please refer to their documentation. diff --git a/Doc/library/collections.rst b/Doc/library/collections.rst index 2a269712f1814d..ce89101d6b667c 100644 --- a/Doc/library/collections.rst +++ b/Doc/library/collections.rst @@ -99,7 +99,7 @@ The class can be used to simulate nested scopes and is useful in templating. :func:`super` function. A reference to ``d.parents`` is equivalent to: ``ChainMap(*d.maps[1:])``. - Note, the iteration order of a :class:`ChainMap()` is determined by + Note, the iteration order of a :class:`ChainMap` is determined by scanning the mappings last to first:: >>> baseline = {'music': 'bach', 'art': 'rembrandt'} diff --git a/Doc/library/datetime.rst b/Doc/library/datetime.rst index 0723d0fe2fceb0..b6d8e6e6df07fa 100644 --- a/Doc/library/datetime.rst +++ b/Doc/library/datetime.rst @@ -2153,7 +2153,7 @@ There is one more :class:`tzinfo` method that a subclass may wish to override: .. method:: tzinfo.fromutc(dt) - This is called from the default :class:`datetime.astimezone()` + This is called from the default :meth:`datetime.astimezone` implementation. When called from that, ``dt.tzinfo`` is *self*, and *dt*'s date and time data are to be viewed as expressing a UTC time. The purpose of :meth:`fromutc` is to adjust the date and time data, returning an diff --git a/Doc/library/decimal.rst b/Doc/library/decimal.rst index 3e33581f96f16a..db323802a6f68c 100644 --- a/Doc/library/decimal.rst +++ b/Doc/library/decimal.rst @@ -897,6 +897,48 @@ Decimal objects :const:`Rounded`. If given, applies *rounding*; otherwise, uses the rounding method in either the supplied *context* or the current context. + Decimal numbers can be rounded using the :func:`.round` function: + + .. describe:: round(number) + .. describe:: round(number, ndigits) + + If *ndigits* is not given or ``None``, + returns the nearest :class:`int` to *number*, + rounding ties to even, and ignoring the rounding mode of the + :class:`Decimal` context. Raises :exc:`OverflowError` if *number* is an + infinity or :exc:`ValueError` if it is a (quiet or signaling) NaN. + + If *ndigits* is an :class:`int`, the context's rounding mode is respected + and a :class:`Decimal` representing *number* rounded to the nearest + multiple of ``Decimal('1E-ndigits')`` is returned; in this case, + ``round(number, ndigits)`` is equivalent to + ``self.quantize(Decimal('1E-ndigits'))``. Returns ``Decimal('NaN')`` if + *number* is a quiet NaN. Raises :class:`InvalidOperation` if *number* + is an infinity, a signaling NaN, or if the length of the coefficient after + the quantize operation would be greater than the current context's + precision. In other words, for the non-corner cases: + + * if *ndigits* is positive, return *number* rounded to *ndigits* decimal + places; + * if *ndigits* is zero, return *number* rounded to the nearest integer; + * if *ndigits* is negative, return *number* rounded to the nearest + multiple of ``10**abs(ndigits)``. + + For example:: + + >>> from decimal import Decimal, getcontext, ROUND_DOWN + >>> getcontext().rounding = ROUND_DOWN + >>> round(Decimal('3.75')) # context rounding ignored + 4 + >>> round(Decimal('3.5')) # round-ties-to-even + 4 + >>> round(Decimal('3.75'), 0) # uses the context rounding + Decimal('3') + >>> round(Decimal('3.75'), 1) + Decimal('3.7') + >>> round(Decimal('3.75'), -1) + Decimal('0E+1') + .. _logical_operands_label: diff --git a/Doc/library/dis.rst b/Doc/library/dis.rst index ab46d4554d8773..e932b865a825a0 100644 --- a/Doc/library/dis.rst +++ b/Doc/library/dis.rst @@ -780,16 +780,6 @@ not have to be) the original ``STACK[-2]``. .. versionadded:: 3.12 -.. opcode:: BEFORE_ASYNC_WITH - - Resolves ``__aenter__`` and ``__aexit__`` from ``STACK[-1]``. - Pushes ``__aexit__`` and result of ``__aenter__()`` to the stack:: - - STACK.extend((__aexit__, __aenter__()) - - .. versionadded:: 3.5 - - **Miscellaneous opcodes** @@ -944,18 +934,6 @@ iterations of the loop. Pushes :func:`!builtins.__build_class__` onto the stack. It is later called to construct a class. - -.. opcode:: BEFORE_WITH - - This opcode performs several operations before a with block starts. First, - it loads :meth:`~object.__exit__` from the context manager and pushes it onto - the stack for later use by :opcode:`WITH_EXCEPT_START`. Then, - :meth:`~object.__enter__` is called. Finally, the result of calling the - ``__enter__()`` method is pushed onto the stack. - - .. versionadded:: 3.11 - - .. opcode:: GET_LEN Perform ``STACK.append(len(STACK[-1]))``. @@ -1812,6 +1790,17 @@ iterations of the loop. .. versionadded:: 3.12 +.. opcode:: LOAD_SPECIAL + + Performs special method lookup on ``STACK[-1]``. + If ``type(STACK[-1]).__xxx__`` is a method, leave + ``type(STACK[-1]).__xxx__; STACK[-1]`` on the stack. + If ``type(STACK[-1]).__xxx__`` is not a method, leave + ``STACK[-1].__xxx__; NULL`` on the stack. + + .. versionadded:: 3.14 + + **Pseudo-instructions** These opcodes do not appear in Python bytecode. They are used by the compiler diff --git a/Doc/library/enum.rst b/Doc/library/enum.rst index 8c604c2347a547..8b3f397ea862f4 100644 --- a/Doc/library/enum.rst +++ b/Doc/library/enum.rst @@ -527,7 +527,7 @@ Data Types ``Flag`` is the same as :class:`Enum`, but its members support the bitwise operators ``&`` (*AND*), ``|`` (*OR*), ``^`` (*XOR*), and ``~`` (*INVERT*); - the results of those operators are members of the enumeration. + the results of those operations are (aliases of) members of the enumeration. .. method:: __contains__(self, value) @@ -629,7 +629,7 @@ Data Types of two, starting with ``1``. .. versionchanged:: 3.11 The *repr()* of zero-valued flags has changed. It - is now:: + is now: >>> Color(0) # doctest: +SKIP diff --git a/Doc/library/fileinput.rst b/Doc/library/fileinput.rst index 94a4139f64c2e4..8f32b11e565365 100644 --- a/Doc/library/fileinput.rst +++ b/Doc/library/fileinput.rst @@ -47,7 +47,7 @@ Lines are returned with any newlines intact, which means that the last line in a file may not have one. You can control how files are opened by providing an opening hook via the -*openhook* parameter to :func:`fileinput.input` or :class:`FileInput()`. The +*openhook* parameter to :func:`fileinput.input` or :func:`FileInput`. The hook must be a function that takes two arguments, *filename* and *mode*, and returns an accordingly opened file-like object. If *encoding* and/or *errors* are specified, they will be passed to the hook as additional keyword arguments. diff --git a/Doc/library/gzip.rst b/Doc/library/gzip.rst index 965da5981f6dbc..6b6e158f6eba2c 100644 --- a/Doc/library/gzip.rst +++ b/Doc/library/gzip.rst @@ -188,9 +188,7 @@ The module defines the following items: Compress the *data*, returning a :class:`bytes` object containing the compressed data. *compresslevel* and *mtime* have the same meaning as in - the :class:`GzipFile` constructor above. When *mtime* is set to ``0``, this - function is equivalent to :func:`zlib.compress` with *wbits* set to ``31``. - The zlib function is faster. + the :class:`GzipFile` constructor above. .. versionadded:: 3.2 .. versionchanged:: 3.8 @@ -198,7 +196,13 @@ The module defines the following items: .. versionchanged:: 3.11 Speed is improved by compressing all data at once instead of in a streamed fashion. Calls with *mtime* set to ``0`` are delegated to - :func:`zlib.compress` for better speed. + :func:`zlib.compress` for better speed. In this situation the + output may contain a gzip header "OS" byte value other than 255 + "unknown" as supplied by the underlying zlib implementation. + + .. versionchanged:: 3.13 + The gzip header OS byte is guaranteed to be set to 255 when this function + is used as was the case in 3.10 and earlier. .. function:: decompress(data) diff --git a/Doc/library/inspect.rst b/Doc/library/inspect.rst index 7130faa4b5b696..7838eeed2843c4 100644 --- a/Doc/library/inspect.rst +++ b/Doc/library/inspect.rst @@ -42,220 +42,233 @@ attributes (see :ref:`import-mod-attrs` for module attributes): .. this function name is too big to fit in the ascii-art table below .. |coroutine-origin-link| replace:: :func:`sys.set_coroutine_origin_tracking_depth` -+-----------+-------------------+---------------------------+ -| Type | Attribute | Description | -+===========+===================+===========================+ -| class | __doc__ | documentation string | -+-----------+-------------------+---------------------------+ -| | __name__ | name with which this | -| | | class was defined | -+-----------+-------------------+---------------------------+ -| | __qualname__ | qualified name | -+-----------+-------------------+---------------------------+ -| | __module__ | name of module in which | -| | | this class was defined | -+-----------+-------------------+---------------------------+ -| | __type_params__ | A tuple containing the | -| | | :ref:`type parameters | -| | | ` of | -| | | a generic class | -+-----------+-------------------+---------------------------+ -| method | __doc__ | documentation string | -+-----------+-------------------+---------------------------+ -| | __name__ | name with which this | -| | | method was defined | -+-----------+-------------------+---------------------------+ -| | __qualname__ | qualified name | -+-----------+-------------------+---------------------------+ -| | __func__ | function object | -| | | containing implementation | -| | | of method | -+-----------+-------------------+---------------------------+ -| | __self__ | instance to which this | -| | | method is bound, or | -| | | ``None`` | -+-----------+-------------------+---------------------------+ -| | __module__ | name of module in which | -| | | this method was defined | -+-----------+-------------------+---------------------------+ -| function | __doc__ | documentation string | -+-----------+-------------------+---------------------------+ -| | __name__ | name with which this | -| | | function was defined | -+-----------+-------------------+---------------------------+ -| | __qualname__ | qualified name | -+-----------+-------------------+---------------------------+ -| | __code__ | code object containing | -| | | compiled function | -| | | :term:`bytecode` | -+-----------+-------------------+---------------------------+ -| | __defaults__ | tuple of any default | -| | | values for positional or | -| | | keyword parameters | -+-----------+-------------------+---------------------------+ -| | __kwdefaults__ | mapping of any default | -| | | values for keyword-only | -| | | parameters | -+-----------+-------------------+---------------------------+ -| | __globals__ | global namespace in which | -| | | this function was defined | -+-----------+-------------------+---------------------------+ -| | __builtins__ | builtins namespace | -+-----------+-------------------+---------------------------+ -| | __annotations__ | mapping of parameters | -| | | names to annotations; | -| | | ``"return"`` key is | -| | | reserved for return | -| | | annotations. | -+-----------+-------------------+---------------------------+ -| | __type_params__ | A tuple containing the | -| | | :ref:`type parameters | -| | | ` of | -| | | a generic function | -+-----------+-------------------+---------------------------+ -| | __module__ | name of module in which | -| | | this function was defined | -+-----------+-------------------+---------------------------+ -| traceback | tb_frame | frame object at this | -| | | level | -+-----------+-------------------+---------------------------+ -| | tb_lasti | index of last attempted | -| | | instruction in bytecode | -+-----------+-------------------+---------------------------+ -| | tb_lineno | current line number in | -| | | Python source code | -+-----------+-------------------+---------------------------+ -| | tb_next | next inner traceback | -| | | object (called by this | -| | | level) | -+-----------+-------------------+---------------------------+ -| frame | f_back | next outer frame object | -| | | (this frame's caller) | -+-----------+-------------------+---------------------------+ -| | f_builtins | builtins namespace seen | -| | | by this frame | -+-----------+-------------------+---------------------------+ -| | f_code | code object being | -| | | executed in this frame | -+-----------+-------------------+---------------------------+ -| | f_globals | global namespace seen by | -| | | this frame | -+-----------+-------------------+---------------------------+ -| | f_lasti | index of last attempted | -| | | instruction in bytecode | -+-----------+-------------------+---------------------------+ -| | f_lineno | current line number in | -| | | Python source code | -+-----------+-------------------+---------------------------+ -| | f_locals | local namespace seen by | -| | | this frame | -+-----------+-------------------+---------------------------+ -| | f_trace | tracing function for this | -| | | frame, or ``None`` | -+-----------+-------------------+---------------------------+ -| code | co_argcount | number of arguments (not | -| | | including keyword only | -| | | arguments, \* or \*\* | -| | | args) | -+-----------+-------------------+---------------------------+ -| | co_code | string of raw compiled | -| | | bytecode | -+-----------+-------------------+---------------------------+ -| | co_cellvars | tuple of names of cell | -| | | variables (referenced by | -| | | containing scopes) | -+-----------+-------------------+---------------------------+ -| | co_consts | tuple of constants used | -| | | in the bytecode | -+-----------+-------------------+---------------------------+ -| | co_filename | name of file in which | -| | | this code object was | -| | | created | -+-----------+-------------------+---------------------------+ -| | co_firstlineno | number of first line in | -| | | Python source code | -+-----------+-------------------+---------------------------+ -| | co_flags | bitmap of ``CO_*`` flags, | -| | | read more :ref:`here | -| | | `| -+-----------+-------------------+---------------------------+ -| | co_lnotab | encoded mapping of line | -| | | numbers to bytecode | -| | | indices | -+-----------+-------------------+---------------------------+ -| | co_freevars | tuple of names of free | -| | | variables (referenced via | -| | | a function's closure) | -+-----------+-------------------+---------------------------+ -| | co_posonlyargcount| number of positional only | -| | | arguments | -+-----------+-------------------+---------------------------+ -| | co_kwonlyargcount | number of keyword only | -| | | arguments (not including | -| | | \*\* arg) | -+-----------+-------------------+---------------------------+ -| | co_name | name with which this code | -| | | object was defined | -+-----------+-------------------+---------------------------+ -| | co_qualname | fully qualified name with | -| | | which this code object | -| | | was defined | -+-----------+-------------------+---------------------------+ -| | co_names | tuple of names other | -| | | than arguments and | -| | | function locals | -+-----------+-------------------+---------------------------+ -| | co_nlocals | number of local variables | -+-----------+-------------------+---------------------------+ -| | co_stacksize | virtual machine stack | -| | | space required | -+-----------+-------------------+---------------------------+ -| | co_varnames | tuple of names of | -| | | arguments and local | -| | | variables | -+-----------+-------------------+---------------------------+ -| generator | __name__ | name | -+-----------+-------------------+---------------------------+ -| | __qualname__ | qualified name | -+-----------+-------------------+---------------------------+ -| | gi_frame | frame | -+-----------+-------------------+---------------------------+ -| | gi_running | is the generator running? | -+-----------+-------------------+---------------------------+ -| | gi_code | code | -+-----------+-------------------+---------------------------+ -| | gi_yieldfrom | object being iterated by | -| | | ``yield from``, or | -| | | ``None`` | -+-----------+-------------------+---------------------------+ -| coroutine | __name__ | name | -+-----------+-------------------+---------------------------+ -| | __qualname__ | qualified name | -+-----------+-------------------+---------------------------+ -| | cr_await | object being awaited on, | -| | | or ``None`` | -+-----------+-------------------+---------------------------+ -| | cr_frame | frame | -+-----------+-------------------+---------------------------+ -| | cr_running | is the coroutine running? | -+-----------+-------------------+---------------------------+ -| | cr_code | code | -+-----------+-------------------+---------------------------+ -| | cr_origin | where coroutine was | -| | | created, or ``None``. See | -| | | |coroutine-origin-link| | -+-----------+-------------------+---------------------------+ -| builtin | __doc__ | documentation string | -+-----------+-------------------+---------------------------+ -| | __name__ | original name of this | -| | | function or method | -+-----------+-------------------+---------------------------+ -| | __qualname__ | qualified name | -+-----------+-------------------+---------------------------+ -| | __self__ | instance to which a | -| | | method is bound, or | -| | | ``None`` | -+-----------+-------------------+---------------------------+ ++-----------------+-------------------+---------------------------+ +| Type | Attribute | Description | ++=================+===================+===========================+ +| class | __doc__ | documentation string | ++-----------------+-------------------+---------------------------+ +| | __name__ | name with which this | +| | | class was defined | ++-----------------+-------------------+---------------------------+ +| | __qualname__ | qualified name | ++-----------------+-------------------+---------------------------+ +| | __module__ | name of module in which | +| | | this class was defined | ++-----------------+-------------------+---------------------------+ +| | __type_params__ | A tuple containing the | +| | | :ref:`type parameters | +| | | ` of | +| | | a generic class | ++-----------------+-------------------+---------------------------+ +| method | __doc__ | documentation string | ++-----------------+-------------------+---------------------------+ +| | __name__ | name with which this | +| | | method was defined | ++-----------------+-------------------+---------------------------+ +| | __qualname__ | qualified name | ++-----------------+-------------------+---------------------------+ +| | __func__ | function object | +| | | containing implementation | +| | | of method | ++-----------------+-------------------+---------------------------+ +| | __self__ | instance to which this | +| | | method is bound, or | +| | | ``None`` | ++-----------------+-------------------+---------------------------+ +| | __module__ | name of module in which | +| | | this method was defined | ++-----------------+-------------------+---------------------------+ +| function | __doc__ | documentation string | ++-----------------+-------------------+---------------------------+ +| | __name__ | name with which this | +| | | function was defined | ++-----------------+-------------------+---------------------------+ +| | __qualname__ | qualified name | ++-----------------+-------------------+---------------------------+ +| | __code__ | code object containing | +| | | compiled function | +| | | :term:`bytecode` | ++-----------------+-------------------+---------------------------+ +| | __defaults__ | tuple of any default | +| | | values for positional or | +| | | keyword parameters | ++-----------------+-------------------+---------------------------+ +| | __kwdefaults__ | mapping of any default | +| | | values for keyword-only | +| | | parameters | ++-----------------+-------------------+---------------------------+ +| | __globals__ | global namespace in which | +| | | this function was defined | ++-----------------+-------------------+---------------------------+ +| | __builtins__ | builtins namespace | ++-----------------+-------------------+---------------------------+ +| | __annotations__ | mapping of parameters | +| | | names to annotations; | +| | | ``"return"`` key is | +| | | reserved for return | +| | | annotations. | ++-----------------+-------------------+---------------------------+ +| | __type_params__ | A tuple containing the | +| | | :ref:`type parameters | +| | | ` of | +| | | a generic function | ++-----------------+-------------------+---------------------------+ +| | __module__ | name of module in which | +| | | this function was defined | ++-----------------+-------------------+---------------------------+ +| traceback | tb_frame | frame object at this | +| | | level | ++-----------------+-------------------+---------------------------+ +| | tb_lasti | index of last attempted | +| | | instruction in bytecode | ++-----------------+-------------------+---------------------------+ +| | tb_lineno | current line number in | +| | | Python source code | ++-----------------+-------------------+---------------------------+ +| | tb_next | next inner traceback | +| | | object (called by this | +| | | level) | ++-----------------+-------------------+---------------------------+ +| frame | f_back | next outer frame object | +| | | (this frame's caller) | ++-----------------+-------------------+---------------------------+ +| | f_builtins | builtins namespace seen | +| | | by this frame | ++-----------------+-------------------+---------------------------+ +| | f_code | code object being | +| | | executed in this frame | ++-----------------+-------------------+---------------------------+ +| | f_globals | global namespace seen by | +| | | this frame | ++-----------------+-------------------+---------------------------+ +| | f_lasti | index of last attempted | +| | | instruction in bytecode | ++-----------------+-------------------+---------------------------+ +| | f_lineno | current line number in | +| | | Python source code | ++-----------------+-------------------+---------------------------+ +| | f_locals | local namespace seen by | +| | | this frame | ++-----------------+-------------------+---------------------------+ +| | f_trace | tracing function for this | +| | | frame, or ``None`` | ++-----------------+-------------------+---------------------------+ +| code | co_argcount | number of arguments (not | +| | | including keyword only | +| | | arguments, \* or \*\* | +| | | args) | ++-----------------+-------------------+---------------------------+ +| | co_code | string of raw compiled | +| | | bytecode | ++-----------------+-------------------+---------------------------+ +| | co_cellvars | tuple of names of cell | +| | | variables (referenced by | +| | | containing scopes) | ++-----------------+-------------------+---------------------------+ +| | co_consts | tuple of constants used | +| | | in the bytecode | ++-----------------+-------------------+---------------------------+ +| | co_filename | name of file in which | +| | | this code object was | +| | | created | ++-----------------+-------------------+---------------------------+ +| | co_firstlineno | number of first line in | +| | | Python source code | ++-----------------+-------------------+---------------------------+ +| | co_flags | bitmap of ``CO_*`` flags, | +| | | read more :ref:`here | +| | | `| ++-----------------+-------------------+---------------------------+ +| | co_lnotab | encoded mapping of line | +| | | numbers to bytecode | +| | | indices | ++-----------------+-------------------+---------------------------+ +| | co_freevars | tuple of names of free | +| | | variables (referenced via | +| | | a function's closure) | ++-----------------+-------------------+---------------------------+ +| | co_posonlyargcount| number of positional only | +| | | arguments | ++-----------------+-------------------+---------------------------+ +| | co_kwonlyargcount | number of keyword only | +| | | arguments (not including | +| | | \*\* arg) | ++-----------------+-------------------+---------------------------+ +| | co_name | name with which this code | +| | | object was defined | ++-----------------+-------------------+---------------------------+ +| | co_qualname | fully qualified name with | +| | | which this code object | +| | | was defined | ++-----------------+-------------------+---------------------------+ +| | co_names | tuple of names other | +| | | than arguments and | +| | | function locals | ++-----------------+-------------------+---------------------------+ +| | co_nlocals | number of local variables | ++-----------------+-------------------+---------------------------+ +| | co_stacksize | virtual machine stack | +| | | space required | ++-----------------+-------------------+---------------------------+ +| | co_varnames | tuple of names of | +| | | arguments and local | +| | | variables | ++-----------------+-------------------+---------------------------+ +| generator | __name__ | name | ++-----------------+-------------------+---------------------------+ +| | __qualname__ | qualified name | ++-----------------+-------------------+---------------------------+ +| | gi_frame | frame | ++-----------------+-------------------+---------------------------+ +| | gi_running | is the generator running? | ++-----------------+-------------------+---------------------------+ +| | gi_code | code | ++-----------------+-------------------+---------------------------+ +| | gi_yieldfrom | object being iterated by | +| | | ``yield from``, or | +| | | ``None`` | ++-----------------+-------------------+---------------------------+ +| async generator | __name__ | name | ++-----------------+-------------------+---------------------------+ +| | __qualname__ | qualified name | ++-----------------+-------------------+---------------------------+ +| | ag_await | object being awaited on, | +| | | or ``None`` | ++-----------------+-------------------+---------------------------+ +| | ag_frame | frame | ++-----------------+-------------------+---------------------------+ +| | ag_running | is the generator running? | ++-----------------+-------------------+---------------------------+ +| | ag_code | code | ++-----------------+-------------------+---------------------------+ +| coroutine | __name__ | name | ++-----------------+-------------------+---------------------------+ +| | __qualname__ | qualified name | ++-----------------+-------------------+---------------------------+ +| | cr_await | object being awaited on, | +| | | or ``None`` | ++-----------------+-------------------+---------------------------+ +| | cr_frame | frame | ++-----------------+-------------------+---------------------------+ +| | cr_running | is the coroutine running? | ++-----------------+-------------------+---------------------------+ +| | cr_code | code | ++-----------------+-------------------+---------------------------+ +| | cr_origin | where coroutine was | +| | | created, or ``None``. See | +| | | |coroutine-origin-link| | ++-----------------+-------------------+---------------------------+ +| builtin | __doc__ | documentation string | ++-----------------+-------------------+---------------------------+ +| | __name__ | original name of this | +| | | function or method | ++-----------------+-------------------+---------------------------+ +| | __qualname__ | qualified name | ++-----------------+-------------------+---------------------------+ +| | __self__ | instance to which a | +| | | method is bound, or | +| | | ``None`` | ++-----------------+-------------------+---------------------------+ .. versionchanged:: 3.5 @@ -504,9 +517,9 @@ attributes (see :ref:`import-mod-attrs` for module attributes): are true. This, for example, is true of ``int.__add__``. An object passing this test - has a :meth:`~object.__get__` method but not a :meth:`~object.__set__` - method, but beyond that the set of attributes varies. A - :attr:`~definition.__name__` attribute is usually + has a :meth:`~object.__get__` method, but not a :meth:`~object.__set__` + method or a :meth:`~object.__delete__` method. Beyond that, the set of + attributes varies. A :attr:`~definition.__name__` attribute is usually sensible, and :attr:`!__doc__` often is. Methods implemented via descriptors that also pass one of the other tests @@ -515,6 +528,11 @@ attributes (see :ref:`import-mod-attrs` for module attributes): :attr:`~method.__func__` attribute (etc) when an object passes :func:`ismethod`. + .. versionchanged:: 3.13 + This function no longer incorrectly reports objects with :meth:`~object.__get__` + and :meth:`~object.__delete__`, but not :meth:`~object.__set__`, as being method + descriptors (such objects are data descriptors, not method descriptors). + .. function:: isdatadescriptor(object) diff --git a/Doc/library/itertools.rst b/Doc/library/itertools.rst index 3dc3f60923a0ba..1fdd00a69da1f3 100644 --- a/Doc/library/itertools.rst +++ b/Doc/library/itertools.rst @@ -58,12 +58,12 @@ Iterator Arguments Results :func:`compress` data, selectors (d[0] if s[0]), (d[1] if s[1]), ... ``compress('ABCDEF', [1,0,1,0,1,1]) → A C E F`` :func:`dropwhile` predicate, seq seq[n], seq[n+1], starting when predicate fails ``dropwhile(lambda x: x<5, [1,4,6,3,8]) → 6 3 8`` :func:`filterfalse` predicate, seq elements of seq where predicate(elem) fails ``filterfalse(lambda x: x<5, [1,4,6,3,8]) → 6 8`` -:func:`groupby` iterable[, key] sub-iterators grouped by value of key(v) +:func:`groupby` iterable[, key] sub-iterators grouped by value of key(v) ``groupby(['A','B','ABC'], len) → (1, A B) (3, ABC)`` :func:`islice` seq, [start,] stop [, step] elements from seq[start:stop:step] ``islice('ABCDEFG', 2, None) → C D E F G`` :func:`pairwise` iterable (p[0], p[1]), (p[1], p[2]) ``pairwise('ABCDEFG') → AB BC CD DE EF FG`` :func:`starmap` func, seq func(\*seq[0]), func(\*seq[1]), ... ``starmap(pow, [(2,5), (3,2), (10,3)]) → 32 9 1000`` :func:`takewhile` predicate, seq seq[0], seq[1], until predicate fails ``takewhile(lambda x: x<5, [1,4,6,3,8]) → 1 4`` -:func:`tee` it, n it1, it2, ... itn splits one iterator into n +:func:`tee` it, n it1, it2, ... itn splits one iterator into n ``tee('ABC', 2) → A B C, A B C`` :func:`zip_longest` p, q, ... (p[0], q[0]), (p[1], q[1]), ... ``zip_longest('ABCD', 'xy', fillvalue='-') → Ax By C- D-`` ============================ ============================ ================================================= ============================================================= diff --git a/Doc/library/multiprocessing.rst b/Doc/library/multiprocessing.rst index 49762491bae5f4..426291c5f0743d 100644 --- a/Doc/library/multiprocessing.rst +++ b/Doc/library/multiprocessing.rst @@ -837,6 +837,8 @@ For an example of the usage of queues for interprocess communication see Return ``True`` if the queue is empty, ``False`` otherwise. Because of multithreading/multiprocessing semantics, this is not reliable. + May raise an :exc:`OSError` on closed queues. (not guaranteed) + .. method:: full() Return ``True`` if the queue is full, ``False`` otherwise. Because of @@ -940,6 +942,8 @@ For an example of the usage of queues for interprocess communication see Return ``True`` if the queue is empty, ``False`` otherwise. + Always raises an :exc:`OSError` if the SimpleQueue is closed. + .. method:: get() Remove and return an item from the queue. diff --git a/Doc/library/pathlib.rst b/Doc/library/pathlib.rst index b7ab44706a0160..28a006d9619bbc 100644 --- a/Doc/library/pathlib.rst +++ b/Doc/library/pathlib.rst @@ -1343,152 +1343,150 @@ Reading directories .. versionadded:: 3.12 -Other methods -^^^^^^^^^^^^^ - -.. classmethod:: Path.cwd() - - Return a new path object representing the current directory (as returned - by :func:`os.getcwd`):: - - >>> Path.cwd() - PosixPath('/home/antoine/pathlib') +Creating files and directories +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +.. method:: Path.touch(mode=0o666, exist_ok=True) -.. classmethod:: Path.home() + Create a file at this given path. If *mode* is given, it is combined + with the process's ``umask`` value to determine the file mode and access + flags. If the file already exists, the function succeeds when *exist_ok* + is true (and its modification time is updated to the current time), + otherwise :exc:`FileExistsError` is raised. - Return a new path object representing the user's home directory (as - returned by :func:`os.path.expanduser` with ``~`` construct). If the home - directory can't be resolved, :exc:`RuntimeError` is raised. + .. seealso:: + The :meth:`~Path.open`, :meth:`~Path.write_text` and + :meth:`~Path.write_bytes` methods are often used to create files. - :: - >>> Path.home() - PosixPath('/home/antoine') +.. method:: Path.mkdir(mode=0o777, parents=False, exist_ok=False) - .. versionadded:: 3.5 + Create a new directory at this given path. If *mode* is given, it is + combined with the process's ``umask`` value to determine the file mode + and access flags. If the path already exists, :exc:`FileExistsError` + is raised. + If *parents* is true, any missing parents of this path are created + as needed; they are created with the default permissions without taking + *mode* into account (mimicking the POSIX ``mkdir -p`` command). -.. method:: Path.chmod(mode, *, follow_symlinks=True) + If *parents* is false (the default), a missing parent raises + :exc:`FileNotFoundError`. - Change the file mode and permissions, like :func:`os.chmod`. + If *exist_ok* is false (the default), :exc:`FileExistsError` is + raised if the target directory already exists. - This method normally follows symlinks. Some Unix flavours support changing - permissions on the symlink itself; on these platforms you may add the - argument ``follow_symlinks=False``, or use :meth:`~Path.lchmod`. + If *exist_ok* is true, :exc:`FileExistsError` will not be raised unless the given + path already exists in the file system and is not a directory (same + behavior as the POSIX ``mkdir -p`` command). - :: + .. versionchanged:: 3.5 + The *exist_ok* parameter was added. - >>> p = Path('setup.py') - >>> p.stat().st_mode - 33277 - >>> p.chmod(0o444) - >>> p.stat().st_mode - 33060 - .. versionchanged:: 3.10 - The *follow_symlinks* parameter was added. +.. method:: Path.symlink_to(target, target_is_directory=False) -.. method:: Path.expanduser() + Make this path a symbolic link pointing to *target*. - Return a new path with expanded ``~`` and ``~user`` constructs, - as returned by :meth:`os.path.expanduser`. If a home directory can't be - resolved, :exc:`RuntimeError` is raised. + On Windows, a symlink represents either a file or a directory, and does not + morph to the target dynamically. If the target is present, the type of the + symlink will be created to match. Otherwise, the symlink will be created + as a directory if *target_is_directory* is true or a file symlink (the + default) otherwise. On non-Windows platforms, *target_is_directory* is ignored. :: - >>> p = PosixPath('~/films/Monty Python') - >>> p.expanduser() - PosixPath('/home/eric/films/Monty Python') - - .. versionadded:: 3.5 - - -.. method:: Path.group(*, follow_symlinks=True) - - Return the name of the group owning the file. :exc:`KeyError` is raised - if the file's gid isn't found in the system database. + >>> p = Path('mylink') + >>> p.symlink_to('setup.py') + >>> p.resolve() + PosixPath('/home/antoine/pathlib/setup.py') + >>> p.stat().st_size + 956 + >>> p.lstat().st_size + 8 - This method normally follows symlinks; to get the group of the symlink, add - the argument ``follow_symlinks=False``. + .. note:: + The order of arguments (link, target) is the reverse + of :func:`os.symlink`'s. .. versionchanged:: 3.13 - Raises :exc:`UnsupportedOperation` if the :mod:`grp` module is not + Raises :exc:`UnsupportedOperation` if :func:`os.symlink` is not available. In previous versions, :exc:`NotImplementedError` was raised. - .. versionchanged:: 3.13 - The *follow_symlinks* parameter was added. +.. method:: Path.hardlink_to(target) -.. method:: Path.lchmod(mode) + Make this path a hard link to the same file as *target*. - Like :meth:`Path.chmod` but, if the path points to a symbolic link, the - symbolic link's mode is changed rather than its target's. + .. note:: + The order of arguments (link, target) is the reverse + of :func:`os.link`'s. + .. versionadded:: 3.10 -.. method:: Path.mkdir(mode=0o777, parents=False, exist_ok=False) + .. versionchanged:: 3.13 + Raises :exc:`UnsupportedOperation` if :func:`os.link` is not + available. In previous versions, :exc:`NotImplementedError` was raised. - Create a new directory at this given path. If *mode* is given, it is - combined with the process' ``umask`` value to determine the file mode - and access flags. If the path already exists, :exc:`FileExistsError` - is raised. - If *parents* is true, any missing parents of this path are created - as needed; they are created with the default permissions without taking - *mode* into account (mimicking the POSIX ``mkdir -p`` command). +Copying, renaming and deleting +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - If *parents* is false (the default), a missing parent raises - :exc:`FileNotFoundError`. +.. method:: Path.copy(target, *, follow_symlinks=True) - If *exist_ok* is false (the default), :exc:`FileExistsError` is - raised if the target directory already exists. + Copy the contents of this file to the *target* file. If *target* specifies + a file that already exists, it will be replaced. - If *exist_ok* is true, :exc:`FileExistsError` will not be raised unless the given - path already exists in the file system and is not a directory (same - behavior as the POSIX ``mkdir -p`` command). + If *follow_symlinks* is false, and this file is a symbolic link, *target* + will be created as a symbolic link. If *follow_symlinks* is true and this + file is a symbolic link, *target* will be a copy of the symlink target. - .. versionchanged:: 3.5 - The *exist_ok* parameter was added. + .. note:: + This method uses operating system functionality to copy file content + efficiently. The OS might also copy some metadata, such as file + permissions. After the copy is complete, users may wish to call + :meth:`Path.chmod` to set the permissions of the target file. + .. warning:: + On old builds of Windows (before Windows 10 build 19041), this method + raises :exc:`OSError` when a symlink to a directory is encountered and + *follow_symlinks* is false. -.. method:: Path.owner(*, follow_symlinks=True) + .. versionadded:: 3.14 - Return the name of the user owning the file. :exc:`KeyError` is raised - if the file's uid isn't found in the system database. - This method normally follows symlinks; to get the owner of the symlink, add - the argument ``follow_symlinks=False``. +.. method:: Path.copytree(target, *, follow_symlinks=True, dirs_exist_ok=False, \ + ignore=None, on_error=None) - .. versionchanged:: 3.13 - Raises :exc:`UnsupportedOperation` if the :mod:`pwd` module is not - available. In previous versions, :exc:`NotImplementedError` was raised. + Recursively copy this directory tree to the given destination. - .. versionchanged:: 3.13 - The *follow_symlinks* parameter was added. + If a symlink is encountered in the source tree, and *follow_symlinks* is + true (the default), the symlink's target is copied. Otherwise, the symlink + is recreated in the destination tree. + If the destination is an existing directory and *dirs_exist_ok* is false + (the default), a :exc:`FileExistsError` is raised. Otherwise, the copying + operation will continue if it encounters existing directories, and files + within the destination tree will be overwritten by corresponding files from + the source tree. -.. method:: Path.readlink() + If *ignore* is given, it should be a callable accepting one argument: a + file or directory path within the source tree. The callable may return true + to suppress copying of the path. - Return the path to which the symbolic link points (as returned by - :func:`os.readlink`):: - - >>> p = Path('mylink') - >>> p.symlink_to('setup.py') - >>> p.readlink() - PosixPath('setup.py') + If *on_error* is given, it should be a callable accepting one argument: an + instance of :exc:`OSError`. The callable may re-raise the exception or do + nothing, in which case the copying operation continues. If *on_error* isn't + given, exceptions are propagated to the caller. - .. versionadded:: 3.9 - - .. versionchanged:: 3.13 - Raises :exc:`UnsupportedOperation` if :func:`os.readlink` is not - available. In previous versions, :exc:`NotImplementedError` was raised. + .. versionadded:: 3.14 .. method:: Path.rename(target) - Rename this file or directory to the given *target*, and return a new Path - instance pointing to *target*. On Unix, if *target* exists and is a file, - it will be replaced silently if the user has permission. + Rename this file or directory to the given *target*, and return a new + :class:`!Path` instance pointing to *target*. On Unix, if *target* exists + and is a file, it will be replaced silently if the user has permission. On Windows, if *target* exists, :exc:`FileExistsError` will be raised. *target* can be either a string or another path object:: @@ -1502,27 +1500,167 @@ Other methods 'some text' The target path may be absolute or relative. Relative paths are interpreted - relative to the current working directory, *not* the directory of the Path - object. + relative to the current working directory, *not* the directory of the + :class:`!Path` object. It is implemented in terms of :func:`os.rename` and gives the same guarantees. .. versionchanged:: 3.8 - Added return value, return the new Path instance. + Added return value, return the new :class:`!Path` instance. .. method:: Path.replace(target) - Rename this file or directory to the given *target*, and return a new Path - instance pointing to *target*. If *target* points to an existing file or - empty directory, it will be unconditionally replaced. + Rename this file or directory to the given *target*, and return a new + :class:`!Path` instance pointing to *target*. If *target* points to an + existing file or empty directory, it will be unconditionally replaced. The target path may be absolute or relative. Relative paths are interpreted - relative to the current working directory, *not* the directory of the Path - object. + relative to the current working directory, *not* the directory of the + :class:`!Path` object. .. versionchanged:: 3.8 - Added return value, return the new Path instance. + Added return value, return the new :class:`!Path` instance. + + +.. method:: Path.unlink(missing_ok=False) + + Remove this file or symbolic link. If the path points to a directory, + use :func:`Path.rmdir` instead. + + If *missing_ok* is false (the default), :exc:`FileNotFoundError` is + raised if the path does not exist. + + If *missing_ok* is true, :exc:`FileNotFoundError` exceptions will be + ignored (same behavior as the POSIX ``rm -f`` command). + + .. versionchanged:: 3.8 + The *missing_ok* parameter was added. + + +.. method:: Path.rmdir() + + Remove this directory. The directory must be empty. + + +Permissions and ownership +^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. method:: Path.owner(*, follow_symlinks=True) + + Return the name of the user owning the file. :exc:`KeyError` is raised + if the file's user identifier (UID) isn't found in the system database. + + This method normally follows symlinks; to get the owner of the symlink, add + the argument ``follow_symlinks=False``. + + .. versionchanged:: 3.13 + Raises :exc:`UnsupportedOperation` if the :mod:`pwd` module is not + available. In earlier versions, :exc:`NotImplementedError` was raised. + + .. versionchanged:: 3.13 + The *follow_symlinks* parameter was added. + + +.. method:: Path.group(*, follow_symlinks=True) + + Return the name of the group owning the file. :exc:`KeyError` is raised + if the file's group identifier (GID) isn't found in the system database. + + This method normally follows symlinks; to get the group of the symlink, add + the argument ``follow_symlinks=False``. + + .. versionchanged:: 3.13 + Raises :exc:`UnsupportedOperation` if the :mod:`grp` module is not + available. In earlier versions, :exc:`NotImplementedError` was raised. + + .. versionchanged:: 3.13 + The *follow_symlinks* parameter was added. + + +.. method:: Path.chmod(mode, *, follow_symlinks=True) + + Change the file mode and permissions, like :func:`os.chmod`. + + This method normally follows symlinks. Some Unix flavours support changing + permissions on the symlink itself; on these platforms you may add the + argument ``follow_symlinks=False``, or use :meth:`~Path.lchmod`. + + :: + + >>> p = Path('setup.py') + >>> p.stat().st_mode + 33277 + >>> p.chmod(0o444) + >>> p.stat().st_mode + 33060 + + .. versionchanged:: 3.10 + The *follow_symlinks* parameter was added. + + +.. method:: Path.lchmod(mode) + + Like :meth:`Path.chmod` but, if the path points to a symbolic link, the + symbolic link's mode is changed rather than its target's. + + +Other methods +^^^^^^^^^^^^^ + +.. classmethod:: Path.cwd() + + Return a new path object representing the current directory (as returned + by :func:`os.getcwd`):: + + >>> Path.cwd() + PosixPath('/home/antoine/pathlib') + + +.. classmethod:: Path.home() + + Return a new path object representing the user's home directory (as + returned by :func:`os.path.expanduser` with ``~`` construct). If the home + directory can't be resolved, :exc:`RuntimeError` is raised. + + :: + + >>> Path.home() + PosixPath('/home/antoine') + + .. versionadded:: 3.5 + + +.. method:: Path.expanduser() + + Return a new path with expanded ``~`` and ``~user`` constructs, + as returned by :meth:`os.path.expanduser`. If a home directory can't be + resolved, :exc:`RuntimeError` is raised. + + :: + + >>> p = PosixPath('~/films/Monty Python') + >>> p.expanduser() + PosixPath('/home/eric/films/Monty Python') + + .. versionadded:: 3.5 + + +.. method:: Path.readlink() + + Return the path to which the symbolic link points (as returned by + :func:`os.readlink`):: + + >>> p = Path('mylink') + >>> p.symlink_to('setup.py') + >>> p.readlink() + PosixPath('setup.py') + + .. versionadded:: 3.9 + + .. versionchanged:: 3.13 + Raises :exc:`UnsupportedOperation` if :func:`os.readlink` is not + available. In previous versions, :exc:`NotImplementedError` was raised. .. method:: Path.absolute() @@ -1567,79 +1705,6 @@ Other methods strict mode, and no exception is raised in non-strict mode. In previous versions, :exc:`RuntimeError` is raised no matter the value of *strict*. -.. method:: Path.rmdir() - - Remove this directory. The directory must be empty. - - -.. method:: Path.symlink_to(target, target_is_directory=False) - - Make this path a symbolic link pointing to *target*. - - On Windows, a symlink represents either a file or a directory, and does not - morph to the target dynamically. If the target is present, the type of the - symlink will be created to match. Otherwise, the symlink will be created - as a directory if *target_is_directory* is ``True`` or a file symlink (the - default) otherwise. On non-Windows platforms, *target_is_directory* is ignored. - - :: - - >>> p = Path('mylink') - >>> p.symlink_to('setup.py') - >>> p.resolve() - PosixPath('/home/antoine/pathlib/setup.py') - >>> p.stat().st_size - 956 - >>> p.lstat().st_size - 8 - - .. note:: - The order of arguments (link, target) is the reverse - of :func:`os.symlink`'s. - - .. versionchanged:: 3.13 - Raises :exc:`UnsupportedOperation` if :func:`os.symlink` is not - available. In previous versions, :exc:`NotImplementedError` was raised. - - -.. method:: Path.hardlink_to(target) - - Make this path a hard link to the same file as *target*. - - .. note:: - The order of arguments (link, target) is the reverse - of :func:`os.link`'s. - - .. versionadded:: 3.10 - - .. versionchanged:: 3.13 - Raises :exc:`UnsupportedOperation` if :func:`os.link` is not - available. In previous versions, :exc:`NotImplementedError` was raised. - - -.. method:: Path.touch(mode=0o666, exist_ok=True) - - Create a file at this given path. If *mode* is given, it is combined - with the process' ``umask`` value to determine the file mode and access - flags. If the file already exists, the function succeeds if *exist_ok* - is true (and its modification time is updated to the current time), - otherwise :exc:`FileExistsError` is raised. - - -.. method:: Path.unlink(missing_ok=False) - - Remove this file or symbolic link. If the path points to a directory, - use :func:`Path.rmdir` instead. - - If *missing_ok* is false (the default), :exc:`FileNotFoundError` is - raised if the path does not exist. - - If *missing_ok* is true, :exc:`FileNotFoundError` exceptions will be - ignored (same behavior as the POSIX ``rm -f`` command). - - .. versionchanged:: 3.8 - The *missing_ok* parameter was added. - .. _pathlib-pattern-language: diff --git a/Doc/library/pdb.rst b/Doc/library/pdb.rst index f6085171dccb38..b1e9392ecfd927 100644 --- a/Doc/library/pdb.rst +++ b/Doc/library/pdb.rst @@ -321,11 +321,17 @@ can be overridden by the local file. argument must be an identifier, ``help exec`` must be entered to get help on the ``!`` command. -.. pdbcommand:: w(here) +.. pdbcommand:: w(here) [count] - Print a stack trace, with the most recent frame at the bottom. An arrow (``>``) + Print a stack trace, with the most recent frame at the bottom. if *count* + is 0, print the current frame entry. If *count* is negative, print the least + recent - *count* frames. If *count* is positive, print the most recent + *count* frames. An arrow (``>``) indicates the current frame, which determines the context of most commands. + .. versionchanged:: 3.14 + *count* argument is added. + .. pdbcommand:: d(own) [count] Move the current frame *count* (default one) levels down in the stack trace diff --git a/Doc/library/re.rst b/Doc/library/re.rst index 39788de76b558b..cc979fe66f7fe9 100644 --- a/Doc/library/re.rst +++ b/Doc/library/re.rst @@ -101,7 +101,7 @@ The special characters are: ``.`` (Dot.) In the default mode, this matches any character except a newline. If the :const:`DOTALL` flag has been specified, this matches any character - including a newline. + including a newline. ``(?s:.)`` matches any character regardless of flags. .. index:: single: ^ (caret); in regular expressions @@ -911,6 +911,10 @@ Functions ``None`` if no position in the string matches the pattern; note that this is different from finding a zero-length match at some point in the string. + The expression's behaviour can be modified by specifying a *flags* value. + Values can be any of the `flags`_ variables, combined using bitwise OR + (the ``|`` operator). + .. function:: match(pattern, string, flags=0) @@ -925,6 +929,10 @@ Functions If you want to locate a match anywhere in *string*, use :func:`search` instead (see also :ref:`search-vs-match`). + The expression's behaviour can be modified by specifying a *flags* value. + Values can be any of the `flags`_ variables, combined using bitwise OR + (the ``|`` operator). + .. function:: fullmatch(pattern, string, flags=0) @@ -932,6 +940,10 @@ Functions corresponding :class:`~re.Match`. Return ``None`` if the string does not match the pattern; note that this is different from a zero-length match. + The expression's behaviour can be modified by specifying a *flags* value. + Values can be any of the `flags`_ variables, combined using bitwise OR + (the ``|`` operator). + .. versionadded:: 3.4 @@ -974,6 +986,10 @@ Functions >>> re.split(r'(\W*)', '...words...') ['', '...', '', '', 'w', '', 'o', '', 'r', '', 'd', '', 's', '...', '', '', ''] + The expression's behaviour can be modified by specifying a *flags* value. + Values can be any of the `flags`_ variables, combined using bitwise OR + (the ``|`` operator). + .. versionchanged:: 3.1 Added the optional flags argument. @@ -1004,6 +1020,10 @@ Functions >>> re.findall(r'(\w+)=(\d+)', 'set width=20 and height=10') [('width', '20'), ('height', '10')] + The expression's behaviour can be modified by specifying a *flags* value. + Values can be any of the `flags`_ variables, combined using bitwise OR + (the ``|`` operator). + .. versionchanged:: 3.7 Non-empty matches can now start just after a previous empty match. @@ -1015,6 +1035,10 @@ Functions is scanned left-to-right, and matches are returned in the order found. Empty matches are included in the result. + The expression's behaviour can be modified by specifying a *flags* value. + Values can be any of the `flags`_ variables, combined using bitwise OR + (the ``|`` operator). + .. versionchanged:: 3.7 Non-empty matches can now start just after a previous empty match. @@ -1070,6 +1094,10 @@ Functions character ``'0'``. The backreference ``\g<0>`` substitutes in the entire substring matched by the RE. + The expression's behaviour can be modified by specifying a *flags* value. + Values can be any of the `flags`_ variables, combined using bitwise OR + (the ``|`` operator). + .. versionchanged:: 3.1 Added the optional flags argument. @@ -1102,6 +1130,10 @@ Functions Perform the same operation as :func:`sub`, but return a tuple ``(new_string, number_of_subs_made)``. + The expression's behaviour can be modified by specifying a *flags* value. + Values can be any of the `flags`_ variables, combined using bitwise OR + (the ``|`` operator). + .. function:: escape(pattern) diff --git a/Doc/library/smtplib.rst b/Doc/library/smtplib.rst index 2511ef7f2ada41..7cd530a5fd6438 100644 --- a/Doc/library/smtplib.rst +++ b/Doc/library/smtplib.rst @@ -556,34 +556,33 @@ This example prompts the user for addresses needed in the message envelope ('To' and 'From' addresses), and the message to be delivered. Note that the headers to be included with the message must be included in the message as entered; this example doesn't do any processing of the :rfc:`822` headers. In particular, the -'To' and 'From' addresses must be included in the message headers explicitly. :: +'To' and 'From' addresses must be included in the message headers explicitly:: import smtplib - def prompt(prompt): - return input(prompt).strip() + def prompt(title): + return input(title).strip() - fromaddr = prompt("From: ") - toaddrs = prompt("To: ").split() + from_addr = prompt("From: ") + to_addrs = prompt("To: ").split() print("Enter message, end with ^D (Unix) or ^Z (Windows):") # Add the From: and To: headers at the start! - msg = ("From: %s\r\nTo: %s\r\n\r\n" - % (fromaddr, ", ".join(toaddrs))) + lines = [f"From: {from_addr}", f"To: {', '.join(to_addrs)}", ""] while True: try: line = input() except EOFError: break - if not line: - break - msg = msg + line + else: + lines.append(line) + msg = "\r\n".join(lines) print("Message length is", len(msg)) - server = smtplib.SMTP('localhost') + server = smtplib.SMTP("localhost") server.set_debuglevel(1) - server.sendmail(fromaddr, toaddrs, msg) + server.sendmail(from_addr, to_addrs, msg) server.quit() .. note:: diff --git a/Doc/library/socket.rst b/Doc/library/socket.rst index 2df0257d1f24f0..782fb9b27ae1ba 100644 --- a/Doc/library/socket.rst +++ b/Doc/library/socket.rst @@ -450,6 +450,10 @@ Constants same way that ``SO_BINDTODEVICE`` is used, but with the index of a network interface instead of its name. + .. versionchanged:: 3.14 + Added missing ``IP_RECVERR``, ``IP_RECVTTL``, and ``IP_RECVORIGDSTADDR`` + on Linux. + .. data:: AF_CAN PF_CAN SOL_CAN_* diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst index 99abf45469018e..dc72f67c6361e2 100644 --- a/Doc/library/ssl.rst +++ b/Doc/library/ssl.rst @@ -1472,6 +1472,19 @@ to speed up repeated connections from the same clients. :data:`PROTOCOL_TLS`, :data:`PROTOCOL_TLS_CLIENT`, and :data:`PROTOCOL_TLS_SERVER` use TLS 1.2 as minimum TLS version. + .. note:: + + :class:`SSLContext` only supports limited mutation once it has been used + by a connection. Adding new certificates to the internal trust store is + allowed, but changing ciphers, verification settings, or mTLS + certificates may result in surprising behavior. + + .. note:: + + :class:`SSLContext` is designed to be shared and used by multiple + connections. + Thus, it is thread-safe as long as it is not reconfigured after being + used by a connection. :class:`SSLContext` objects have the following methods and attributes: diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst index c8acde8b57dcdb..34f6e44babe596 100644 --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -1220,7 +1220,7 @@ accepts integers that meet the value restriction ``0 <= x <= 255``). Notes: (1) - *t* must have the same length as the slice it is replacing. + If *k* is not equal to ``1``, *t* must have the same length as the slice it is replacing. (2) The optional argument *i* defaults to ``-1``, so that by default the last diff --git a/Doc/library/symtable.rst b/Doc/library/symtable.rst index e17a33f7feb1ab..aa5f8d95925ada 100644 --- a/Doc/library/symtable.rst +++ b/Doc/library/symtable.rst @@ -31,21 +31,74 @@ Generating Symbol Tables Examining Symbol Tables ----------------------- +.. class:: SymbolTableType + + An enumeration indicating the type of a :class:`SymbolTable` object. + + .. attribute:: MODULE + :value: "module" + + Used for the symbol table of a module. + + .. attribute:: FUNCTION + :value: "function" + + Used for the symbol table of a function. + + .. attribute:: CLASS + :value: "class" + + Used for the symbol table of a class. + + The following members refer to different flavors of + :ref:`annotation scopes `. + + .. attribute:: ANNOTATION + :value: "annotation" + + Used for annotations if ``from __future__ import annotations`` is active. + + .. attribute:: TYPE_ALIAS + :value: "type alias" + + Used for the symbol table of :keyword:`type` constructions. + + .. attribute:: TYPE_PARAMETERS + :value: "type parameters" + + Used for the symbol table of :ref:`generic functions ` + or :ref:`generic classes `. + + .. attribute:: TYPE_VARIABLE + :value: "type variable" + + Used for the symbol table of the bound, the constraint tuple or the + default value of a single type variable in the formal sense, i.e., + a TypeVar, a TypeVarTuple or a ParamSpec object (the latter two do + not support a bound or a constraint tuple). + + .. versionadded:: 3.13 + .. class:: SymbolTable A namespace table for a block. The constructor is not public. .. method:: get_type() - Return the type of the symbol table. Possible values are ``'class'``, - ``'module'``, ``'function'``, ``'annotation'``, ``'TypeVar bound'``, - ``'type alias'``, and ``'type parameter'``. The latter four refer to - different flavors of :ref:`annotation scopes `. + Return the type of the symbol table. Possible values are members + of the :class:`SymbolTableType` enumeration. .. versionchanged:: 3.12 Added ``'annotation'``, ``'TypeVar bound'``, ``'type alias'``, and ``'type parameter'`` as possible return values. + .. versionchanged:: 3.13 + Return values are members of the :class:`SymbolTableType` enumeration. + + The exact values of the returned string may change in the future, + and thus, it is recommended to use :class:`SymbolTableType` members + instead of hard-coded strings. + .. method:: get_id() Return the table's identifier. @@ -127,8 +180,39 @@ Examining Symbol Tables .. method:: get_methods() - Return a tuple containing the names of methods declared in the class. - + Return a tuple containing the names of method-like functions declared + in the class. + + Here, the term 'method' designates *any* function defined in the class + body via :keyword:`def` or :keyword:`async def`. + + Functions defined in a deeper scope (e.g., in an inner class) are not + picked up by :meth:`get_methods`. + + For example: + + >>> import symtable + >>> st = symtable.symtable(''' + ... def outer(): pass + ... + ... class A: + ... def f(): + ... def w(): pass + ... + ... def g(self): pass + ... + ... @classmethod + ... async def h(cls): pass + ... + ... global outer + ... def outer(self): pass + ... ''', 'test', 'exec') + >>> class_A = st.get_children()[2] + >>> class_A.get_methods() + ('f', 'g', 'h') + + Although ``A().f()`` raises :exc:`TypeError` at runtime, ``A.f`` is still + considered as a method-like function. .. class:: Symbol @@ -155,6 +239,8 @@ Examining Symbol Tables Return ``True`` if the symbol is a type parameter. + .. versionadded:: 3.14 + .. method:: is_global() Return ``True`` if the symbol is global. @@ -182,10 +268,42 @@ Examining Symbol Tables Return ``True`` if the symbol is referenced in its block, but not assigned to. + .. method:: is_free_class() + + Return *True* if a class-scoped symbol is free from + the perspective of a method. + + Consider the following example:: + + def f(): + x = 1 # function-scoped + class C: + x = 2 # class-scoped + def method(self): + return x + + In this example, the class-scoped symbol ``x`` is considered to + be free from the perspective of ``C.method``, thereby allowing + the latter to return *1* at runtime and not *2*. + + .. versionadded:: 3.14 + .. method:: is_assigned() Return ``True`` if the symbol is assigned to in its block. + .. method:: is_comp_iter() + + Return ``True`` if the symbol is a comprehension iteration variable. + + .. versionadded:: 3.14 + + .. method:: is_comp_cell() + + Return ``True`` if the symbol is a cell in an inlined comprehension. + + .. versionadded:: 3.14 + .. method:: is_namespace() Return ``True`` if name binding introduces new namespace. diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst index 94de64fcf835fc..7d1d317b9f8f8a 100644 --- a/Doc/library/typing.rst +++ b/Doc/library/typing.rst @@ -27,12 +27,13 @@ This module provides runtime support for type hints. Consider the function below:: - def moon_weight(earth_weight: float) -> str: - return f'On the moon, you would weigh {earth_weight * 0.166} kilograms.' + def surface_area_of_cube(edge_length: float) -> str: + return f"The surface area of the cube is {6 * edge_length ** 2}." -The function ``moon_weight`` takes an argument expected to be an instance of :class:`float`, -as indicated by the *type hint* ``earth_weight: float``. The function is expected to -return an instance of :class:`str`, as indicated by the ``-> str`` hint. +The function ``surface_area_of_cube`` takes an argument expected to +be an instance of :class:`float`, as indicated by the :term:`type hint` +``edge_length: float``. The function is expected to return an instance +of :class:`str`, as indicated by the ``-> str`` hint. While type hints can be simple classes like :class:`float` or :class:`str`, they can also be more complex. The :mod:`typing` module provides a vocabulary of @@ -97,8 +98,9 @@ Type aliases are useful for simplifying complex type signatures. For example:: # The static type checker will treat the previous type signature as # being exactly equivalent to this one. def broadcast_message( - message: str, - servers: Sequence[tuple[tuple[str, int], dict[str, str]]]) -> None: + message: str, + servers: Sequence[tuple[tuple[str, int], dict[str, str]]] + ) -> None: ... The :keyword:`type` statement is new in Python 3.12. For backwards @@ -1454,8 +1456,8 @@ These can be used as types in annotations. They all support subscription using to write such functions in a type-safe manner. If a ``TypeIs`` function is a class or instance method, then the type in - ``TypeIs`` maps to the type of the second parameter after ``cls`` or - ``self``. + ``TypeIs`` maps to the type of the second parameter (after ``cls`` or + ``self``). In short, the form ``def foo(arg: TypeA) -> TypeIs[TypeB]: ...``, means that if ``foo(arg)`` returns ``True``, then ``arg`` is an instance @@ -1871,8 +1873,8 @@ without the dedicated syntax, as documented below. of ``*args``:: def call_soon[*Ts]( - callback: Callable[[*Ts], None], - *args: *Ts + callback: Callable[[*Ts], None], + *args: *Ts ) -> None: ... callback(*args) diff --git a/Doc/library/urllib.parse.rst b/Doc/library/urllib.parse.rst index cd402e87a8224b..27909b763e9e43 100644 --- a/Doc/library/urllib.parse.rst +++ b/Doc/library/urllib.parse.rst @@ -173,7 +173,7 @@ or on combining URL components into a URL string. Added IPv6 URL parsing capabilities. .. versionchanged:: 3.3 - The fragment is now parsed for all URL schemes (unless *allow_fragment* is + The fragment is now parsed for all URL schemes (unless *allow_fragments* is false), in accordance with :rfc:`3986`. Previously, an allowlist of schemes that support fragments existed. diff --git a/Doc/library/xml.etree.elementtree.rst b/Doc/library/xml.etree.elementtree.rst index e5919029c62c93..4c1e7bd7e6734a 100644 --- a/Doc/library/xml.etree.elementtree.rst +++ b/Doc/library/xml.etree.elementtree.rst @@ -508,7 +508,7 @@ Functions `C14N 2.0 `_ transformation function. Canonicalization is a way to normalise XML output in a way that allows - byte-by-byte comparisons and digital signatures. It reduced the freedom + byte-by-byte comparisons and digital signatures. It reduces the freedom that XML serializers have and instead generates a more constrained XML representation. The main restrictions regard the placement of namespace declarations, the ordering of attributes, and ignorable whitespace. diff --git a/Doc/reference/compound_stmts.rst b/Doc/reference/compound_stmts.rst index 42cca0664df71d..8181b9759517f6 100644 --- a/Doc/reference/compound_stmts.rst +++ b/Doc/reference/compound_stmts.rst @@ -245,13 +245,12 @@ handler is started. This search inspects the :keyword:`!except` clauses in turn until one is found that matches the exception. An expression-less :keyword:`!except` clause, if present, must be last; it matches any exception. -For an :keyword:`!except` clause with an expression, -that expression is evaluated, and the clause matches the exception -if the resulting object is "compatible" with the exception. An object is -compatible with an exception if the object is the class or a -:term:`non-virtual base class ` of the exception object, -or a tuple containing an item that is the class or a non-virtual base class -of the exception object. + +For an :keyword:`!except` clause with an expression, the +expression must evaluate to an exception type or a tuple of exception types. +The raised exception matches an :keyword:`!except` clause whose expression evaluates +to the class or a :term:`non-virtual base class ` of the exception object, +or to a tuple that contains such a class. If no :keyword:`!except` clause matches the exception, the search for an exception handler @@ -378,8 +377,10 @@ exception group with an empty message string. :: ... ExceptionGroup('', (BlockingIOError())) -An :keyword:`!except*` clause must have a matching type, -and this type cannot be a subclass of :exc:`BaseExceptionGroup`. +An :keyword:`!except*` clause must have a matching expression; it cannot be ``except*:``. +Furthermore, this expression cannot contain exception group types, because that would +have ambiguous semantics. + It is not possible to mix :keyword:`except` and :keyword:`!except*` in the same :keyword:`try`. :keyword:`break`, :keyword:`continue` and :keyword:`return` diff --git a/Doc/reference/simple_stmts.rst b/Doc/reference/simple_stmts.rst index a253482156d3b4..4f6c0c63ae42be 100644 --- a/Doc/reference/simple_stmts.rst +++ b/Doc/reference/simple_stmts.rst @@ -333,7 +333,9 @@ statement, of a variable or attribute annotation and an optional assignment stat The difference from normal :ref:`assignment` is that only a single target is allowed. -For simple names as assignment targets, if in class or module scope, +The assignment target is considered "simple" if it consists of a single +name that is not enclosed in parentheses. +For simple assignment targets, if in class or module scope, the annotations are evaluated and stored in a special class or module attribute :attr:`__annotations__` that is a dictionary mapping from variable names (mangled if private) to @@ -341,7 +343,8 @@ evaluated annotations. This attribute is writable and is automatically created at the start of class or module body execution, if annotations are found statically. -For expressions as assignment targets, the annotations are evaluated if +If the assignment target is not simple (an attribute, subscript node, or +parenthesized name), the annotation is evaluated if in class or module scope, but not stored. If a name is annotated in a function scope, then this name is local for diff --git a/Doc/requirements-oldest-sphinx.txt b/Doc/requirements-oldest-sphinx.txt index 3ae65bc944da26..4e49ba1a8ededd 100644 --- a/Doc/requirements-oldest-sphinx.txt +++ b/Doc/requirements-oldest-sphinx.txt @@ -14,16 +14,16 @@ python-docs-theme>=2022.1 alabaster==0.7.16 Babel==2.15.0 -certifi==2024.2.2 +certifi==2024.6.2 charset-normalizer==3.3.2 docutils==0.19 idna==3.7 imagesize==1.4.1 Jinja2==3.1.4 MarkupSafe==2.1.5 -packaging==24.0 +packaging==24.1 Pygments==2.18.0 -requests==2.32.2 +requests==2.32.3 snowballstemmer==2.2.0 Sphinx==6.2.1 sphinxcontrib-applehelp==1.0.8 @@ -32,4 +32,4 @@ sphinxcontrib-htmlhelp==2.0.5 sphinxcontrib-jsmath==1.0.1 sphinxcontrib-qthelp==1.0.7 sphinxcontrib-serializinghtml==1.1.10 -urllib3==2.2.1 +urllib3==2.2.2 diff --git a/Doc/tools/.nitignore b/Doc/tools/.nitignore index 4790136a75cba9..66914f79f3d4ec 100644 --- a/Doc/tools/.nitignore +++ b/Doc/tools/.nitignore @@ -17,7 +17,6 @@ Doc/howto/descriptor.rst Doc/howto/enum.rst Doc/library/ast.rst Doc/library/asyncio-extending.rst -Doc/library/asyncio-policy.rst Doc/library/asyncio-subprocess.rst Doc/library/collections.rst Doc/library/dbm.rst diff --git a/Doc/tools/static/rtd_switcher.js b/Doc/tools/static/rtd_switcher.js index a67bb85505a9ca..f5dc7045a0dbc4 100644 --- a/Doc/tools/static/rtd_switcher.js +++ b/Doc/tools/static/rtd_switcher.js @@ -6,42 +6,9 @@ document.addEventListener("readthedocs-addons-data-ready", function(event) { const config = event.detail.data() - - // Add some mocked hardcoded versions pointing to the official - // documentation while migrating to Read the Docs. - // These are only for testing purposes. - // TODO: remove them when managing all the versions on Read the Docs, - // since all the "active, built and not hidden" versions will be shown automatically. - let versions = config.versions.active.concat([ - { - slug: "dev (3.14)", - urls: { - documentation: "https://docs.python.org/3.14/", - } - }, - { - slug: "dev (3.13)", - urls: { - documentation: "https://docs.python.org/3.13/", - } - }, - { - slug: "3.12", - urls: { - documentation: "https://docs.python.org/3.12/", - } - }, - { - slug: "3.11", - urls: { - documentation: "https://docs.python.org/3.11/", - } - }, - ]); - const versionSelect = `