diff -pruN 3.12.0~a7-1/.devcontainer/Dockerfile 3.12.0~b1-1/.devcontainer/Dockerfile
--- 3.12.0~a7-1/.devcontainer/Dockerfile	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/.devcontainer/Dockerfile	2023-05-22 12:07:36.000000000 +0000
@@ -9,8 +9,8 @@ ENV WASMTIME_HOME=/opt/wasmtime
 ENV WASMTIME_VERSION=7.0.0
 ENV WASMTIME_CPU_ARCH=x86_64
 
-RUN dnf -y --nodocs install git clang xz python3-blurb dnf-plugins-core && \
-    dnf -y --nodocs builddep python3 && \
+RUN dnf -y --nodocs --setopt=install_weak_deps=False install /usr/bin/{blurb,clang,curl,git,ln,tar,xz} 'dnf-command(builddep)' && \
+    dnf -y --nodocs --setopt=install_weak_deps=False builddep python3 && \
     dnf -y clean all
 
 RUN mkdir ${WASI_SDK_PATH} && \
diff -pruN 3.12.0~a7-1/.mailmap 3.12.0~b1-1/.mailmap
--- 3.12.0~a7-1/.mailmap	1970-01-01 00:00:00.000000000 +0000
+++ 3.12.0~b1-1/.mailmap	2023-05-22 12:07:36.000000000 +0000
@@ -0,0 +1,3 @@
+# This file sets the canonical name for contributors to the repository.
+# Documentation: https://git-scm.com/docs/gitmailmap
+Amethyst Reese <amethyst@n7.gg> <john@noswap.com>
diff -pruN 3.12.0~a7-1/.pre-commit-config.yaml 3.12.0~b1-1/.pre-commit-config.yaml
--- 3.12.0~a7-1/.pre-commit-config.yaml	1970-01-01 00:00:00.000000000 +0000
+++ 3.12.0~b1-1/.pre-commit-config.yaml	2023-05-22 12:07:36.000000000 +0000
@@ -0,0 +1,7 @@
+repos:
+  - repo: https://github.com/pre-commit/pre-commit-hooks
+    rev: v4.4.0
+    hooks:
+      - id: check-yaml
+      - id: trailing-whitespace
+        types_or: [c, python, rst]
diff -pruN 3.12.0~a7-1/.readthedocs.yml 3.12.0~b1-1/.readthedocs.yml
--- 3.12.0~a7-1/.readthedocs.yml	1970-01-01 00:00:00.000000000 +0000
+++ 3.12.0~b1-1/.readthedocs.yml	2023-05-22 12:07:36.000000000 +0000
@@ -0,0 +1,18 @@
+# Read the Docs configuration file
+# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
+# Project page: https://readthedocs.org/projects/cpython-previews/
+
+version: 2
+
+sphinx:
+   configuration: Doc/conf.py
+
+build:
+  os: ubuntu-22.04
+  tools:
+    python: "3"
+
+  commands:
+    - make -C Doc venv html
+    - mkdir _readthedocs
+    - mv Doc/build/html _readthedocs/html
diff -pruN 3.12.0~a7-1/Doc/Makefile 3.12.0~b1-1/Doc/Makefile
--- 3.12.0~a7-1/Doc/Makefile	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/Makefile	2023-05-22 12:07:36.000000000 +0000
@@ -13,6 +13,7 @@ JOBS         = auto
 PAPER        =
 SOURCES      =
 DISTVERSION  = $(shell $(PYTHON) tools/extensions/patchlevel.py)
+REQUIREMENTS = requirements.txt
 SPHINXERRORHANDLING = -W
 
 # Internal variables.
@@ -154,8 +155,8 @@ venv:
 		echo "To recreate it, remove it first with \`make clean-venv'."; \
 	else \
 		$(PYTHON) -m venv $(VENVDIR); \
-		$(VENVDIR)/bin/python3 -m pip install -U pip setuptools; \
-		$(VENVDIR)/bin/python3 -m pip install -r requirements.txt; \
+		$(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
 
diff -pruN 3.12.0~a7-1/Doc/c-api/bytearray.rst 3.12.0~b1-1/Doc/c-api/bytearray.rst
--- 3.12.0~a7-1/Doc/c-api/bytearray.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/c-api/bytearray.rst	2023-05-22 12:07:36.000000000 +0000
@@ -5,7 +5,7 @@
 Byte Array Objects
 ------------------
 
-.. index:: object: bytearray
+.. index:: pair: object; bytearray
 
 
 .. c:type:: PyByteArrayObject
diff -pruN 3.12.0~a7-1/Doc/c-api/bytes.rst 3.12.0~b1-1/Doc/c-api/bytes.rst
--- 3.12.0~a7-1/Doc/c-api/bytes.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/c-api/bytes.rst	2023-05-22 12:07:36.000000000 +0000
@@ -8,7 +8,7 @@ Bytes Objects
 These functions raise :exc:`TypeError` when expecting a bytes parameter and
 called with a non-bytes parameter.
 
-.. index:: object: bytes
+.. index:: pair: object; bytes
 
 
 .. c:type:: PyBytesObject
diff -pruN 3.12.0~a7-1/Doc/c-api/capsule.rst 3.12.0~b1-1/Doc/c-api/capsule.rst
--- 3.12.0~a7-1/Doc/c-api/capsule.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/c-api/capsule.rst	2023-05-22 12:07:36.000000000 +0000
@@ -5,7 +5,7 @@
 Capsules
 --------
 
-.. index:: object: Capsule
+.. index:: pair: object; Capsule
 
 Refer to :ref:`using-capsules` for more information on using these objects.
 
diff -pruN 3.12.0~a7-1/Doc/c-api/complex.rst 3.12.0~b1-1/Doc/c-api/complex.rst
--- 3.12.0~a7-1/Doc/c-api/complex.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/c-api/complex.rst	2023-05-22 12:07:36.000000000 +0000
@@ -5,7 +5,7 @@
 Complex Number Objects
 ----------------------
 
-.. index:: object: complex number
+.. index:: pair: object; complex number
 
 Python's complex number objects are implemented as two distinct types when
 viewed from the C API:  one is the Python object exposed to Python programs, and
diff -pruN 3.12.0~a7-1/Doc/c-api/concrete.rst 3.12.0~b1-1/Doc/c-api/concrete.rst
--- 3.12.0~a7-1/Doc/c-api/concrete.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/c-api/concrete.rst	2023-05-22 12:07:36.000000000 +0000
@@ -40,7 +40,7 @@ This section describes Python type objec
 Numeric Objects
 ===============
 
-.. index:: object: numeric
+.. index:: pair: object; numeric
 
 .. toctree::
 
@@ -55,7 +55,7 @@ Numeric Objects
 Sequence Objects
 ================
 
-.. index:: object: sequence
+.. index:: pair: object; sequence
 
 Generic operations on sequence objects were discussed in the previous chapter;
 this section deals with the specific kinds of sequence objects that are
@@ -77,7 +77,7 @@ intrinsic to the Python language.
 Container Objects
 =================
 
-.. index:: object: mapping
+.. index:: pair: object; mapping
 
 .. toctree::
 
diff -pruN 3.12.0~a7-1/Doc/c-api/dict.rst 3.12.0~b1-1/Doc/c-api/dict.rst
--- 3.12.0~a7-1/Doc/c-api/dict.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/c-api/dict.rst	2023-05-22 12:07:36.000000000 +0000
@@ -5,7 +5,7 @@
 Dictionary Objects
 ------------------
 
-.. index:: object: dictionary
+.. index:: pair: object; dictionary
 
 
 .. c:type:: PyDictObject
@@ -154,7 +154,7 @@ Dictionary Objects
 
 .. c:function:: Py_ssize_t PyDict_Size(PyObject *p)
 
-   .. index:: builtin: len
+   .. index:: pair: built-in function; len
 
    Return the number of items in the dictionary.  This is equivalent to
    ``len(p)`` on a dictionary.
diff -pruN 3.12.0~a7-1/Doc/c-api/exceptions.rst 3.12.0~b1-1/Doc/c-api/exceptions.rst
--- 3.12.0~a7-1/Doc/c-api/exceptions.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/c-api/exceptions.rst	2023-05-22 12:07:36.000000000 +0000
@@ -602,7 +602,7 @@ Signal Handling
 .. c:function:: int PyErr_CheckSignals()
 
    .. index::
-      module: signal
+      pair: module; signal
       single: SIGINT
       single: KeyboardInterrupt (built-in exception)
 
@@ -633,7 +633,7 @@ Signal Handling
 .. c:function:: void PyErr_SetInterrupt()
 
    .. index::
-      module: signal
+      pair: module; signal
       single: SIGINT
       single: KeyboardInterrupt (built-in exception)
 
@@ -648,7 +648,7 @@ Signal Handling
 .. c:function:: int PyErr_SetInterruptEx(int signum)
 
    .. index::
-      module: signal
+      pair: module; signal
       single: KeyboardInterrupt (built-in exception)
 
    Simulate the effect of a signal arriving. The next time
diff -pruN 3.12.0~a7-1/Doc/c-api/file.rst 3.12.0~b1-1/Doc/c-api/file.rst
--- 3.12.0~a7-1/Doc/c-api/file.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/c-api/file.rst	2023-05-22 12:07:36.000000000 +0000
@@ -5,7 +5,7 @@
 File Objects
 ------------
 
-.. index:: object: file
+.. index:: pair: object; file
 
 These APIs are a minimal emulation of the Python 2 C API for built-in file
 objects, which used to rely on the buffered I/O (:c:expr:`FILE*`) support
diff -pruN 3.12.0~a7-1/Doc/c-api/float.rst 3.12.0~b1-1/Doc/c-api/float.rst
--- 3.12.0~a7-1/Doc/c-api/float.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/c-api/float.rst	2023-05-22 12:07:36.000000000 +0000
@@ -5,7 +5,7 @@
 Floating Point Objects
 ----------------------
 
-.. index:: object: floating point
+.. index:: pair: object; floating point
 
 
 .. c:type:: PyFloatObject
diff -pruN 3.12.0~a7-1/Doc/c-api/frame.rst 3.12.0~b1-1/Doc/c-api/frame.rst
--- 3.12.0~a7-1/Doc/c-api/frame.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/c-api/frame.rst	2023-05-22 12:07:36.000000000 +0000
@@ -130,3 +130,38 @@ See also :ref:`Reflection <reflection>`.
 .. c:function:: int PyFrame_GetLineNumber(PyFrameObject *frame)
 
    Return the line number that *frame* is currently executing.
+
+
+
+Internal Frames
+---------------
+
+Unless using :pep:`523`, you will not need this.
+
+.. c:struct:: _PyInterpreterFrame
+
+   The interpreter's internal frame representation.
+
+   .. versionadded:: 3.11
+
+.. c:function:: PyObject* PyUnstable_InterpreterFrame_GetCode(struct _PyInterpreterFrame *frame);
+
+    Return a :term:`strong reference` to the code object for the frame.
+
+   .. versionadded:: 3.12
+
+
+.. c:function:: int PyUnstable_InterpreterFrame_GetLasti(struct _PyInterpreterFrame *frame);
+
+   Return the byte offset into the last executed instruction.
+
+   .. versionadded:: 3.12
+
+
+.. c:function:: int PyUnstable_InterpreterFrame_GetLine(struct _PyInterpreterFrame *frame);
+
+   Return the currently executing line number, or -1 if there is no line number.
+
+   .. versionadded:: 3.12
+
+
diff -pruN 3.12.0~a7-1/Doc/c-api/function.rst 3.12.0~b1-1/Doc/c-api/function.rst
--- 3.12.0~a7-1/Doc/c-api/function.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/c-api/function.rst	2023-05-22 12:07:36.000000000 +0000
@@ -5,7 +5,7 @@
 Function Objects
 ----------------
 
-.. index:: object: function
+.. index:: pair: object; function
 
 There are a few functions specific to Python functions.
 
diff -pruN 3.12.0~a7-1/Doc/c-api/gcsupport.rst 3.12.0~b1-1/Doc/c-api/gcsupport.rst
--- 3.12.0~a7-1/Doc/c-api/gcsupport.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/c-api/gcsupport.rst	2023-05-22 12:07:36.000000000 +0000
@@ -59,12 +59,31 @@ rules:
    Analogous to :c:func:`PyObject_New` but for container objects with the
    :const:`Py_TPFLAGS_HAVE_GC` flag set.
 
-
 .. c:function:: TYPE* PyObject_GC_NewVar(TYPE, PyTypeObject *type, Py_ssize_t size)
 
    Analogous to :c:func:`PyObject_NewVar` but for container objects with the
    :const:`Py_TPFLAGS_HAVE_GC` flag set.
 
+.. c:function:: PyObject* PyUnstable_Object_GC_NewWithExtraData(PyTypeObject *type, size_t extra_size)
+
+   Analogous to :c:func:`PyObject_GC_New` but allocates *extra_size*
+   bytes at the end of the object (at offset
+   :c:member:`~PyTypeObject.tp_basicsize`).
+   The allocated memory is initialized to zeros,
+   except for the :c:type:`Python object header <PyObject>`.
+
+   The extra data will be deallocated with the object, but otherwise it is
+   not managed by Python.
+
+   .. warning::
+      The function is marked as unstable because the final mechanism
+      for reserving extra data after an instance is not yet decided.
+      For allocating a variable number of fields, prefer using
+      :c:type:`PyVarObject` and :c:member:`~PyTypeObject.tp_itemsize`
+      instead.
+
+   .. versionadded:: 3.12
+
 
 .. c:function:: TYPE* PyObject_GC_Resize(TYPE, PyVarObject *op, Py_ssize_t newsize)
 
diff -pruN 3.12.0~a7-1/Doc/c-api/import.rst 3.12.0~b1-1/Doc/c-api/import.rst
--- 3.12.0~a7-1/Doc/c-api/import.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/c-api/import.rst	2023-05-22 12:07:36.000000000 +0000
@@ -41,7 +41,7 @@ Importing Modules
 
 .. c:function:: PyObject* PyImport_ImportModuleEx(const char *name, PyObject *globals, PyObject *locals, PyObject *fromlist)
 
-   .. index:: builtin: __import__
+   .. index:: pair: built-in function; __import__
 
    Import a module.  This is best described by referring to the built-in Python
    function :func:`__import__`.
@@ -120,7 +120,7 @@ Importing Modules
 
 .. c:function:: PyObject* PyImport_ExecCodeModule(const char *name, PyObject *co)
 
-   .. index:: builtin: compile
+   .. index:: pair: built-in function; compile
 
    Given a module name (possibly of the form ``package.module``) and a code object
    read from a Python bytecode file or obtained from the built-in function
@@ -186,8 +186,10 @@ Importing Modules
 
    .. versionadded:: 3.2
    .. versionchanged:: 3.3
-      Uses :func:`imp.source_from_cache()` in calculating the source path if
+      Uses :func:`!imp.source_from_cache()` in calculating the source path if
       only the bytecode path is provided.
+   .. versionchanged:: 3.12
+      No longer uses the removed :mod:`!imp` module.
 
 
 .. c:function:: long PyImport_GetMagicNumber()
diff -pruN 3.12.0~a7-1/Doc/c-api/init.rst 3.12.0~b1-1/Doc/c-api/init.rst
--- 3.12.0~a7-1/Doc/c-api/init.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/c-api/init.rst	2023-05-22 12:07:36.000000000 +0000
@@ -336,9 +336,9 @@ Initializing and finalizing the interpre
       single: PyEval_InitThreads()
       single: modules (in module sys)
       single: path (in module sys)
-      module: builtins
-      module: __main__
-      module: sys
+      pair: module; builtins
+      pair: module; __main__
+      pair: module; sys
       triple: module; search; path
       single: PySys_SetArgv()
       single: PySys_SetArgvEx()
@@ -1051,7 +1051,7 @@ code, or when embedding the Python inter
 
    .. deprecated:: 3.9
 
-   .. index:: module: _thread
+   .. index:: pair: module; _thread
 
 
 .. c:function:: int PyEval_ThreadsInitialized()
@@ -1494,9 +1494,9 @@ function. You can create and destroy the
 .. c:function:: PyThreadState* Py_NewInterpreter()
 
    .. index::
-      module: builtins
-      module: __main__
-      module: sys
+      pair: module; builtins
+      pair: module; __main__
+      pair: module; sys
       single: stdout (in module sys)
       single: stderr (in module sys)
       single: stdin (in module sys)
diff -pruN 3.12.0~a7-1/Doc/c-api/intro.rst 3.12.0~b1-1/Doc/c-api/intro.rst
--- 3.12.0~a7-1/Doc/c-api/intro.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/c-api/intro.rst	2023-05-22 12:07:36.000000000 +0000
@@ -261,7 +261,7 @@ complete listing.
 Objects, Types and Reference Counts
 ===================================
 
-.. index:: object: type
+.. index:: pair: object; type
 
 Most Python/C API functions have one or more arguments as well as a return value
 of type :c:expr:`PyObject*`.  This type is a pointer to an opaque data type
@@ -705,9 +705,9 @@ interpreter can only be used after the i
 
 .. index::
    single: Py_Initialize()
-   module: builtins
-   module: __main__
-   module: sys
+   pair: module; builtins
+   pair: module; __main__
+   pair: module; sys
    triple: module; search; path
    single: path (in module sys)
 
diff -pruN 3.12.0~a7-1/Doc/c-api/list.rst 3.12.0~b1-1/Doc/c-api/list.rst
--- 3.12.0~a7-1/Doc/c-api/list.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/c-api/list.rst	2023-05-22 12:07:36.000000000 +0000
@@ -5,7 +5,7 @@
 List Objects
 ------------
 
-.. index:: object: list
+.. index:: pair: object; list
 
 
 .. c:type:: PyListObject
@@ -45,7 +45,7 @@ List Objects
 
 .. c:function:: Py_ssize_t PyList_Size(PyObject *list)
 
-   .. index:: builtin: len
+   .. index:: pair: built-in function; len
 
    Return the length of the list object in *list*; this is equivalent to
    ``len(list)`` on a list object.
@@ -138,7 +138,7 @@ List Objects
 
 .. c:function:: PyObject* PyList_AsTuple(PyObject *list)
 
-   .. index:: builtin: tuple
+   .. index:: pair: built-in function; tuple
 
    Return a new tuple object containing the contents of *list*; equivalent to
    ``tuple(list)``.
diff -pruN 3.12.0~a7-1/Doc/c-api/long.rst 3.12.0~b1-1/Doc/c-api/long.rst
--- 3.12.0~a7-1/Doc/c-api/long.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/c-api/long.rst	2023-05-22 12:07:36.000000000 +0000
@@ -5,8 +5,8 @@
 Integer Objects
 ---------------
 
-.. index:: object: long integer
-           object: integer
+.. index:: pair: object; long integer
+           pair: object; integer
 
 All integers are implemented as "long" integer objects of arbitrary size.
 
@@ -322,3 +322,27 @@ distinguished from a number.  Use :c:fun
    with :c:func:`PyLong_FromVoidPtr`.
 
    Returns ``NULL`` on error.  Use :c:func:`PyErr_Occurred` to disambiguate.
+
+
+.. c:function:: int PyUnstable_Long_IsCompact(const PyLongObject* op)
+
+   Return 1 if *op* is compact, 0 otherwise.
+
+   This function makes it possible for performance-critical code to implement
+   a “fast path” for small integers. For compact values use
+   :c:func:`PyUnstable_Long_CompactValue`; for others fall back to a
+   :c:func:`PyLong_As* <PyLong_AsSize_t>` function or
+   :c:func:`calling <PyObject_CallMethod>` :meth:`int.to_bytes`.
+
+   The speedup is expected to be negligible for most users.
+
+   Exactly what values are considered compact is an implementation detail
+   and is subject to change.
+
+.. c:function:: Py_ssize_t PyUnstable_Long_CompactValue(const PyLongObject* op)
+
+   If *op* is compact, as determined by :c:func:`PyUnstable_Long_IsCompact`,
+   return its value.
+
+   Otherwise, the return value is undefined.
+
diff -pruN 3.12.0~a7-1/Doc/c-api/mapping.rst 3.12.0~b1-1/Doc/c-api/mapping.rst
--- 3.12.0~a7-1/Doc/c-api/mapping.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/c-api/mapping.rst	2023-05-22 12:07:36.000000000 +0000
@@ -20,7 +20,7 @@ See also :c:func:`PyObject_GetItem`, :c:
 .. c:function:: Py_ssize_t PyMapping_Size(PyObject *o)
                Py_ssize_t PyMapping_Length(PyObject *o)
 
-   .. index:: builtin: len
+   .. index:: pair: built-in function; len
 
    Returns the number of keys in object *o* on success, and ``-1`` on failure.
    This is equivalent to the Python expression ``len(o)``.
diff -pruN 3.12.0~a7-1/Doc/c-api/memoryview.rst 3.12.0~b1-1/Doc/c-api/memoryview.rst
--- 3.12.0~a7-1/Doc/c-api/memoryview.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/c-api/memoryview.rst	2023-05-22 12:07:36.000000000 +0000
@@ -3,7 +3,7 @@
 .. _memoryview-objects:
 
 .. index::
-   object: memoryview
+   pair: object; memoryview
 
 MemoryView objects
 ------------------
diff -pruN 3.12.0~a7-1/Doc/c-api/method.rst 3.12.0~b1-1/Doc/c-api/method.rst
--- 3.12.0~a7-1/Doc/c-api/method.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/c-api/method.rst	2023-05-22 12:07:36.000000000 +0000
@@ -5,7 +5,7 @@
 Instance Method Objects
 -----------------------
 
-.. index:: object: instancemethod
+.. index:: pair: object; instancemethod
 
 An instance method is a wrapper for a :c:data:`PyCFunction` and the new way
 to bind a :c:data:`PyCFunction` to a class object. It replaces the former call
@@ -47,7 +47,7 @@ to bind a :c:data:`PyCFunction` to a cla
 Method Objects
 --------------
 
-.. index:: object: method
+.. index:: pair: object; method
 
 Methods are bound function objects. Methods are always bound to an instance of
 a user-defined class. Unbound methods (methods bound to a class object) are
diff -pruN 3.12.0~a7-1/Doc/c-api/module.rst 3.12.0~b1-1/Doc/c-api/module.rst
--- 3.12.0~a7-1/Doc/c-api/module.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/c-api/module.rst	2023-05-22 12:07:36.000000000 +0000
@@ -5,7 +5,7 @@
 Module Objects
 --------------
 
-.. index:: object: module
+.. index:: pair: object; module
 
 
 .. c:var:: PyTypeObject PyModule_Type
diff -pruN 3.12.0~a7-1/Doc/c-api/none.rst 3.12.0~b1-1/Doc/c-api/none.rst
--- 3.12.0~a7-1/Doc/c-api/none.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/c-api/none.rst	2023-05-22 12:07:36.000000000 +0000
@@ -5,7 +5,7 @@
 The ``None`` Object
 -------------------
 
-.. index:: object: None
+.. index:: pair: object; None
 
 Note that the :c:type:`PyTypeObject` for ``None`` is not directly exposed in the
 Python/C API.  Since ``None`` is a singleton, testing for object identity (using
diff -pruN 3.12.0~a7-1/Doc/c-api/number.rst 3.12.0~b1-1/Doc/c-api/number.rst
--- 3.12.0~a7-1/Doc/c-api/number.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/c-api/number.rst	2023-05-22 12:07:36.000000000 +0000
@@ -64,7 +64,7 @@ Number Protocol
 
 .. c:function:: PyObject* PyNumber_Divmod(PyObject *o1, PyObject *o2)
 
-   .. index:: builtin: divmod
+   .. index:: pair: built-in function; divmod
 
    See the built-in function :func:`divmod`. Returns ``NULL`` on failure.  This is
    the equivalent of the Python expression ``divmod(o1, o2)``.
@@ -72,7 +72,7 @@ Number Protocol
 
 .. c:function:: PyObject* PyNumber_Power(PyObject *o1, PyObject *o2, PyObject *o3)
 
-   .. index:: builtin: pow
+   .. index:: pair: built-in function; pow
 
    See the built-in function :func:`pow`. Returns ``NULL`` on failure.  This is the
    equivalent of the Python expression ``pow(o1, o2, o3)``, where *o3* is optional.
@@ -94,7 +94,7 @@ Number Protocol
 
 .. c:function:: PyObject* PyNumber_Absolute(PyObject *o)
 
-   .. index:: builtin: abs
+   .. index:: pair: built-in function; abs
 
    Returns the absolute value of *o*, or ``NULL`` on failure.  This is the equivalent
    of the Python expression ``abs(o)``.
@@ -192,7 +192,7 @@ Number Protocol
 
 .. c:function:: PyObject* PyNumber_InPlacePower(PyObject *o1, PyObject *o2, PyObject *o3)
 
-   .. index:: builtin: pow
+   .. index:: pair: built-in function; pow
 
    See the built-in function :func:`pow`. Returns ``NULL`` on failure.  The operation
    is done *in-place* when *o1* supports it.  This is the equivalent of the Python
@@ -238,7 +238,7 @@ Number Protocol
 
 .. c:function:: PyObject* PyNumber_Long(PyObject *o)
 
-   .. index:: builtin: int
+   .. index:: pair: built-in function; int
 
    Returns the *o* converted to an integer object on success, or ``NULL`` on
    failure.  This is the equivalent of the Python expression ``int(o)``.
@@ -246,7 +246,7 @@ Number Protocol
 
 .. c:function:: PyObject* PyNumber_Float(PyObject *o)
 
-   .. index:: builtin: float
+   .. index:: pair: built-in function; float
 
    Returns the *o* converted to a float object on success, or ``NULL`` on failure.
    This is the equivalent of the Python expression ``float(o)``.
diff -pruN 3.12.0~a7-1/Doc/c-api/object.rst 3.12.0~b1-1/Doc/c-api/object.rst
--- 3.12.0~a7-1/Doc/c-api/object.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/c-api/object.rst	2023-05-22 12:07:36.000000000 +0000
@@ -190,7 +190,7 @@ Object Protocol
 
 .. c:function:: PyObject* PyObject_Repr(PyObject *o)
 
-   .. index:: builtin: repr
+   .. index:: pair: built-in function; repr
 
    Compute a string representation of object *o*.  Returns the string
    representation on success, ``NULL`` on failure.  This is the equivalent of the
@@ -202,7 +202,7 @@ Object Protocol
 
 .. c:function:: PyObject* PyObject_ASCII(PyObject *o)
 
-   .. index:: builtin: ascii
+   .. index:: pair: built-in function; ascii
 
    As :c:func:`PyObject_Repr`, compute a string representation of object *o*, but
    escape the non-ASCII characters in the string returned by
@@ -227,7 +227,7 @@ Object Protocol
 
 .. c:function:: PyObject* PyObject_Bytes(PyObject *o)
 
-   .. index:: builtin: bytes
+   .. index:: pair: built-in function; bytes
 
    Compute a bytes representation of object *o*.  ``NULL`` is returned on
    failure and a bytes object on success.  This is equivalent to the Python
@@ -278,7 +278,7 @@ Object Protocol
 
 .. c:function:: Py_hash_t PyObject_Hash(PyObject *o)
 
-   .. index:: builtin: hash
+   .. index:: pair: built-in function; hash
 
    Compute and return the hash value of an object *o*.  On failure, return ``-1``.
    This is the equivalent of the Python expression ``hash(o)``.
@@ -312,7 +312,7 @@ Object Protocol
 
 .. c:function:: PyObject* PyObject_Type(PyObject *o)
 
-   .. index:: builtin: type
+   .. index:: pair: built-in function; type
 
    When *o* is non-``NULL``, returns a type object corresponding to the object type
    of object *o*. On failure, raises :exc:`SystemError` and returns ``NULL``.  This
@@ -332,7 +332,7 @@ Object Protocol
 .. c:function:: Py_ssize_t PyObject_Size(PyObject *o)
                Py_ssize_t PyObject_Length(PyObject *o)
 
-   .. index:: builtin: len
+   .. index:: pair: built-in function; len
 
    Return the length of object *o*.  If the object *o* provides either the sequence
    and mapping protocols, the sequence length is returned.  On error, ``-1`` is
@@ -395,3 +395,42 @@ Object Protocol
    returns ``NULL`` if the object cannot be iterated.
 
    .. versionadded:: 3.10
+
+.. c:function:: void *PyObject_GetTypeData(PyObject *o, PyTypeObject *cls)
+
+   Get a pointer to subclass-specific data reserved for *cls*.
+
+   The object *o* must be an instance of *cls*, and *cls* must have been
+   created using negative :c:member:`PyType_Spec.basicsize`.
+   Python does not check this.
+
+   On error, set an exception and return ``NULL``.
+
+   .. versionadded:: 3.12
+
+.. c:function:: Py_ssize_t PyType_GetTypeDataSize(PyTypeObject *cls)
+
+   Return the size of the instance memory space reserved for *cls*, i.e. the size of the
+   memory :c:func:`PyObject_GetTypeData` returns.
+
+   This may be larger than requested using :c:member:`-PyType_Spec.basicsize <PyType_Spec.basicsize>`;
+   it is safe to use this larger size (e.g. with :c:func:`!memset`).
+
+   The type *cls* **must** have been created using
+   negative :c:member:`PyType_Spec.basicsize`.
+   Python does not check this.
+
+   On error, set an exception and return a negative value.
+
+   .. versionadded:: 3.12
+
+.. c:function:: void *PyObject_GetItemData(PyObject *o)
+
+   Get a pointer to per-item data for a class with
+   :const:`Py_TPFLAGS_ITEMS_AT_END`.
+
+   On error, set an exception and return ``NULL``.
+   :py:exc:`TypeError` is raised if *o* does not have
+   :const:`Py_TPFLAGS_ITEMS_AT_END` set.
+
+   .. versionadded:: 3.12
diff -pruN 3.12.0~a7-1/Doc/c-api/perfmaps.rst 3.12.0~b1-1/Doc/c-api/perfmaps.rst
--- 3.12.0~a7-1/Doc/c-api/perfmaps.rst	1970-01-01 00:00:00.000000000 +0000
+++ 3.12.0~b1-1/Doc/c-api/perfmaps.rst	2023-05-22 12:07:36.000000000 +0000
@@ -0,0 +1,50 @@
+.. highlight:: c
+
+.. _perfmaps:
+
+Support for Perf Maps
+----------------------
+
+On supported platforms (as of this writing, only Linux), the runtime can take
+advantage of *perf map files* to make Python functions visible to an external
+profiling tool (such as `perf <https://perf.wiki.kernel.org/index.php/Main_Page>`_).
+A running process may create a file in the ``/tmp`` directory, which contains entries
+that can map a section of executable code to a name. This interface is described in the
+`documentation of the Linux Perf tool <https://git.kernel.org/pub/scm/linux/
+kernel/git/torvalds/linux.git/tree/tools/perf/Documentation/jit-interface.txt>`_.
+
+In Python, these helper APIs can be used by libraries and features that rely
+on generating machine code on the fly.
+
+Note that holding the Global Interpreter Lock (GIL) is not required for these APIs.
+
+.. c:function:: int PyUnstable_PerfMapState_Init(void)
+
+   Open the ``/tmp/perf-$pid.map`` file, unless it's already opened, and create
+   a lock to ensure thread-safe writes to the file (provided the writes are
+   done through :c:func:`PyUnstable_WritePerfMapEntry`). Normally, there's no need
+   to call this explicitly; just use :c:func:`PyUnstable_WritePerfMapEntry`
+   and it will initialize the state on first call.
+
+   Returns ``0`` on success, ``-1`` on failure to create/open the perf map file,
+   or ``-2`` on failure to create a lock. Check ``errno`` for more information
+   about the cause of a failure.
+
+.. c:function:: int PyUnstable_WritePerfMapEntry(const void *code_addr, unsigned int code_size, const char *entry_name)
+
+   Write one single entry to the ``/tmp/perf-$pid.map`` file. This function is
+   thread safe. Here is what an example entry looks like::
+
+      # address      size  name
+      7f3529fcf759 b     py::bar:/run/t.py
+
+   Will call :c:func:`PyUnstable_PerfMapState_Init` before writing the entry, if
+   the perf map file is not already opened. Returns ``0`` on success, or the
+   same error codes as :c:func:`PyUnstable_PerfMapState_Init` on failure.
+
+.. c:function:: void PyUnstable_PerfMapState_Fini(void)
+
+   Close the perf map file opened by :c:func:`PyUnstable_PerfMapState_Init`.
+   This is called by the runtime itself during interpreter shut-down. In
+   general, there shouldn't be a reason to explicitly call this, except to
+   handle specific scenarios such as forking.
diff -pruN 3.12.0~a7-1/Doc/c-api/sequence.rst 3.12.0~b1-1/Doc/c-api/sequence.rst
--- 3.12.0~a7-1/Doc/c-api/sequence.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/c-api/sequence.rst	2023-05-22 12:07:36.000000000 +0000
@@ -18,7 +18,7 @@ Sequence Protocol
 .. c:function:: Py_ssize_t PySequence_Size(PyObject *o)
                Py_ssize_t PySequence_Length(PyObject *o)
 
-   .. index:: builtin: len
+   .. index:: pair: built-in function; len
 
    Returns the number of objects in sequence *o* on success, and ``-1`` on
    failure.  This is equivalent to the Python expression ``len(o)``.
@@ -120,7 +120,7 @@ Sequence Protocol
 
 .. c:function:: PyObject* PySequence_Tuple(PyObject *o)
 
-   .. index:: builtin: tuple
+   .. index:: pair: built-in function; tuple
 
    Return a tuple object with the same contents as the sequence or iterable *o*,
    or ``NULL`` on failure.  If *o* is a tuple, a new reference will be returned,
diff -pruN 3.12.0~a7-1/Doc/c-api/set.rst 3.12.0~b1-1/Doc/c-api/set.rst
--- 3.12.0~a7-1/Doc/c-api/set.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/c-api/set.rst	2023-05-22 12:07:36.000000000 +0000
@@ -9,8 +9,8 @@ Set Objects
 
 
 .. index::
-   object: set
-   object: frozenset
+   pair: object; set
+   pair: object; frozenset
 
 This section details the public API for :class:`set` and :class:`frozenset`
 objects.  Any functionality not listed below is best accessed using either
@@ -107,7 +107,7 @@ or :class:`frozenset` or instances of th
 
 .. c:function:: Py_ssize_t PySet_Size(PyObject *anyset)
 
-   .. index:: builtin: len
+   .. index:: pair: built-in function; len
 
    Return the length of a :class:`set` or :class:`frozenset` object. Equivalent to
    ``len(anyset)``.  Raises a :exc:`PyExc_SystemError` if *anyset* is not a
diff -pruN 3.12.0~a7-1/Doc/c-api/structures.rst 3.12.0~b1-1/Doc/c-api/structures.rst
--- 3.12.0~a7-1/Doc/c-api/structures.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/c-api/structures.rst	2023-05-22 12:07:36.000000000 +0000
@@ -347,7 +347,7 @@ method.
 
 .. data:: METH_CLASS
 
-   .. index:: builtin: classmethod
+   .. index:: pair: built-in function; classmethod
 
    The method will be passed the type object as the first parameter rather
    than an instance of the type.  This is used to create *class methods*,
@@ -357,7 +357,7 @@ method.
 
 .. data:: METH_STATIC
 
-   .. index:: builtin: staticmethod
+   .. index:: pair: built-in function; staticmethod
 
    The method will be passed ``NULL`` as the first parameter rather than an
    instance of the type.  This is used to create *static methods*, similar to
@@ -486,6 +486,22 @@ The following flags can be used with :c:
    Emit an ``object.__getattr__`` :ref:`audit event <audit-events>`
    before reading.
 
+.. c:macro:: Py_RELATIVE_OFFSET
+
+   Indicates that the :c:member:`~PyMemberDef.offset` of this ``PyMemberDef``
+   entry indicates an offset from the subclass-specific data, rather than
+   from ``PyObject``.
+
+   Can only be used as part of :c:member:`Py_tp_members <PyTypeObject.tp_members>`
+   :c:type:`slot <PyTypeSlot>` when creating a class using negative
+   :c:member:`~PyTypeDef.basicsize`.
+   It is mandatory in that case.
+
+   This flag is only used in :c:type:`PyTypeSlot`.
+   When setting :c:member:`~PyTypeObject.tp_members` during
+   class creation, Python clears it and sets
+   :c:member:`PyMemberDef.offset` to the offset from the ``PyObject`` struct.
+
 .. index::
    single: READ_RESTRICTED
    single: WRITE_RESTRICTED
diff -pruN 3.12.0~a7-1/Doc/c-api/tuple.rst 3.12.0~b1-1/Doc/c-api/tuple.rst
--- 3.12.0~a7-1/Doc/c-api/tuple.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/c-api/tuple.rst	2023-05-22 12:07:36.000000000 +0000
@@ -5,7 +5,7 @@
 Tuple Objects
 -------------
 
-.. index:: object: tuple
+.. index:: pair: object; tuple
 
 
 .. c:type:: PyTupleObject
diff -pruN 3.12.0~a7-1/Doc/c-api/type.rst 3.12.0~b1-1/Doc/c-api/type.rst
--- 3.12.0~a7-1/Doc/c-api/type.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/c-api/type.rst	2023-05-22 12:07:36.000000000 +0000
@@ -5,7 +5,7 @@
 Type Objects
 ------------
 
-.. index:: object: type
+.. index:: pair: object; type
 
 
 .. c:type:: PyTypeObject
@@ -232,6 +232,15 @@ Type Objects
 
    .. versionadded:: 3.11
 
+.. c:function:: int PyUnstable_Type_AssignVersionTag(PyTypeObject *type)
+
+   Attempt to assign a version tag to the given type.
+
+   Returns 1 if the type already had a valid version tag or a new one was
+   assigned, or 0 if a new tag could not be assigned.
+
+   .. versionadded:: 3.12
+
 
 Creating Heap-Allocated Types
 .............................
@@ -247,8 +256,13 @@ The following functions and structs are
    The metaclass *metaclass* is used to construct the resulting type object.
    When *metaclass* is ``NULL``, the metaclass is derived from *bases*
    (or *Py_tp_base[s]* slots if *bases* is ``NULL``, see below).
-   Note that metaclasses that override
-   :c:member:`~PyTypeObject.tp_new` are not supported.
+
+   Metaclasses that override :c:member:`~PyTypeObject.tp_new` are not
+   supported.
+   (For backwards compatibility, other ``PyType_From*`` functions allow
+   such metaclasses. They ignore ``tp_new``, which may result in incomplete
+   initialization. This is deprecated and in Python 3.14+ such metaclasses will
+   not be supported.)
 
    The *bases* argument can be used to specify base classes; it can either
    be only one class or a tuple of classes.
@@ -296,6 +310,11 @@ The following functions and structs are
       The function now finds and uses a metaclass corresponding to the provided
       base classes.  Previously, only :class:`type` instances were returned.
 
+      The :c:member:`~PyTypeObject.tp_new` of the metaclass is *ignored*.
+      which may result in incomplete initialization.
+      Creating classes whose metaclass overrides
+      :c:member:`~PyTypeObject.tp_new` is deprecated and in Python 3.14+ it
+      will be no longer allowed.
 
 .. c:function:: PyObject* PyType_FromSpecWithBases(PyType_Spec *spec, PyObject *bases)
 
@@ -308,6 +327,12 @@ The following functions and structs are
       The function now finds and uses a metaclass corresponding to the provided
       base classes.  Previously, only :class:`type` instances were returned.
 
+      The :c:member:`~PyTypeObject.tp_new` of the metaclass is *ignored*.
+      which may result in incomplete initialization.
+      Creating classes whose metaclass overrides
+      :c:member:`~PyTypeObject.tp_new` is deprecated and in Python 3.14+ it
+      will be no longer allowed.
+
 .. c:function:: PyObject* PyType_FromSpec(PyType_Spec *spec)
 
    Equivalent to ``PyType_FromMetaclass(NULL, NULL, spec, NULL)``.
@@ -318,29 +343,67 @@ The following functions and structs are
       base classes provided in *Py_tp_base[s]* slots.
       Previously, only :class:`type` instances were returned.
 
+      The :c:member:`~PyTypeObject.tp_new` of the metaclass is *ignored*.
+      which may result in incomplete initialization.
+      Creating classes whose metaclass overrides
+      :c:member:`~PyTypeObject.tp_new` is deprecated and in Python 3.14+ it
+      will be no longer allowed.
+
 .. c:type:: PyType_Spec
 
    Structure defining a type's behavior.
 
-   .. c:member:: const char* PyType_Spec.name
+   .. c:member:: const char* name
 
       Name of the type, used to set :c:member:`PyTypeObject.tp_name`.
 
-   .. c:member:: int PyType_Spec.basicsize
-   .. c:member:: int PyType_Spec.itemsize
+   .. c:member:: int basicsize
+
+      If positive, specifies the size of the instance in bytes.
+      It is used to set :c:member:`PyTypeObject.tp_basicsize`.
+
+      If zero, specifies that :c:member:`~PyTypeObject.tp_basicsize`
+      should be inherited.
 
-      Size of the instance in bytes, used to set
-      :c:member:`PyTypeObject.tp_basicsize` and
-      :c:member:`PyTypeObject.tp_itemsize`.
+      If negative, the absolute value specifies how much space instances of the
+      class need *in addition* to the superclass.
+      Use :c:func:`PyObject_GetTypeData` to get a pointer to subclass-specific
+      memory reserved this way.
+
+      .. versionchanged:: 3.12
+
+         Previously, this field could not be negative.
+
+   .. c:member:: int itemsize
+
+      Size of one element of a variable-size type, in bytes.
+      Used to set :c:member:`PyTypeObject.tp_itemsize`.
+      See ``tp_itemsize`` documentation for caveats.
+
+      If zero, :c:member:`~PyTypeObject.tp_itemsize` is inherited.
+      Extending arbitrary variable-sized classes is dangerous,
+      since some types use a fixed offset for variable-sized memory,
+      which can then overlap fixed-sized memory used by a subclass.
+      To help prevent mistakes, inheriting ``itemsize`` is only possible
+      in the following situations:
+
+      - The base is not variable-sized (its
+        :c:member:`~PyTypeObject.tp_itemsize`).
+      - The requested :c:member:`PyType_Spec.basicsize` is positive,
+        suggesting that the memory layout of the base class is known.
+      - The requested :c:member:`PyType_Spec.basicsize` is zero,
+        suggesting that the subclass does not access the instance's memory
+        directly.
+      - With the :const:`Py_TPFLAGS_ITEMS_AT_END` flag.
 
-   .. c:member:: int PyType_Spec.flags
+   .. c:member:: unsigned int flags
 
       Type flags, used to set :c:member:`PyTypeObject.tp_flags`.
 
       If the ``Py_TPFLAGS_HEAPTYPE`` flag is not set,
       :c:func:`PyType_FromSpecWithBases` sets it automatically.
 
-   .. c:member:: PyType_Slot *PyType_Spec.slots
+   .. c:member:: PyType_Slot *slots
 
       Array of :c:type:`PyType_Slot` structures.
       Terminated by the special slot value ``{0, NULL}``.
diff -pruN 3.12.0~a7-1/Doc/c-api/typeobj.rst 3.12.0~b1-1/Doc/c-api/typeobj.rst
--- 3.12.0~a7-1/Doc/c-api/typeobj.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/c-api/typeobj.rst	2023-05-22 12:07:36.000000000 +0000
@@ -805,7 +805,7 @@ and :c:type:`PyType_Type` effectively ac
 
 .. c:member:: reprfunc PyTypeObject.tp_repr
 
-   .. index:: builtin: repr
+   .. index:: pair: built-in function; repr
 
    An optional pointer to a function that implements the built-in function
    :func:`repr`.
@@ -870,7 +870,7 @@ and :c:type:`PyType_Type` effectively ac
 
 .. c:member:: hashfunc PyTypeObject.tp_hash
 
-   .. index:: builtin: hash
+   .. index:: pair: built-in function; hash
 
    An optional pointer to a function that implements the built-in function
    :func:`hash`.
@@ -1145,7 +1145,7 @@ and :c:type:`PyType_Type` effectively ac
 
     .. data:: Py_TPFLAGS_MANAGED_DICT
 
-       This bit indicates that instances of the class have a ``__dict___``
+       This bit indicates that instances of the class have a ``__dict__``
        attribute, and that the space for the dictionary is managed by the VM.
 
        If this flag is set, :const:`Py_TPFLAGS_HAVE_GC` should also be set.
@@ -1171,6 +1171,26 @@ and :c:type:`PyType_Type` effectively ac
       :c:member:`~PyTypeObject.tp_weaklistoffset` field is set in a superclass.
 
 
+   .. data:: Py_TPFLAGS_ITEMS_AT_END
+
+      Only usable with variable-size types, i.e. ones with non-zero
+      :c:member:`~PyObject.tp_itemsize`.
+
+      Indicates that the variable-sized portion of an instance of this type is
+      at the end of the instance's memory area, at an offset of
+      :c:expr:`Py_TYPE(obj)->tp_basicsize` (which may be different in each
+      subclass).
+
+      When setting this flag, be sure that all superclasses either
+      use this memory layout, or are not variable-sized.
+      Python does not check this.
+
+      .. versionadded:: 3.12
+
+      **Inheritance:**
+
+      This flag is inherited.
+
    .. XXX Document more flags here?
 
 
diff -pruN 3.12.0~a7-1/Doc/c-api/unicode.rst 3.12.0~b1-1/Doc/c-api/unicode.rst
--- 3.12.0~a7-1/Doc/c-api/unicode.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/c-api/unicode.rst	2023-05-22 12:07:36.000000000 +0000
@@ -394,98 +394,149 @@ APIs:
    arguments, calculate the size of the resulting Python Unicode string and return
    a string with the values formatted into it.  The variable arguments must be C
    types and must correspond exactly to the format characters in the *format*
-   ASCII-encoded string. The following format characters are allowed:
+   ASCII-encoded string.
 
-   .. % This should be exactly the same as the table in PyErr_Format.
+   A conversion specifier contains two or more characters and has the following
+   components, which must occur in this order:
 
-   .. tabularcolumns:: |l|l|L|
+   #. The ``'%'`` character, which marks the start of the specifier.
 
-   +-------------------+---------------------+----------------------------------+
-   | Format Characters | Type                | Comment                          |
-   +===================+=====================+==================================+
-   | :attr:`%%`        | *n/a*               | The literal % character.         |
-   +-------------------+---------------------+----------------------------------+
-   | :attr:`%c`        | int                 | A single character,              |
-   |                   |                     | represented as a C int.          |
-   +-------------------+---------------------+----------------------------------+
-   | :attr:`%d`        | int                 | Equivalent to                    |
-   |                   |                     | ``printf("%d")``. [1]_           |
-   +-------------------+---------------------+----------------------------------+
-   | :attr:`%u`        | unsigned int        | Equivalent to                    |
-   |                   |                     | ``printf("%u")``. [1]_           |
-   +-------------------+---------------------+----------------------------------+
-   | :attr:`%ld`       | long                | Equivalent to                    |
-   |                   |                     | ``printf("%ld")``. [1]_          |
-   +-------------------+---------------------+----------------------------------+
-   | :attr:`%li`       | long                | Equivalent to                    |
-   |                   |                     | ``printf("%li")``. [1]_          |
-   +-------------------+---------------------+----------------------------------+
-   | :attr:`%lu`       | unsigned long       | Equivalent to                    |
-   |                   |                     | ``printf("%lu")``. [1]_          |
-   +-------------------+---------------------+----------------------------------+
-   | :attr:`%lld`      | long long           | Equivalent to                    |
-   |                   |                     | ``printf("%lld")``. [1]_         |
-   +-------------------+---------------------+----------------------------------+
-   | :attr:`%lli`      | long long           | Equivalent to                    |
-   |                   |                     | ``printf("%lli")``. [1]_         |
-   +-------------------+---------------------+----------------------------------+
-   | :attr:`%llu`      | unsigned long long  | Equivalent to                    |
-   |                   |                     | ``printf("%llu")``. [1]_         |
-   +-------------------+---------------------+----------------------------------+
-   | :attr:`%zd`       | :c:type:`\          | Equivalent to                    |
-   |                   | Py_ssize_t`         | ``printf("%zd")``. [1]_          |
-   +-------------------+---------------------+----------------------------------+
-   | :attr:`%zi`       | :c:type:`\          | Equivalent to                    |
-   |                   | Py_ssize_t`         | ``printf("%zi")``. [1]_          |
-   +-------------------+---------------------+----------------------------------+
-   | :attr:`%zu`       | size_t              | Equivalent to                    |
-   |                   |                     | ``printf("%zu")``. [1]_          |
-   +-------------------+---------------------+----------------------------------+
-   | :attr:`%i`        | int                 | Equivalent to                    |
-   |                   |                     | ``printf("%i")``. [1]_           |
-   +-------------------+---------------------+----------------------------------+
-   | :attr:`%x`        | int                 | Equivalent to                    |
-   |                   |                     | ``printf("%x")``. [1]_           |
-   +-------------------+---------------------+----------------------------------+
-   | :attr:`%s`        | const char\*        | A null-terminated C character    |
-   |                   |                     | array.                           |
-   +-------------------+---------------------+----------------------------------+
-   | :attr:`%p`        | const void\*        | The hex representation of a C    |
-   |                   |                     | pointer. Mostly equivalent to    |
-   |                   |                     | ``printf("%p")`` except that     |
-   |                   |                     | it is guaranteed to start with   |
-   |                   |                     | the literal ``0x`` regardless    |
-   |                   |                     | of what the platform's           |
-   |                   |                     | ``printf`` yields.               |
-   +-------------------+---------------------+----------------------------------+
-   | :attr:`%A`        | PyObject\*          | The result of calling            |
-   |                   |                     | :func:`ascii`.                   |
-   +-------------------+---------------------+----------------------------------+
-   | :attr:`%U`        | PyObject\*          | A Unicode object.                |
-   +-------------------+---------------------+----------------------------------+
-   | :attr:`%V`        | PyObject\*,         | A Unicode object (which may be   |
-   |                   | const char\*        | ``NULL``) and a null-terminated  |
-   |                   |                     | C character array as a second    |
-   |                   |                     | parameter (which will be used,   |
-   |                   |                     | if the first parameter is        |
-   |                   |                     | ``NULL``).                       |
-   +-------------------+---------------------+----------------------------------+
-   | :attr:`%S`        | PyObject\*          | The result of calling            |
-   |                   |                     | :c:func:`PyObject_Str`.          |
-   +-------------------+---------------------+----------------------------------+
-   | :attr:`%R`        | PyObject\*          | The result of calling            |
-   |                   |                     | :c:func:`PyObject_Repr`.         |
-   +-------------------+---------------------+----------------------------------+
+   #. Conversion flags (optional), which affect the result of some conversion
+      types.
+
+   #. Minimum field width (optional).
+      If specified as an ``'*'`` (asterisk), the actual width is given in the
+      next argument, which must be of type :c:expr:`int`, and the object to
+      convert comes after the minimum field width and optional precision.
+
+   #. Precision (optional), given as a ``'.'`` (dot) followed by the precision.
+      If specified as ``'*'`` (an asterisk), the actual precision is given in
+      the next argument, which must be of type :c:expr:`int`, and the value to
+      convert comes after the precision.
+
+   #. Length modifier (optional).
+
+   #. Conversion type.
+
+   The conversion flag characters are:
+
+   .. tabularcolumns:: |l|L|
+
+   +-------+-------------------------------------------------------------+
+   | Flag  | Meaning                                                     |
+   +=======+=============================================================+
+   | ``0`` | The conversion will be zero padded for numeric values.      |
+   +-------+-------------------------------------------------------------+
+   | ``-`` | The converted value is left adjusted (overrides the ``0``   |
+   |       | flag if both are given).                                    |
+   +-------+-------------------------------------------------------------+
+
+   The length modifiers for following integer conversions (``d``, ``i``,
+   ``o``, ``u``, ``x``, or ``X``) specify the type of the argument
+   (:c:expr:`int` by default):
+
+   .. tabularcolumns:: |l|L|
+
+   +----------+-----------------------------------------------------+
+   | Modifier | Types                                               |
+   +==========+=====================================================+
+   | ``l``    | :c:expr:`long` or :c:expr:`unsigned long`           |
+   +----------+-----------------------------------------------------+
+   | ``ll``   | :c:expr:`long long` or :c:expr:`unsigned long long` |
+   +----------+-----------------------------------------------------+
+   | ``j``    | :c:expr:`intmax_t` or :c:expr:`uintmax_t`           |
+   +----------+-----------------------------------------------------+
+   | ``z``    | :c:expr:`size_t` or :c:expr:`ssize_t`               |
+   +----------+-----------------------------------------------------+
+   | ``t``    | :c:expr:`ptrdiff_t`                                 |
+   +----------+-----------------------------------------------------+
+
+   The length modifier ``l`` for following conversions ``s`` or ``V`` specify
+   that the type of the argument is :c:expr:`const wchar_t*`.
+
+   The conversion specifiers are:
+
+   .. list-table::
+      :widths: auto
+      :header-rows: 1
+
+      * - Conversion Specifier
+        - Type
+        - Comment
+
+      * - ``%``
+        - *n/a*
+        - The literal ``%`` character.
+
+      * - ``d``, ``i``
+        - Specified by the length modifier
+        - The decimal representation of a signed C integer.
+
+      * - ``u``
+        - Specified by the length modifier
+        - The decimal representation of an unsigned C integer.
+
+      * - ``o``
+        - Specified by the length modifier
+        - The octal representation of an unsigned C integer.
+
+      * - ``x``
+        - Specified by the length modifier
+        - The hexadecimal representation of an unsigned C integer (lowercase).
+
+      * - ``X``
+        - Specified by the length modifier
+        - The hexadecimal representation of an unsigned C integer (uppercase).
+
+      * - ``c``
+        - :c:expr:`int`
+        - A single character.
+
+      * - ``s``
+        - :c:expr:`const char*` or :c:expr:`const wchar_t*`
+        - A null-terminated C character array.
+
+      * - ``p``
+        - :c:expr:`const void*`
+        - The hex representation of a C  pointer.
+          Mostly equivalent to ``printf("%p")`` except that it is guaranteed to
+          start with the literal ``0x`` regardless of what the platform's
+          ``printf`` yields.
+
+      * - ``A``
+        - :c:expr:`PyObject*`
+        - The result of calling :func:`ascii`.
+
+      * - ``U``
+        - :c:expr:`PyObject*`
+        - A Unicode object.
+
+      * - ``V``
+        - :c:expr:`PyObject*`, :c:expr:`const char*` or :c:expr:`const wchar_t*`
+        - A Unicode object (which may be ``NULL``) and a null-terminated
+          C character array as a second parameter (which will be used,
+          if the first parameter is ``NULL``).
+
+      * - ``S``
+        - :c:expr:`PyObject*`
+        - The result of calling :c:func:`PyObject_Str`.
+
+      * - ``R``
+        - :c:expr:`PyObject*`
+        - The result of calling :c:func:`PyObject_Repr`.
 
    .. note::
       The width formatter unit is number of characters rather than bytes.
-      The precision formatter unit is number of bytes for ``"%s"`` and
+      The precision formatter unit is number of bytes or :c:expr:`wchar_t`
+      items (if the length modifier ``l`` is used) for ``"%s"`` and
       ``"%V"`` (if the ``PyObject*`` argument is ``NULL``), and a number of
       characters for ``"%A"``, ``"%U"``, ``"%S"``, ``"%R"`` and ``"%V"``
       (if the ``PyObject*`` argument is not ``NULL``).
 
-   .. [1] For integer specifiers (d, u, ld, li, lu, lld, lli, llu, zd, zi,
-      zu, i, x): the 0-conversion flag has effect even when a precision is given.
+   .. note::
+      Unlike to C :c:func:`printf` the ``0`` flag has effect even when
+      a precision is given for integer conversions (``d``, ``i``, ``u``, ``o``,
+      ``x``, or ``X``).
 
    .. versionchanged:: 3.2
       Support for ``"%lld"`` and ``"%llu"`` added.
@@ -498,6 +549,13 @@ APIs:
       ``"%V"``, ``"%S"``, ``"%R"`` added.
 
    .. versionchanged:: 3.12
+      Support for conversion specifiers ``o`` and ``X``.
+      Support for length modifiers ``j`` and ``t``.
+      Length modifiers are now applied to all integer conversions.
+      Length modifier ``l`` is now applied to conversion specifiers ``s`` and ``V``.
+      Support for variable width and precision ``*``.
+      Support for flag ``-``.
+
       An unrecognized format character now sets a :exc:`SystemError`.
       In previous versions it caused all the rest of the format string to be
       copied as-is to the result string, and any extra arguments discarded.
@@ -509,6 +567,15 @@ APIs:
    arguments.
 
 
+.. c:function:: PyObject* PyUnicode_FromObject(PyObject *obj)
+
+   Copy an instance of a Unicode subtype to a new true Unicode object if
+   necessary. If *obj* is already a true Unicode object (not a subtype),
+   return the reference with incremented refcount.
+
+   Objects other than Unicode or its subtypes will cause a :exc:`TypeError`.
+
+
 .. c:function:: PyObject* PyUnicode_FromEncodedObject(PyObject *obj, \
                                const char *encoding, const char *errors)
 
@@ -616,15 +683,6 @@ APIs:
    .. versionadded:: 3.3
 
 
-.. c:function:: PyObject* PyUnicode_FromObject(PyObject *obj)
-
-   Copy an instance of a Unicode subtype to a new true Unicode object if
-   necessary. If *obj* is already a true Unicode object (not a subtype),
-   return the reference with incremented refcount.
-
-   Objects other than Unicode or its subtypes will cause a :exc:`TypeError`.
-
-
 Locale Encoding
 """""""""""""""
 
diff -pruN 3.12.0~a7-1/Doc/c-api/utilities.rst 3.12.0~b1-1/Doc/c-api/utilities.rst
--- 3.12.0~a7-1/Doc/c-api/utilities.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/c-api/utilities.rst	2023-05-22 12:07:36.000000000 +0000
@@ -19,3 +19,4 @@ and parsing function arguments and const
    conversion.rst
    reflection.rst
    codec.rst
+   perfmaps.rst
diff -pruN 3.12.0~a7-1/Doc/conf.py 3.12.0~b1-1/Doc/conf.py
--- 3.12.0~a7-1/Doc/conf.py	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/conf.py	2023-05-22 12:07:36.000000000 +0000
@@ -68,12 +68,21 @@ highlight_language = 'python3'
 # Minimum version of sphinx required
 needs_sphinx = '3.2'
 
+# Ignore any .rst files in the includes/ directory;
+# they're embedded in pages but not rendered individually.
 # Ignore any .rst files in the venv/ directory.
-exclude_patterns = ['venv/*', 'README.rst']
+exclude_patterns = ['includes/*.rst', 'venv/*', 'README.rst']
 venvdir = os.getenv('VENVDIR')
 if venvdir is not None:
     exclude_patterns.append(venvdir + '/*')
 
+nitpick_ignore = [
+    # Do not error nit-picky mode builds when _SubParsersAction.add_parser cannot
+    # be resolved, as the method is currently undocumented. For context, see
+    # https://github.com/python/cpython/pull/103289.
+    ('py:meth', '_SubParsersAction.add_parser'),
+]
+
 # Disable Docutils smartquotes for several translations
 smartquotes_excludes = {
     'languages': ['ja', 'fr', 'zh_TW', 'zh_CN'], 'builders': ['man', 'text'],
@@ -82,6 +91,11 @@ smartquotes_excludes = {
 # Avoid a warning with Sphinx >= 2.0
 master_doc = 'contents'
 
+# Allow translation of index directives
+gettext_additional_targets = [
+    'index',
+]
+
 # Options for HTML output
 # -----------------------
 
@@ -105,12 +119,13 @@ if any('htmlhelp' in arg for arg in sys.
 # Short title used e.g. for <title> HTML tags.
 html_short_title = '%s Documentation' % release
 
-# Deployment preview information, from Netlify
-# (See netlify.toml and https://docs.netlify.com/configure-builds/environment-variables/#git-metadata)
+# Deployment preview information
+# (See .readthedocs.yml and https://docs.readthedocs.io/en/stable/reference/environment-variables.html)
+repository_url = os.getenv("READTHEDOCS_GIT_CLONE_URL")
 html_context = {
-    "is_deployment_preview": os.getenv("IS_DEPLOYMENT_PREVIEW"),
-    "repository_url": os.getenv("REPOSITORY_URL"),
-    "pr_id": os.getenv("REVIEW_ID")
+    "is_deployment_preview": os.getenv("READTHEDOCS_VERSION_TYPE") == "external",
+    "repository_url": repository_url.removesuffix(".git") if repository_url else None,
+    "pr_id": os.getenv("READTHEDOCS_VERSION")
 }
 
 # If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
@@ -252,8 +267,49 @@ coverage_ignore_c_items = {
 # Options for the link checker
 # ----------------------------
 
-# Ignore certain URLs.
-linkcheck_ignore = [r'https://bugs.python.org/(issue)?\d+']
+linkcheck_allowed_redirects = {
+    # bpo-NNNN -> BPO -> GH Issues
+    r'https://bugs.python.org/issue\?@action=redirect&bpo=\d+': r'https://github.com/python/cpython/issues/\d+',
+    # GH-NNNN used to refer to pull requests
+    r'https://github.com/python/cpython/issues/\d+': r'https://github.com/python/cpython/pull/\d+',
+    # :source:`something` linking files in the repository
+    r'https://github.com/python/cpython/tree/.*': 'https://github.com/python/cpython/blob/.*',
+    # Intentional HTTP use at Misc/NEWS.d/3.5.0a1.rst
+    r'http://www.python.org/$': 'https://www.python.org/$',
+    # Used in license page, keep as is
+    r'https://www.zope.org/': r'https://www.zope.dev/',
+    # Microsoft's redirects to learn.microsoft.com
+    r'https://msdn.microsoft.com/.*': 'https://learn.microsoft.com/.*',
+    r'https://docs.microsoft.com/.*': 'https://learn.microsoft.com/.*',
+    r'https://go.microsoft.com/fwlink/\?LinkID=\d+': 'https://learn.microsoft.com/.*',
+    # Language redirects
+    r'https://toml.io': 'https://toml.io/en/',
+    r'https://www.redhat.com': 'https://www.redhat.com/en',
+    # Other redirects
+    r'https://www.boost.org/libs/.+': r'https://www.boost.org/doc/libs/\d_\d+_\d/.+',
+    r'https://support.microsoft.com/en-us/help/\d+': 'https://support.microsoft.com/en-us/topic/.+',
+    r'https://perf.wiki.kernel.org$': 'https://perf.wiki.kernel.org/index.php/Main_Page',
+    r'https://www.sqlite.org': 'https://www.sqlite.org/index.html',
+    r'https://mitpress.mit.edu/sicp$': 'https://mitpress.mit.edu/9780262510875/structure-and-interpretation-of-computer-programs/',
+    r'https://www.python.org/psf/': 'https://www.python.org/psf-landing/',
+}
+
+linkcheck_anchors_ignore = [
+    # ignore anchors that start with a '/', e.g. Wikipedia media files:
+    # https://en.wikipedia.org/wiki/Walrus#/media/File:Pacific_Walrus_-_Bull_(8247646168).jpg
+    r'\/.*',
+]
+
+linkcheck_ignore = [
+    # The crawler gets "Anchor not found"
+    r'https://developer.apple.com/documentation/.+?#.*',
+    r'https://devguide.python.org.+?/#.*',
+    r'https://github.com.+?#.*',
+    # Robot crawlers not allowed: "403 Client Error: Forbidden"
+    r'https://support.enthought.com/hc/.*',
+    # SSLError CertificateError, even though it is valid
+    r'https://unix.org/version2/whatsnew/lp64_wp.html',
+]
 
 
 # Options for extensions
diff -pruN 3.12.0~a7-1/Doc/constraints.txt 3.12.0~b1-1/Doc/constraints.txt
--- 3.12.0~a7-1/Doc/constraints.txt	1970-01-01 00:00:00.000000000 +0000
+++ 3.12.0~b1-1/Doc/constraints.txt	2023-05-22 12:07:36.000000000 +0000
@@ -0,0 +1,29 @@
+# We have upper bounds on our transitive dependencies here
+# To avoid new releases unexpectedly breaking our build.
+# This file can be updated on an ad-hoc basis,
+# though it will probably have to be updated
+# whenever Doc/requirements.txt is updated.
+
+# Direct dependencies of Sphinx
+babel<3
+colorama<0.5
+imagesize<1.5
+Jinja2<3.2
+packaging<24
+# Pygments==2.15.0 breaks CI
+Pygments<2.16,!=2.15.0
+requests<3
+snowballstemmer<3
+sphinxcontrib-applehelp<1.1
+sphinxcontrib-devhelp<1.1
+sphinxcontrib-htmlhelp<2.1
+sphinxcontrib-jsmath<1.1
+sphinxcontrib-qthelp<1.1
+sphinxcontrib-serializinghtml<1.2
+
+# Direct dependencies of Jinja2 (Jinja is a dependency of Sphinx, see above)
+MarkupSafe<2.2
+
+# Direct dependencies of sphinx-lint
+polib<1.3
+regex<2024
diff -pruN 3.12.0~a7-1/Doc/data/stable_abi.dat 3.12.0~b1-1/Doc/data/stable_abi.dat
--- 3.12.0~a7-1/Doc/data/stable_abi.dat	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/data/stable_abi.dat	2023-05-22 12:07:36.000000000 +0000
@@ -521,6 +521,7 @@ function,PyObject_GetAttrString,3.2,,
 function,PyObject_GetBuffer,3.11,,
 function,PyObject_GetItem,3.2,,
 function,PyObject_GetIter,3.2,,
+function,PyObject_GetTypeData,3.12,,
 function,PyObject_HasAttr,3.2,,
 function,PyObject_HasAttrString,3.2,,
 function,PyObject_Hash,3.2,,
@@ -675,6 +676,7 @@ function,PyType_GetModuleState,3.10,,
 function,PyType_GetName,3.11,,
 function,PyType_GetQualName,3.11,,
 function,PyType_GetSlot,3.4,,
+function,PyType_GetTypeDataSize,3.12,,
 function,PyType_IsSubtype,3.2,,
 function,PyType_Modified,3.2,,
 function,PyType_Ready,3.2,,
diff -pruN 3.12.0~a7-1/Doc/distributing/index.rst 3.12.0~b1-1/Doc/distributing/index.rst
--- 3.12.0~a7-1/Doc/distributing/index.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/distributing/index.rst	2023-05-22 12:07:36.000000000 +0000
@@ -129,14 +129,10 @@ involved in creating and publishing a pr
 * `Uploading the project to the Python Package Index`_
 * `The .pypirc file`_
 
-.. _Project structure: \
-    https://packaging.python.org/tutorials/packaging-projects/#packaging-python-projects
-.. _Building and packaging the project: \
-   https://packaging.python.org/tutorials/packaging-projects/#creating-the-package-files
-.. _Uploading the project to the Python Package Index: \
-   https://packaging.python.org/tutorials/packaging-projects/#uploading-the-distribution-archives
-.. _The .pypirc file: \
-   https://packaging.python.org/specifications/pypirc/
+.. _Project structure: https://packaging.python.org/tutorials/packaging-projects/#packaging-python-projects
+.. _Building and packaging the project: https://packaging.python.org/tutorials/packaging-projects/#creating-the-package-files
+.. _Uploading the project to the Python Package Index: https://packaging.python.org/tutorials/packaging-projects/#uploading-the-distribution-archives
+.. _The .pypirc file: https://packaging.python.org/specifications/pypirc/
 
 
 How do I...?
diff -pruN 3.12.0~a7-1/Doc/extending/newtypes.rst 3.12.0~b1-1/Doc/extending/newtypes.rst
--- 3.12.0~a7-1/Doc/extending/newtypes.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/extending/newtypes.rst	2023-05-22 12:07:36.000000000 +0000
@@ -149,7 +149,7 @@ done.  This can be done using the :c:fun
 
 .. index::
    single: string; object representation
-   builtin: repr
+   pair: built-in function; repr
 
 Object Presentation
 -------------------
@@ -337,7 +337,7 @@ Here is an example::
        }
 
        PyErr_Format(PyExc_AttributeError,
-                    "'%.50s' object has no attribute '%.400s'",
+                    "'%.100s' object has no attribute '%.400s'",
                     tp->tp_name, name);
        return NULL;
    }
diff -pruN 3.12.0~a7-1/Doc/extending/newtypes_tutorial.rst 3.12.0~b1-1/Doc/extending/newtypes_tutorial.rst
--- 3.12.0~a7-1/Doc/extending/newtypes_tutorial.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/extending/newtypes_tutorial.rst	2023-05-22 12:07:36.000000000 +0000
@@ -88,7 +88,7 @@ standard Python floats::
 The second bit is the definition of the type object. ::
 
    static PyTypeObject CustomType = {
-       PyVarObject_HEAD_INIT(NULL, 0)
+       .ob_base = PyVarObject_HEAD_INIT(NULL, 0)
        .tp_name = "custom.Custom",
        .tp_doc = PyDoc_STR("Custom objects"),
        .tp_basicsize = sizeof(CustomObject),
@@ -109,7 +109,7 @@ common practice to not specify them expl
 
 We're going to pick it apart, one field at a time::
 
-   PyVarObject_HEAD_INIT(NULL, 0)
+   .ob_base = PyVarObject_HEAD_INIT(NULL, 0)
 
 This line is mandatory boilerplate to initialize the ``ob_base``
 field mentioned above. ::
diff -pruN 3.12.0~a7-1/Doc/faq/extending.rst 3.12.0~b1-1/Doc/faq/extending.rst
--- 3.12.0~a7-1/Doc/faq/extending.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/faq/extending.rst	2023-05-22 12:07:36.000000000 +0000
@@ -42,7 +42,7 @@ on what you're trying to do.
 .. XXX make sure these all work
 
 `Cython <https://cython.org>`_ and its relative `Pyrex
-<https://www.cosc.canterbury.ac.nz/greg.ewing/python/Pyrex/>`_ are compilers
+<https://www.csse.canterbury.ac.nz/greg.ewing/python/Pyrex/>`_ are compilers
 that accept a slightly modified form of Python and generate the corresponding
 C code.  Cython and Pyrex make it possible to write an extension without having
 to learn Python's C API.
diff -pruN 3.12.0~a7-1/Doc/faq/general.rst 3.12.0~b1-1/Doc/faq/general.rst
--- 3.12.0~a7-1/Doc/faq/general.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/faq/general.rst	2023-05-22 12:07:36.000000000 +0000
@@ -54,8 +54,8 @@ commercial use, to sell copies of Python
 unmodified), or to sell products that incorporate Python in some form.  We would
 still like to know about all commercial use of Python, of course.
 
-See `the PSF license page <https://www.python.org/psf/license/>`_ to find further
-explanations and a link to the full text of the license.
+See `the license page <https://docs.python.org/3/license.html>`_ to find further
+explanations and the full text of the PSF License.
 
 The Python logo is trademarked, and in certain cases permission is required to
 use it.  Consult `the Trademark Usage Policy
@@ -215,7 +215,7 @@ every day, and Usenet readers are often
 Announcements of new software releases and events can be found in
 comp.lang.python.announce, a low-traffic moderated list that receives about five
 postings per day.  It's available as `the python-announce mailing list
-<https://mail.python.org/mailman/listinfo/python-announce-list>`_.
+<https://mail.python.org/mailman3/lists/python-announce-list.python.org/>`_.
 
 More info about other mailing lists and newsgroups
 can be found at https://www.python.org/community/lists/.
@@ -352,7 +352,7 @@ titled "Python X.Y Release Schedule", wh
 publicly released yet.
 
 New development is discussed on `the python-dev mailing list
-<https://mail.python.org/mailman/listinfo/python-dev/>`_.
+<https://mail.python.org/mailman3/lists/python-dev.python.org/>`_.
 
 
 Is it reasonable to propose incompatible changes to Python?
diff -pruN 3.12.0~a7-1/Doc/faq/library.rst 3.12.0~b1-1/Doc/faq/library.rst
--- 3.12.0~a7-1/Doc/faq/library.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/faq/library.rst	2023-05-22 12:07:36.000000000 +0000
@@ -780,7 +780,7 @@ socket to :meth:`select.select` to check
    The :mod:`asyncio` module provides a general purpose single-threaded and
    concurrent asynchronous library, which can be used for writing non-blocking
    network code.
-   The third-party `Twisted <https://twistedmatrix.com/trac/>`_ library is
+   The third-party `Twisted <https://twisted.org/>`_ library is
    a popular and feature-rich alternative.
 
 
diff -pruN 3.12.0~a7-1/Doc/faq/programming.rst 3.12.0~b1-1/Doc/faq/programming.rst
--- 3.12.0~a7-1/Doc/faq/programming.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/faq/programming.rst	2023-05-22 12:07:36.000000000 +0000
@@ -61,7 +61,7 @@ Yes.
 `Pyflakes <https://github.com/PyCQA/pyflakes>`_ do basic checking that will
 help you catch bugs sooner.
 
-Static type checkers such as `Mypy <http://mypy-lang.org/>`_,
+Static type checkers such as `Mypy <https://mypy-lang.org/>`_,
 `Pyre <https://pyre-check.org/>`_, and
 `Pytype <https://github.com/google/pytype>`_ can check type hints in Python
 source code.
diff -pruN 3.12.0~a7-1/Doc/glossary.rst 3.12.0~b1-1/Doc/glossary.rst
--- 3.12.0~a7-1/Doc/glossary.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/glossary.rst	2023-05-22 12:07:36.000000000 +0000
@@ -214,7 +214,7 @@ Glossary
       A callable is an object that can be called, possibly with a set
       of arguments (see :term:`argument`), with the following syntax::
 
-         callable(argument1, argument2, ...)
+         callable(argument1, argument2, argumentN)
 
       A :term:`function`, and by extension a :term:`method`, is a callable.
       An instance of a class that implements the :meth:`~object.__call__`
diff -pruN 3.12.0~a7-1/Doc/howto/argparse.rst 3.12.0~b1-1/Doc/howto/argparse.rst
--- 3.12.0~a7-1/Doc/howto/argparse.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/howto/argparse.rst	2023-05-22 12:07:36.000000000 +0000
@@ -1,10 +1,12 @@
+.. _argparse-tutorial:
+
 *****************
 Argparse Tutorial
 *****************
 
 :author: Tshepang Mbambo
 
-.. _argparse-tutorial:
+.. currentmodule:: argparse
 
 This tutorial is intended to be a gentle introduction to :mod:`argparse`, the
 recommended command-line parsing module in the Python standard library.
@@ -12,7 +14,7 @@ recommended command-line parsing module
 .. note::
 
    There are two other modules that fulfill the same task, namely
-   :mod:`getopt` (an equivalent for :c:func:`getopt` from the C
+   :mod:`getopt` (an equivalent for ``getopt()`` from the C
    language) and the deprecated :mod:`optparse`.
    Note also that :mod:`argparse` is based on :mod:`optparse`,
    and therefore very similar in terms of usage.
@@ -137,13 +139,13 @@ And running the code:
 
 Here is what's happening:
 
-* We've added the :meth:`add_argument` method, which is what we use to specify
+* We've added the :meth:`~ArgumentParser.add_argument` method, which is what we use to specify
   which command-line options the program is willing to accept. In this case,
   I've named it ``echo`` so that it's in line with its function.
 
 * Calling our program now requires us to specify an option.
 
-* The :meth:`parse_args` method actually returns some data from the
+* The :meth:`~ArgumentParser.parse_args` method actually returns some data from the
   options specified, in this case, ``echo``.
 
 * The variable is some form of 'magic' that :mod:`argparse` performs for free
@@ -256,7 +258,7 @@ Here is what is happening:
 
 * To show that the option is actually optional, there is no error when running
   the program without it. Note that by default, if an optional argument isn't
-  used, the relevant variable, in this case :attr:`args.verbosity`, is
+  used, the relevant variable, in this case ``args.verbosity``, is
   given ``None`` as a value, which is the reason it fails the truth
   test of the :keyword:`if` statement.
 
@@ -299,7 +301,7 @@ Here is what is happening:
   We even changed the name of the option to match that idea.
   Note that we now specify a new keyword, ``action``, and give it the value
   ``"store_true"``. This means that, if the option is specified,
-  assign the value ``True`` to :data:`args.verbose`.
+  assign the value ``True`` to ``args.verbose``.
   Not specifying it implies ``False``.
 
 * It complains when you specify a value, in true spirit of what flags
@@ -698,7 +700,7 @@ Conflicting options
 
 So far, we have been working with two methods of an
 :class:`argparse.ArgumentParser` instance. Let's introduce a third one,
-:meth:`add_mutually_exclusive_group`. It allows for us to specify options that
+:meth:`~ArgumentParser.add_mutually_exclusive_group`. It allows for us to specify options that
 conflict with each other. Let's also change the rest of the program so that
 the new functionality makes more sense:
 we'll introduce the ``--quiet`` option,
diff -pruN 3.12.0~a7-1/Doc/howto/clinic.rst 3.12.0~b1-1/Doc/howto/clinic.rst
--- 3.12.0~a7-1/Doc/howto/clinic.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/howto/clinic.rst	2023-05-22 12:07:36.000000000 +0000
@@ -775,6 +775,9 @@ All Argument Clinic converters accept th
     because :pep:`8` mandates that the Python library may not use
     annotations.
 
+  ``unused``
+    Wrap the argument with :c:macro:`Py_UNUSED` in the impl function signature.
+
 In addition, some converters accept additional arguments.  Here is a list
 of these arguments, along with their meanings:
 
@@ -1033,19 +1036,36 @@ you're not permitted to use:
 Using a return converter
 ------------------------
 
-By default the impl function Argument Clinic generates for you returns ``PyObject *``.
-But your C function often computes some C type, then converts it into the ``PyObject *``
+By default, the impl function Argument Clinic generates for you returns
+:c:type:`PyObject * <PyObject>`.
+But your C function often computes some C type,
+then converts it into the :c:type:`!PyObject *`
 at the last moment.  Argument Clinic handles converting your inputs from Python types
 into native C types—why not have it convert your return value from a native C type
 into a Python type too?
 
 That's what a "return converter" does.  It changes your impl function to return
 some C type, then adds code to the generated (non-impl) function to handle converting
-that value into the appropriate ``PyObject *``.
+that value into the appropriate :c:type:`!PyObject *`.
 
 The syntax for return converters is similar to that of parameter converters.
 You specify the return converter like it was a return annotation on the
-function itself.  Return converters behave much the same as parameter converters;
+function itself, using ``->`` notation.
+
+For example:
+
+.. code-block:: c
+
+   /*[clinic input]
+   add -> int
+
+       a: int
+       b: int
+       /
+
+   [clinic start generated code]*/
+
+Return converters behave much the same as parameter converters;
 they take arguments, the arguments are all keyword-only, and if you're not changing
 any of the default arguments you can omit the parentheses.
 
@@ -1066,19 +1086,17 @@ Currently Argument Clinic supports only
 .. code-block:: none
 
     bool
+    double
+    float
     int
-    unsigned int
     long
-    unsigned int
-    size_t
     Py_ssize_t
-    float
-    double
-    DecodeFSDefault
+    size_t
+    unsigned int
+    unsigned long
 
-None of these take parameters.  For the first three, return -1 to indicate
-error.  For ``DecodeFSDefault``, the return type is ``const char *``; return a ``NULL``
-pointer to indicate an error.
+None of these take parameters.
+For all of these, return ``-1`` to indicate error.
 
 To see all the return converters Argument Clinic supports, along with
 their parameters (if any),
diff -pruN 3.12.0~a7-1/Doc/howto/curses.rst 3.12.0~b1-1/Doc/howto/curses.rst
--- 3.12.0~a7-1/Doc/howto/curses.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/howto/curses.rst	2023-05-22 12:07:36.000000000 +0000
@@ -4,6 +4,8 @@
   Curses Programming with Python
 **********************************
 
+.. currentmodule:: curses
+
 :Author: A.M. Kuchling, Eric S. Raymond
 :Release: 2.04
 
@@ -65,7 +67,7 @@ The Python module is a fairly simple wra
 curses; if you're already familiar with curses programming in C, it's really
 easy to transfer that knowledge to Python.  The biggest difference is that the
 Python interface makes things simpler by merging different C functions such as
-:c:func:`addstr`, :c:func:`mvaddstr`, and :c:func:`mvwaddstr` into a single
+:c:func:`!addstr`, :c:func:`!mvaddstr`, and :c:func:`!mvwaddstr` into a single
 :meth:`~curses.window.addstr` method.  You'll see this covered in more
 detail later.
 
@@ -82,7 +84,7 @@ Before doing anything, curses must be in
 calling the :func:`~curses.initscr` function, which will determine the
 terminal type, send any required setup codes to the terminal, and
 create various internal data structures.  If successful,
-:func:`initscr` returns a window object representing the entire
+:func:`!initscr` returns a window object representing the entire
 screen; this is usually called ``stdscr`` after the name of the
 corresponding C variable. ::
 
@@ -151,8 +153,8 @@ importing the :func:`curses.wrapper` fun
 
 The :func:`~curses.wrapper` function takes a callable object and does the
 initializations described above, also initializing colors if color
-support is present.  :func:`wrapper` then runs your provided callable.
-Once the callable returns, :func:`wrapper` will restore the original
+support is present.  :func:`!wrapper` then runs your provided callable.
+Once the callable returns, :func:`!wrapper` will restore the original
 state of the terminal.  The callable is called inside a
 :keyword:`try`...\ :keyword:`except` that catches exceptions, restores
 the state of the terminal, and then re-raises the exception.  Therefore
@@ -200,7 +202,7 @@ This is because curses was originally wr
 terminal connections in mind; with these terminals, minimizing the
 time required to redraw the screen was very important.  Instead curses
 accumulates changes to the screen and displays them in the most
-efficient manner when you call :meth:`refresh`.  For example, if your
+efficient manner when you call :meth:`!refresh`.  For example, if your
 program displays some text in a window and then clears the window,
 there's no need to send the original text because they're never
 visible.
@@ -210,7 +212,7 @@ really complicate programming with curse
 of activity, and then pause waiting for a keypress or some other action on the
 part of the user.  All you have to do is to be sure that the screen has been
 redrawn before pausing to wait for user input, by first calling
-``stdscr.refresh()`` or the :meth:`refresh` method of some other relevant
+:meth:`!stdscr.refresh` or the :meth:`!refresh` method of some other relevant
 window.
 
 A pad is a special case of a window; it can be larger than the actual display
@@ -234,7 +236,7 @@ displayed.  ::
    #          : filled with pad content.
    pad.refresh( 0,0, 5,5, 20,75)
 
-The :meth:`refresh` call displays a section of the pad in the rectangle
+The :meth:`!refresh` call displays a section of the pad in the rectangle
 extending from coordinate (5,5) to coordinate (20,75) on the screen; the upper
 left corner of the displayed section is coordinate (0,0) on the pad.  Beyond
 that difference, pads are exactly like ordinary windows and support the same
@@ -242,7 +244,7 @@ methods.
 
 If you have multiple windows and pads on screen there is a more
 efficient way to update the screen and prevent annoying screen flicker
-as each part of the screen gets updated.  :meth:`refresh` actually
+as each part of the screen gets updated.  :meth:`!refresh` actually
 does two things:
 
 1) Calls the :meth:`~curses.window.noutrefresh` method of each window
@@ -251,8 +253,8 @@ does two things:
 2) Calls the function :func:`~curses.doupdate` function to change the
    physical screen to match the desired state recorded in the data structure.
 
-Instead you can call :meth:`noutrefresh` on a number of windows to
-update the data structure, and then call :func:`doupdate` to update
+Instead you can call :meth:`!noutrefresh` on a number of windows to
+update the data structure, and then call :func:`!doupdate` to update
 the screen.
 
 
@@ -261,11 +263,11 @@ Displaying Text
 
 From a C programmer's point of view, curses may sometimes look like a
 twisty maze of functions, all subtly different.  For example,
-:c:func:`addstr` displays a string at the current cursor location in
-the ``stdscr`` window, while :c:func:`mvaddstr` moves to a given y,x
-coordinate first before displaying the string. :c:func:`waddstr` is just
-like :c:func:`addstr`, but allows specifying a window to use instead of
-using ``stdscr`` by default. :c:func:`mvwaddstr` allows specifying both
+:c:func:`!addstr` displays a string at the current cursor location in
+the ``stdscr`` window, while :c:func:`!mvaddstr` moves to a given y,x
+coordinate first before displaying the string. :c:func:`!waddstr` is just
+like :c:func:`!addstr`, but allows specifying a window to use instead of
+using ``stdscr`` by default. :c:func:`!mvwaddstr` allows specifying both
 a window and a coordinate.
 
 Fortunately the Python interface hides all these details.  ``stdscr``
@@ -298,7 +300,7 @@ the next subsection.
 The :meth:`~curses.window.addstr` method takes a Python string or
 bytestring as the value to be displayed.  The contents of bytestrings
 are sent to the terminal as-is.  Strings are encoded to bytes using
-the value of the window's :attr:`encoding` attribute; this defaults to
+the value of the window's :attr:`~window.encoding` attribute; this defaults to
 the default system encoding as returned by :func:`locale.getencoding`.
 
 The :meth:`~curses.window.addch` methods take a character, which can be
@@ -444,15 +446,15 @@ There are two methods for getting input
 
 It's possible to not wait for the user using the
 :meth:`~curses.window.nodelay` window method. After ``nodelay(True)``,
-:meth:`getch` and :meth:`getkey` for the window become
-non-blocking. To signal that no input is ready, :meth:`getch` returns
-``curses.ERR`` (a value of -1) and :meth:`getkey` raises an exception.
+:meth:`!getch` and :meth:`!getkey` for the window become
+non-blocking. To signal that no input is ready, :meth:`!getch` returns
+``curses.ERR`` (a value of -1) and :meth:`!getkey` raises an exception.
 There's also a :func:`~curses.halfdelay` function, which can be used to (in
-effect) set a timer on each :meth:`getch`; if no input becomes
+effect) set a timer on each :meth:`!getch`; if no input becomes
 available within a specified delay (measured in tenths of a second),
 curses raises an exception.
 
-The :meth:`getch` method returns an integer; if it's between 0 and 255, it
+The :meth:`!getch` method returns an integer; if it's between 0 and 255, it
 represents the ASCII code of the key pressed.  Values greater than 255 are
 special keys such as Page Up, Home, or the cursor keys. You can compare the
 value returned to constants such as :const:`curses.KEY_PPAGE`,
diff -pruN 3.12.0~a7-1/Doc/howto/descriptor.rst 3.12.0~b1-1/Doc/howto/descriptor.rst
--- 3.12.0~a7-1/Doc/howto/descriptor.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/howto/descriptor.rst	2023-05-22 12:07:36.000000000 +0000
@@ -1273,11 +1273,14 @@ Using the non-data descriptor protocol,
 
 .. testcode::
 
+    import functools
+
     class StaticMethod:
         "Emulate PyStaticMethod_Type() in Objects/funcobject.c"
 
         def __init__(self, f):
             self.f = f
+            functools.update_wrapper(self, f)
 
         def __get__(self, obj, objtype=None):
             return self.f
@@ -1285,13 +1288,19 @@ Using the non-data descriptor protocol,
         def __call__(self, *args, **kwds):
             return self.f(*args, **kwds)
 
+The :func:`functools.update_wrapper` call adds a ``__wrapped__`` attribute
+that refers to the underlying function.  Also it carries forward
+the attributes necessary to make the wrapper look like the wrapped
+function: ``__name__``, ``__qualname__``, ``__doc__``, and ``__annotations__``.
+
 .. testcode::
     :hide:
 
     class E_sim:
         @StaticMethod
-        def f(x):
-            return x * 10
+        def f(x: int) -> str:
+            "Simple function example"
+            return "!" * x
 
     wrapped_ord = StaticMethod(ord)
 
@@ -1299,11 +1308,51 @@ Using the non-data descriptor protocol,
     :hide:
 
     >>> E_sim.f(3)
-    30
+    '!!!'
     >>> E_sim().f(3)
-    30
+    '!!!'
+
+    >>> sm = vars(E_sim)['f']
+    >>> type(sm).__name__
+    'StaticMethod'
+    >>> f = E_sim.f
+    >>> type(f).__name__
+    'function'
+    >>> sm.__name__
+    'f'
+    >>> f.__name__
+    'f'
+    >>> sm.__qualname__
+    'E_sim.f'
+    >>> f.__qualname__
+    'E_sim.f'
+    >>> sm.__doc__
+    'Simple function example'
+    >>> f.__doc__
+    'Simple function example'
+    >>> sm.__annotations__
+    {'x': <class 'int'>, 'return': <class 'str'>}
+    >>> f.__annotations__
+    {'x': <class 'int'>, 'return': <class 'str'>}
+    >>> sm.__module__ == f.__module__
+    True
+    >>> sm(3)
+    '!!!'
+    >>> f(3)
+    '!!!'
+
     >>> wrapped_ord('A')
     65
+    >>> wrapped_ord.__module__ == ord.__module__
+    True
+    >>> wrapped_ord.__wrapped__ == ord
+    True
+    >>> wrapped_ord.__name__ == ord.__name__
+    True
+    >>> wrapped_ord.__qualname__ == ord.__qualname__
+    True
+    >>> wrapped_ord.__doc__ == ord.__doc__
+    True
 
 
 Class methods
@@ -1359,11 +1408,14 @@ Using the non-data descriptor protocol,
 
 .. testcode::
 
+    import functools
+
     class ClassMethod:
         "Emulate PyClassMethod_Type() in Objects/funcobject.c"
 
         def __init__(self, f):
             self.f = f
+            functools.update_wrapper(self, f)
 
         def __get__(self, obj, cls=None):
             if cls is None:
@@ -1380,8 +1432,9 @@ Using the non-data descriptor protocol,
     # Verify the emulation works
     class T:
         @ClassMethod
-        def cm(cls, x, y):
-            return (cls, x, y)
+        def cm(cls, x: int, y: str) -> tuple[str, int, str]:
+            "Class method that returns a tuple"
+            return (cls.__name__, x, y)
 
         @ClassMethod
         @property
@@ -1393,17 +1446,40 @@ Using the non-data descriptor protocol,
     :hide:
 
     >>> T.cm(11, 22)
-    (<class 'T'>, 11, 22)
+    ('T', 11, 22)
 
     # Also call it from an instance
     >>> t = T()
     >>> t.cm(11, 22)
-    (<class 'T'>, 11, 22)
+    ('T', 11, 22)
 
     # Check the alternate path for chained descriptors
     >>> T.__doc__
     "A doc for 'T'"
 
+    # Verify that T uses our emulation
+    >>> type(vars(T)['cm']).__name__
+    'ClassMethod'
+
+    # Verify that update_wrapper() correctly copied attributes
+    >>> T.cm.__name__
+    'cm'
+    >>> T.cm.__qualname__
+    'T.cm'
+    >>> T.cm.__doc__
+    'Class method that returns a tuple'
+    >>> T.cm.__annotations__
+    {'x': <class 'int'>, 'y': <class 'str'>, 'return': tuple[str, int, str]}
+
+    # Verify that __wrapped__ was added and works correctly
+    >>> f = vars(T)['cm'].__wrapped__
+    >>> type(f).__name__
+    'function'
+    >>> f.__name__
+    'cm'
+    >>> f(T, 11, 22)
+    ('T', 11, 22)
+
 
 The code path for ``hasattr(type(self.f), '__get__')`` was added in
 Python 3.9 and makes it possible for :func:`classmethod` to support
@@ -1423,6 +1499,12 @@ chained together.  In Python 3.11, this
     >>> G.__doc__
     "A doc for 'G'"
 
+The :func:`functools.update_wrapper` call in ``ClassMethod`` adds a
+``__wrapped__`` attribute that refers to the underlying function.  Also
+it carries forward the attributes necessary to make the wrapper look
+like the wrapped function: ``__name__``, ``__qualname__``, ``__doc__``,
+and ``__annotations__``.
+
 
 Member objects and __slots__
 ----------------------------
diff -pruN 3.12.0~a7-1/Doc/howto/enum.rst 3.12.0~b1-1/Doc/howto/enum.rst
--- 3.12.0~a7-1/Doc/howto/enum.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/howto/enum.rst	2023-05-22 12:07:36.000000000 +0000
@@ -36,8 +36,10 @@ inherits from :class:`Enum` itself.
 
 .. note:: Case of Enum Members
 
-    Because Enums are used to represent constants we recommend using
-    UPPER_CASE names for members, and will be using that style in our examples.
+    Because Enums are used to represent constants, and to help avoid issues
+    with name clashes between mixin-class methods/attributes and enum names,
+    we strongly recommend using UPPER_CASE names for members, and will be using
+    that style in our examples.
 
 Depending on the nature of the enum a member's value may or may not be
 important, but either way that value can be used to get the corresponding
@@ -490,6 +492,10 @@ the :meth:`~Enum.__repr__` omits the inh
 Use the :func:`!dataclass` argument ``repr=False``
 to use the standard :func:`repr`.
 
+.. versionchanged:: 3.12
+   Only the dataclass fields are shown in the value area, not the dataclass'
+   name.
+
 
 Pickling
 --------
@@ -865,17 +871,19 @@ Some rules:
 4. When another data type is mixed in, the :attr:`value` attribute is *not the
    same* as the enum member itself, although it is equivalent and will compare
    equal.
-5. %-style formatting:  ``%s`` and ``%r`` call the :class:`Enum` class's
+5. A ``data type`` is a mixin that defines :meth:`__new__`, or a
+   :class:`~dataclasses.dataclass`
+6. %-style formatting:  ``%s`` and ``%r`` call the :class:`Enum` class's
    :meth:`__str__` and :meth:`__repr__` respectively; other codes (such as
    ``%i`` or ``%h`` for IntEnum) treat the enum member as its mixed-in type.
-6. :ref:`Formatted string literals <f-strings>`, :meth:`str.format`,
+7. :ref:`Formatted string literals <f-strings>`, :meth:`str.format`,
    and :func:`format` will use the enum's :meth:`__str__` method.
 
 .. note::
 
    Because :class:`IntEnum`, :class:`IntFlag`, and :class:`StrEnum` are
    designed to be drop-in replacements for existing constants, their
-   :meth:`__str__` method has been reset to their data types
+   :meth:`__str__` method has been reset to their data types'
    :meth:`__str__` method.
 
 When to use :meth:`__new__` vs. :meth:`__init__`
@@ -988,12 +996,13 @@ but remain normal attributes.
 """"""""""""""""""""
 
 Enum members are instances of their enum class, and are normally accessed as
-``EnumClass.member``.  In Python versions starting with ``3.5`` you could access
-members from other members -- this practice is discouraged, is deprecated
-in ``3.12``, and will be removed in ``3.14``.
+``EnumClass.member``.  In certain situations, such as writing custom enum
+behavior, being able to access one member directly from another is useful,
+and is supported; however, in order to avoid name clashes between member names
+and attributes/methods from mixed-in classes, upper-case names are strongly
+recommended.
 
 .. versionchanged:: 3.5
-.. versionchanged:: 3.12
 
 
 Creating members that are mixed with other data types
diff -pruN 3.12.0~a7-1/Doc/howto/functional.rst 3.12.0~b1-1/Doc/howto/functional.rst
--- 3.12.0~a7-1/Doc/howto/functional.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/howto/functional.rst	2023-05-22 12:07:36.000000000 +0000
@@ -1208,8 +1208,8 @@ General
 -------
 
 **Structure and Interpretation of Computer Programs**, by Harold Abelson and
-Gerald Jay Sussman with Julie Sussman.  Full text at
-https://mitpress.mit.edu/sicp/.  In this classic textbook of computer science,
+Gerald Jay Sussman with Julie Sussman.  The book can be found at
+https://mitpress.mit.edu/sicp.  In this classic textbook of computer science,
 chapters 2 and 3 discuss the use of sequences and streams to organize the data
 flow inside a program.  The book uses Scheme for its examples, but many of the
 design approaches described in these chapters are applicable to functional-style
diff -pruN 3.12.0~a7-1/Doc/howto/isolating-extensions.rst 3.12.0~b1-1/Doc/howto/isolating-extensions.rst
--- 3.12.0~a7-1/Doc/howto/isolating-extensions.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/howto/isolating-extensions.rst	2023-05-22 12:07:36.000000000 +0000
@@ -372,7 +372,7 @@ To save a some tedious error-handling bo
 these two steps with :c:func:`PyType_GetModuleState`, resulting in::
 
    my_struct *state = (my_struct*)PyType_GetModuleState(type);
-   if (state === NULL) {
+   if (state == NULL) {
        return NULL;
    }
 
@@ -435,7 +435,7 @@ For example::
            PyObject *kwnames)
    {
        my_struct *state = (my_struct*)PyType_GetModuleState(defining_class);
-       if (state === NULL) {
+       if (state == NULL) {
            return NULL;
        }
        ... // rest of logic
@@ -479,7 +479,7 @@ to get the state::
 
     PyObject *module = PyType_GetModuleByDef(Py_TYPE(self), &module_def);
     my_struct *state = (my_struct*)PyModule_GetState(module);
-    if (state === NULL) {
+    if (state == NULL) {
         return NULL;
     }
 
diff -pruN 3.12.0~a7-1/Doc/howto/logging.rst 3.12.0~b1-1/Doc/howto/logging.rst
--- 3.12.0~a7-1/Doc/howto/logging.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/howto/logging.rst	2023-05-22 12:07:36.000000000 +0000
@@ -418,6 +418,7 @@ The flow of log event information in log
 following diagram.
 
 .. image:: logging_flow.png
+   :class: invert-in-dark-mode
 
 Loggers
 ^^^^^^^
diff -pruN 3.12.0~a7-1/Doc/howto/perf_profiling.rst 3.12.0~b1-1/Doc/howto/perf_profiling.rst
--- 3.12.0~a7-1/Doc/howto/perf_profiling.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/howto/perf_profiling.rst	2023-05-22 12:07:36.000000000 +0000
@@ -15,21 +15,21 @@ information about the performance of you
 that aid with the analysis of the data that it produces.
 
 The main problem with using the ``perf`` profiler with Python applications is that
-``perf`` only allows to get information about native symbols, this is, the names of
-the functions and procedures written in C. This means that the names and file names
-of the Python functions in your code will not appear in the output of the ``perf``.
+``perf`` only gets information about native symbols, that is, the names of
+functions and procedures written in C. This means that the names and file names
+of Python functions in your code will not appear in the output of ``perf``.
 
 Since Python 3.12, the interpreter can run in a special mode that allows Python
 functions to appear in the output of the ``perf`` profiler. When this mode is
 enabled, the interpreter will interpose a small piece of code compiled on the
 fly before the execution of every Python function and it will teach ``perf`` the
 relationship between this piece of code and the associated Python function using
-`perf map files`_.
+:doc:`perf map files <../c-api/perfmaps>`.
 
 .. note::
 
-    Support for the ``perf`` profiler is only currently available for Linux on
-    selected architectures. Check the output of the configure build step or
+    Support for the ``perf`` profiler is currently only available for Linux on
+    select architectures. Check the output of the ``configure`` build step or
     check the output of ``python -m sysconfig | grep HAVE_PERF_TRAMPOLINE``
     to see if your system is supported.
 
@@ -52,11 +52,11 @@ For example, consider the following scri
     if __name__ == "__main__":
         baz(1000000)
 
-We can run ``perf`` to sample CPU stack traces at 9999 Hertz::
+We can run ``perf`` to sample CPU stack traces at 9999 hertz::
 
     $ perf record -F 9999 -g -o perf.data python my_script.py
 
-Then we can use ``perf`` report to analyze the data:
+Then we can use ``perf report`` to analyze the data:
 
 .. code-block:: shell-session
 
@@ -97,7 +97,7 @@ Then we can use ``perf`` report to analy
                             |          |          |                     |          |          |--2.97%--_PyObject_Malloc
     ...
 
-As you can see here, the Python functions are not shown in the output, only ``_Py_Eval_EvalFrameDefault`` appears
+As you can see, the Python functions are not shown in the output, only ``_Py_Eval_EvalFrameDefault``
 (the function that evaluates the Python bytecode) shows up. Unfortunately that's not very useful because all Python
 functions use the same C function to evaluate bytecode so we cannot know which Python function corresponds to which
 bytecode-evaluating function.
@@ -151,7 +151,7 @@ Instead, if we run the same experiment w
 How to enable ``perf`` profiling support
 ----------------------------------------
 
-``perf`` profiling support can either be enabled from the start using
+``perf`` profiling support can be enabled either from the start using
 the environment variable :envvar:`PYTHONPERFSUPPORT` or the
 :option:`-X perf <-X>` option,
 or dynamically using :func:`sys.activate_stack_trampoline` and
@@ -192,7 +192,7 @@ Example, using the :mod:`sys` APIs in fi
 How to obtain the best results
 ------------------------------
 
-For the best results, Python should be compiled with
+For best results, Python should be compiled with
 ``CFLAGS="-fno-omit-frame-pointer -mno-omit-leaf-frame-pointer"`` as this allows
 profilers to unwind using only the frame pointer and not on DWARF debug
 information. This is because as the code that is interposed to allow ``perf``
@@ -206,5 +206,3 @@ You can check if your system has been co
 If you don't see any output it means that your interpreter has not been compiled with
 frame pointers and therefore it may not be able to show Python functions in the output
 of ``perf``.
-
-.. _perf map files: https://github.com/torvalds/linux/blob/0513e464f9007b70b96740271a948ca5ab6e7dd7/tools/perf/Documentation/jit-interface.txt
diff -pruN 3.12.0~a7-1/Doc/howto/pyporting.rst 3.12.0~b1-1/Doc/howto/pyporting.rst
--- 3.12.0~a7-1/Doc/howto/pyporting.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/howto/pyporting.rst	2023-05-22 12:07:36.000000000 +0000
@@ -438,7 +438,7 @@ to make sure everything functions as exp
 .. _Futurize: https://python-future.org/automatic_conversion.html
 .. _importlib2: https://pypi.org/project/importlib2
 .. _Modernize: https://python-modernize.readthedocs.io/
-.. _mypy: http://mypy-lang.org/
+.. _mypy: https://mypy-lang.org/
 .. _Porting to Python 3: http://python3porting.com/
 .. _Pylint: https://pypi.org/project/pylint
 
diff -pruN 3.12.0~a7-1/Doc/howto/urllib2.rst 3.12.0~b1-1/Doc/howto/urllib2.rst
--- 3.12.0~a7-1/Doc/howto/urllib2.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/howto/urllib2.rst	2023-05-22 12:07:36.000000000 +0000
@@ -86,7 +86,7 @@ response::
 
     import urllib.request
 
-    req = urllib.request.Request('http://www.voidspace.org.uk')
+    req = urllib.request.Request('http://python.org/')
     with urllib.request.urlopen(req) as response:
        the_page = response.read()
 
@@ -458,7 +458,7 @@ To illustrate creating and installing a
 ``HTTPBasicAuthHandler``. For a more detailed discussion of this subject --
 including an explanation of how Basic Authentication works - see the `Basic
 Authentication Tutorial
-<http://www.voidspace.org.uk/python/articles/authentication.shtml>`_.
+<https://web.archive.org/web/20201215133350/http://www.voidspace.org.uk/python/articles/authentication.shtml>`__.
 
 When authentication is required, the server sends a header (as well as the 401
 error code) requesting authentication.  This specifies the authentication scheme
diff -pruN 3.12.0~a7-1/Doc/includes/custom.c 3.12.0~b1-1/Doc/includes/custom.c
--- 3.12.0~a7-1/Doc/includes/custom.c	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/includes/custom.c	2023-05-22 12:07:36.000000000 +0000
@@ -7,7 +7,7 @@ typedef struct {
 } CustomObject;
 
 static PyTypeObject CustomType = {
-    PyVarObject_HEAD_INIT(NULL, 0)
+    .ob_base = PyVarObject_HEAD_INIT(NULL, 0)
     .tp_name = "custom.Custom",
     .tp_doc = PyDoc_STR("Custom objects"),
     .tp_basicsize = sizeof(CustomObject),
@@ -17,7 +17,7 @@ static PyTypeObject CustomType = {
 };
 
 static PyModuleDef custommodule = {
-    PyModuleDef_HEAD_INIT,
+    .m_base = PyModuleDef_HEAD_INIT,
     .m_name = "custom",
     .m_doc = "Example module that creates an extension type.",
     .m_size = -1,
diff -pruN 3.12.0~a7-1/Doc/includes/custom2.c 3.12.0~b1-1/Doc/includes/custom2.c
--- 3.12.0~a7-1/Doc/includes/custom2.c	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/includes/custom2.c	2023-05-22 12:07:36.000000000 +0000
@@ -90,7 +90,7 @@ static PyMethodDef Custom_methods[] = {
 };
 
 static PyTypeObject CustomType = {
-    PyVarObject_HEAD_INIT(NULL, 0)
+    .ob_base = PyVarObject_HEAD_INIT(NULL, 0)
     .tp_name = "custom2.Custom",
     .tp_doc = PyDoc_STR("Custom objects"),
     .tp_basicsize = sizeof(CustomObject),
@@ -104,7 +104,7 @@ static PyTypeObject CustomType = {
 };
 
 static PyModuleDef custommodule = {
-    PyModuleDef_HEAD_INIT,
+    .m_base =PyModuleDef_HEAD_INIT,
     .m_name = "custom2",
     .m_doc = "Example module that creates an extension type.",
     .m_size = -1,
diff -pruN 3.12.0~a7-1/Doc/includes/custom3.c 3.12.0~b1-1/Doc/includes/custom3.c
--- 3.12.0~a7-1/Doc/includes/custom3.c	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/includes/custom3.c	2023-05-22 12:07:36.000000000 +0000
@@ -130,7 +130,7 @@ static PyMethodDef Custom_methods[] = {
 };
 
 static PyTypeObject CustomType = {
-    PyVarObject_HEAD_INIT(NULL, 0)
+    .ob_base = PyVarObject_HEAD_INIT(NULL, 0)
     .tp_name = "custom3.Custom",
     .tp_doc = PyDoc_STR("Custom objects"),
     .tp_basicsize = sizeof(CustomObject),
@@ -145,7 +145,7 @@ static PyTypeObject CustomType = {
 };
 
 static PyModuleDef custommodule = {
-    PyModuleDef_HEAD_INIT,
+    .m_base = PyModuleDef_HEAD_INIT,
     .m_name = "custom3",
     .m_doc = "Example module that creates an extension type.",
     .m_size = -1,
diff -pruN 3.12.0~a7-1/Doc/includes/custom4.c 3.12.0~b1-1/Doc/includes/custom4.c
--- 3.12.0~a7-1/Doc/includes/custom4.c	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/includes/custom4.c	2023-05-22 12:07:36.000000000 +0000
@@ -146,7 +146,7 @@ static PyMethodDef Custom_methods[] = {
 };
 
 static PyTypeObject CustomType = {
-    PyVarObject_HEAD_INIT(NULL, 0)
+    .ob_base = PyVarObject_HEAD_INIT(NULL, 0)
     .tp_name = "custom4.Custom",
     .tp_doc = PyDoc_STR("Custom objects"),
     .tp_basicsize = sizeof(CustomObject),
@@ -163,7 +163,7 @@ static PyTypeObject CustomType = {
 };
 
 static PyModuleDef custommodule = {
-    PyModuleDef_HEAD_INIT,
+    .m_base = PyModuleDef_HEAD_INIT,
     .m_name = "custom4",
     .m_doc = "Example module that creates an extension type.",
     .m_size = -1,
diff -pruN 3.12.0~a7-1/Doc/library/__main__.rst 3.12.0~b1-1/Doc/library/__main__.rst
--- 3.12.0~a7-1/Doc/library/__main__.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/__main__.rst	2023-05-22 12:07:36.000000000 +0000
@@ -124,7 +124,7 @@ This is where using the ``if __name__ ==
 handy. Code within this block won't run unless the module is executed in the
 top-level environment.
 
-Putting as few statements as possible in the block below ``if __name___ ==
+Putting as few statements as possible in the block below ``if __name__ ==
 '__main__'`` can improve code clarity and correctness. Most often, a function
 named ``main`` encapsulates the program's primary behavior::
 
diff -pruN 3.12.0~a7-1/Doc/library/_thread.rst 3.12.0~b1-1/Doc/library/_thread.rst
--- 3.12.0~a7-1/Doc/library/_thread.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/_thread.rst	2023-05-22 12:07:36.000000000 +0000
@@ -208,7 +208,7 @@ In addition to these methods, lock objec
 
 **Caveats:**
 
-  .. index:: module: signal
+  .. index:: pair: module; signal
 
 * Threads interact strangely with interrupts: the :exc:`KeyboardInterrupt`
   exception will be received by an arbitrary thread.  (When the :mod:`signal`
diff -pruN 3.12.0~a7-1/Doc/library/argparse.rst 3.12.0~b1-1/Doc/library/argparse.rst
--- 3.12.0~a7-1/Doc/library/argparse.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/argparse.rst	2023-05-22 12:07:36.000000000 +0000
@@ -57,20 +57,20 @@ the extracted data in a :class:`argparse
 Quick Links for add_argument()
 ------------------------------
 
-====================== =========================================================== ==========================================================================================================================
-Name                   Description                                                 Values
-====================== =========================================================== ==========================================================================================================================
-action_                Specify how an argument should be handled                   ``'store'``, ``'store_const'``, ``'store_true'``, ``'append'``, ``'append_const'``, ``'count'``, ``'help'``, ``'version'``
-choices_               Limit values to a specific set of choices                   ``['foo', 'bar']``, ``range(1, 10)``, or :class:`~collections.abc.Container` instance
-const_                 Store a constant value
-default_               Default value used when an argument is not provided         Defaults to ``None``
-dest_                  Specify the attribute name used in the result namespace
-help_                  Help message for an argument
-metavar_               Alternate display name for the argument as shown in help
-nargs_                 Number of times the argument can be used                    :class:`int`, ``'?'``, ``'*'``, ``'+'``, or ``argparse.REMAINDER``
-required_              Indicate whether an argument is required or optional        ``True`` or ``False``
-type_                  Automatically convert an argument to the given type         :class:`int`, :class:`float`, ``argparse.FileType('w')``, or callable function
-====================== =========================================================== ==========================================================================================================================
+============================ =========================================================== ==========================================================================================================================
+Name                         Description                                                 Values
+============================ =========================================================== ==========================================================================================================================
+action_                      Specify how an argument should be handled                   ``'store'``, ``'store_const'``, ``'store_true'``, ``'append'``, ``'append_const'``, ``'count'``, ``'help'``, ``'version'``
+choices_                     Limit values to a specific set of choices                   ``['foo', 'bar']``, ``range(1, 10)``, or :class:`~collections.abc.Container` instance
+const_                       Store a constant value
+default_                     Default value used when an argument is not provided         Defaults to ``None``
+dest_                        Specify the attribute name used in the result namespace
+help_                        Help message for an argument
+metavar_                     Alternate display name for the argument as shown in help
+nargs_                       Number of times the argument can be used                    :class:`int`, ``'?'``, ``'*'``, or ``'+'``
+required_                    Indicate whether an argument is required or optional        ``True`` or ``False``
+:ref:`type <argparse-type>`  Automatically convert an argument to the given type         :class:`int`, :class:`float`, ``argparse.FileType('w')``, or callable function
+============================ =========================================================== ==========================================================================================================================
 
 
 Example
@@ -585,7 +585,7 @@ arguments will never be treated as file
 
 .. versionchanged:: 3.12
    :class:`ArgumentParser` changed encoding and errors to read arguments files
-   from default (e.g. :func:`locale.getpreferredencoding(False)` and
+   from default (e.g. :func:`locale.getpreferredencoding(False) <locale.getpreferredencoding>` and
    ``"strict"``) to :term:`filesystem encoding and error handler`.
    Arguments file should be encoded in UTF-8 instead of ANSI Codepage on Windows.
 
@@ -1132,7 +1132,7 @@ command-line argument was not present::
    Namespace(foo='1')
 
 
-.. _type:
+.. _argparse-type:
 
 type
 ^^^^
@@ -1191,7 +1191,7 @@ done downstream after the arguments are
 For example, JSON or YAML conversions have complex error cases that require
 better reporting than can be given by the ``type`` keyword.  A
 :exc:`~json.JSONDecodeError` would not be well formatted and a
-:exc:`FileNotFound` exception would not be handled at all.
+:exc:`FileNotFoundError` exception would not be handled at all.
 
 Even :class:`~argparse.FileType` has its limitations for use with the ``type``
 keyword.  If one argument uses *FileType* and then a subsequent argument fails,
@@ -1445,7 +1445,7 @@ Action classes
 Action classes implement the Action API, a callable which returns a callable
 which processes arguments from the command-line. Any object which follows
 this API may be passed as the ``action`` parameter to
-:meth:`add_argument`.
+:meth:`~ArgumentParser.add_argument`.
 
 .. class:: Action(option_strings, dest, nargs=None, const=None, default=None, \
                   type=None, choices=None, required=False, help=None, \
@@ -1723,7 +1723,7 @@ Sub-commands
    :class:`ArgumentParser` supports the creation of such sub-commands with the
    :meth:`add_subparsers` method.  The :meth:`add_subparsers` method is normally
    called with no arguments and returns a special action object.  This object
-   has a single method, :meth:`~ArgumentParser.add_parser`, which takes a
+   has a single method, :meth:`~_SubParsersAction.add_parser`, which takes a
    command name and any :class:`ArgumentParser` constructor arguments, and
    returns an :class:`ArgumentParser` object that can be modified as usual.
 
@@ -1789,7 +1789,7 @@ Sub-commands
    for that particular parser will be printed.  The help message will not
    include parent parser or sibling parser messages.  (A help message for each
    subparser command, however, can be given by supplying the ``help=`` argument
-   to :meth:`add_parser` as above.)
+   to :meth:`~_SubParsersAction.add_parser` as above.)
 
    ::
 
@@ -2157,7 +2157,7 @@ the populated namespace and the list of
 
 .. warning::
    :ref:`Prefix matching <prefix-matching>` rules apply to
-   :meth:`parse_known_args`. The parser may consume an option even if it's just
+   :meth:`~ArgumentParser.parse_known_args`. The parser may consume an option even if it's just
    a prefix of one of its known options, instead of leaving it in the remaining
    arguments list.
 
@@ -2218,7 +2218,7 @@ support this parsing style.
 
 These parsers do not support all the argparse features, and will raise
 exceptions if unsupported features are used.  In particular, subparsers,
-``argparse.REMAINDER``, and mutually exclusive groups that include both
+and mutually exclusive groups that include both
 optionals and positionals are not supported.
 
 The following example shows the difference between
@@ -2295,3 +2295,17 @@ A partial upgrade path from :mod:`optpar
 
 * Replace the OptionParser constructor ``version`` argument with a call to
   ``parser.add_argument('--version', action='version', version='<the version>')``.
+
+Exceptions
+----------
+
+.. exception:: ArgumentError
+
+   An error from creating or using an argument (optional or positional).
+
+   The string value of this exception is the message, augmented with
+   information about the argument that caused it.
+
+.. exception:: ArgumentTypeError
+
+   Raised when something goes wrong converting a command line string to a type.
diff -pruN 3.12.0~a7-1/Doc/library/ast.rst 3.12.0~b1-1/Doc/library/ast.rst
--- 3.12.0~a7-1/Doc/library/ast.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/ast.rst	2023-05-22 12:07:36.000000000 +0000
@@ -1724,6 +1724,7 @@ Function and class definitions
             body=[
                 FunctionDef(
                     name='f',
+                    type_params=[],
                     args=arguments(
                         posonlyargs=[],
                         args=[
@@ -1847,6 +1848,7 @@ Function and class definitions
             body=[
                 ClassDef(
                     name='Foo',
+                    type_params=[],
                     bases=[
                         Name(id='base1', ctx=Load()),
                         Name(id='base2', ctx=Load())],
@@ -1885,6 +1887,7 @@ Async and await
         body=[
             AsyncFunctionDef(
                 name='f',
+                type_params=[],
                 args=arguments(
                     posonlyargs=[],
                     args=[],
diff -pruN 3.12.0~a7-1/Doc/library/asyncio-eventloop.rst 3.12.0~b1-1/Doc/library/asyncio-eventloop.rst
--- 3.12.0~a7-1/Doc/library/asyncio-eventloop.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/asyncio-eventloop.rst	2023-05-22 12:07:36.000000000 +0000
@@ -529,7 +529,7 @@ Opening network connections
       specifies requirements for algorithms that reduce this user-visible
       delay and provides an algorithm.
 
-      For more information: https://tools.ietf.org/html/rfc6555
+      For more information: https://datatracker.ietf.org/doc/html/rfc6555
 
    .. versionchanged:: 3.11
 
@@ -1438,9 +1438,7 @@ async/await code consider using the high
 
    * *stdin* can be any of these:
 
-     * a file-like object representing a pipe to be connected to the
-       subprocess's standard input stream using
-       :meth:`~loop.connect_write_pipe`
+     * a file-like object
      * the :const:`subprocess.PIPE` constant (default) which will create a new
        pipe and connect it,
      * the value ``None`` which will make the subprocess inherit the file
@@ -1450,9 +1448,7 @@ async/await code consider using the high
 
    * *stdout* can be any of these:
 
-     * a file-like object representing a pipe to be connected to the
-       subprocess's standard output stream using
-       :meth:`~loop.connect_write_pipe`
+     * a file-like object
      * the :const:`subprocess.PIPE` constant (default) which will create a new
        pipe and connect it,
      * the value ``None`` which will make the subprocess inherit the file
@@ -1462,9 +1458,7 @@ async/await code consider using the high
 
    * *stderr* can be any of these:
 
-     * a file-like object representing a pipe to be connected to the
-       subprocess's standard error stream using
-       :meth:`~loop.connect_write_pipe`
+     * a file-like object
      * the :const:`subprocess.PIPE` constant (default) which will create a new
        pipe and connect it,
      * the value ``None`` which will make the subprocess inherit the file
@@ -1483,6 +1477,11 @@ async/await code consider using the high
      as text. :func:`bytes.decode` can be used to convert the bytes returned
      from the stream to text.
 
+   If a file-like object passed as *stdin*, *stdout* or *stderr* represents a
+   pipe, then the other side of this pipe should be registered with
+   :meth:`~loop.connect_write_pipe` or :meth:`~loop.connect_read_pipe` for use
+   with the event loop.
+
    See the constructor of the :class:`subprocess.Popen` class
    for documentation on other arguments.
 
@@ -1571,7 +1570,7 @@ Server objects are created by :meth:`loo
 :meth:`loop.create_unix_server`, :func:`start_server`,
 and :func:`start_unix_server` functions.
 
-Do not instantiate the class directly.
+Do not instantiate the :class:`Server` class directly.
 
 .. class:: Server
 
@@ -1662,7 +1661,8 @@ Do not instantiate the class directly.
 
    .. attribute:: sockets
 
-      List of :class:`socket.socket` objects the server is listening on.
+      List of socket-like objects, ``asyncio.trsock.TransportSocket``, which
+      the server is listening on.
 
       .. versionchanged:: 3.7
          Prior to Python 3.7 ``Server.sockets`` used to return an
diff -pruN 3.12.0~a7-1/Doc/library/asyncio-subprocess.rst 3.12.0~b1-1/Doc/library/asyncio-subprocess.rst
--- 3.12.0~a7-1/Doc/library/asyncio-subprocess.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/asyncio-subprocess.rst	2023-05-22 12:07:36.000000000 +0000
@@ -207,8 +207,9 @@ their completion.
       Interact with process:
 
       1. send data to *stdin* (if *input* is not ``None``);
-      2. read data from *stdout* and *stderr*, until EOF is reached;
-      3. wait for process to terminate.
+      2. closes *stdin*;
+      3. read data from *stdout* and *stderr*, until EOF is reached;
+      4. wait for process to terminate.
 
       The optional *input* argument is the data (:class:`bytes` object)
       that will be sent to the child process.
@@ -229,6 +230,10 @@ their completion.
       Note, that the data read is buffered in memory, so do not use
       this method if the data size is large or unlimited.
 
+      .. versionchanged:: 3.12
+
+         *stdin* gets closed when `input=None` too.
+
    .. method:: send_signal(signal)
 
       Sends the signal *signal* to the child process.
diff -pruN 3.12.0~a7-1/Doc/library/asyncio-task.rst 3.12.0~b1-1/Doc/library/asyncio-task.rst
--- 3.12.0~a7-1/Doc/library/asyncio-task.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/asyncio-task.rst	2023-05-22 12:07:36.000000000 +0000
@@ -256,8 +256,9 @@ Creating Tasks
 
    .. note::
 
-      :meth:`asyncio.TaskGroup.create_task` is a newer alternative
-      that allows for convenient waiting for a group of related tasks.
+      :meth:`asyncio.TaskGroup.create_task` is a new alternative
+      leveraging structural concurrency; it allows for waiting
+      for a group of related tasks with strong safety guarantees.
 
    .. important::
 
@@ -340,7 +341,7 @@ Example::
         async with asyncio.TaskGroup() as tg:
             task1 = tg.create_task(some_coro(...))
             task2 = tg.create_task(another_coro(...))
-        print("Both tasks have completed now.")
+        print(f"Both tasks have completed now: {task1.result()}, {task2.result()}")
 
 The ``async with`` statement will wait for all tasks in the group to finish.
 While waiting, new tasks may still be added to the group
@@ -459,8 +460,12 @@ Running Tasks Concurrently
    Tasks/Futures to be cancelled.
 
    .. note::
-      A more modern way to create and run tasks concurrently and
-      wait for their completion is :class:`asyncio.TaskGroup`.
+      A new alternative to create and run tasks concurrently and
+      wait for their completion is :class:`asyncio.TaskGroup`. *TaskGroup*
+      provides stronger safety guarantees than *gather* for scheduling a nesting of subtasks:
+      if a task (or a subtask, a task scheduled by a task)
+      raises an exception, *TaskGroup* will, while *gather* will not,
+      cancel the remaining scheduled tasks).
 
    .. _asyncio_example_gather:
 
@@ -522,6 +527,51 @@ Running Tasks Concurrently
       and there is no running event loop.
 
 
+.. _eager-task-factory:
+
+Eager Task Factory
+==================
+
+.. function:: eager_task_factory(loop, coro, *, name=None, context=None)
+
+    A task factory for eager task execution.
+
+    When using this factory (via :meth:`loop.set_task_factory(asyncio.eager_task_factory) <loop.set_task_factory>`),
+    coroutines begin execution synchronously during :class:`Task` construction.
+    Tasks are only scheduled on the event loop if they block.
+    This can be a performance improvement as the overhead of loop scheduling
+    is avoided for coroutines that complete synchronously.
+
+    A common example where this is beneficial is coroutines which employ
+    caching or memoization to avoid actual I/O when possible.
+
+    .. note::
+
+        Immediate execution of the coroutine is a semantic change.
+        If the coroutine returns or raises, the task is never scheduled
+        to the event loop. If the coroutine execution blocks, the task is
+        scheduled to the event loop. This change may introduce behavior
+        changes to existing applications. For example,
+        the application's task execution order is likely to change.
+
+    .. versionadded:: 3.12
+
+.. function:: create_eager_task_factory(custom_task_constructor)
+
+    Create an eager task factory, similar to :func:`eager_task_factory`,
+    using the provided *custom_task_constructor* when creating a new task instead
+    of the default :class:`Task`.
+
+    *custom_task_constructor* must be a *callable* with the signature matching
+    the signature of :class:`Task.__init__ <Task>`.
+    The callable must return a :class:`asyncio.Task`-compatible object.
+
+    This function returns a *callable* intended to be used as a task factory of an
+    event loop via :meth:`loop.set_task_factory(factory) <loop.set_task_factory>`).
+
+    .. versionadded:: 3.12
+
+
 Shielding From Cancellation
 ===========================
 
@@ -829,6 +879,9 @@ Waiting Primitives
       Deprecation warning is emitted if not all awaitable objects in the *aws*
       iterable are Future-like objects and there is no running event loop.
 
+   .. versionchanged:: 3.12
+      Added support for generators yielding tasks.
+
 
 Running in Threads
 ==================
@@ -970,7 +1023,7 @@ Introspection
 Task Object
 ===========
 
-.. class:: Task(coro, *, loop=None, name=None)
+.. class:: Task(coro, *, loop=None, name=None, context=None, eager_start=False)
 
    A :class:`Future-like <Future>` object that runs a Python
    :ref:`coroutine <coroutine>`.  Not thread-safe.
@@ -1005,9 +1058,17 @@ Task Object
    APIs except :meth:`Future.set_result` and
    :meth:`Future.set_exception`.
 
-   Tasks support the :mod:`contextvars` module.  When a Task
-   is created it copies the current context and later runs its
-   coroutine in the copied context.
+   An optional keyword-only *context* argument allows specifying a
+   custom :class:`contextvars.Context` for the *coro* to run in.
+   If no *context* is provided, the Task copies the current context
+   and later runs its coroutine in the copied context.
+
+   An optional keyword-only *eager_start* argument allows eagerly starting
+   the execution of the :class:`asyncio.Task` at task creation time.
+   If set to ``True`` and the event loop is running, the task will start
+   executing the coroutine immediately, until the first time the coroutine
+   blocks. If the coroutine returns or raises without blocking, the task
+   will be finished eagerly and will skip scheduling to the event loop.
 
    .. versionchanged:: 3.7
       Added support for the :mod:`contextvars` module.
@@ -1019,6 +1080,12 @@ Task Object
       Deprecation warning is emitted if *loop* is not specified
       and there is no running event loop.
 
+   .. versionchanged:: 3.11
+      Added the *context* parameter.
+
+   .. versionchanged:: 3.12
+      Added the *eager_start* parameter.
+
    .. method:: done()
 
       Return ``True`` if the Task is *done*.
@@ -1109,8 +1176,17 @@ Task Object
 
       Return the coroutine object wrapped by the :class:`Task`.
 
+      .. note::
+
+         This will return ``None`` for Tasks which have already
+         completed eagerly. See the :ref:`Eager Task Factory <eager-task-factory>`.
+
       .. versionadded:: 3.8
 
+      .. versionchanged:: 3.12
+
+         Newly added eager task execution means result may be ``None``.
+
    .. method:: get_context()
 
       Return the :class:`contextvars.Context` object
diff -pruN 3.12.0~a7-1/Doc/library/atexit.rst 3.12.0~b1-1/Doc/library/atexit.rst
--- 3.12.0~a7-1/Doc/library/atexit.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/atexit.rst	2023-05-22 12:07:36.000000000 +0000
@@ -20,6 +20,9 @@ at interpreter termination time they wil
 program is killed by a signal not handled by Python, when a Python fatal
 internal error is detected, or when :func:`os._exit` is called.
 
+**Note:** The effect of registering or unregistering functions from within
+a cleanup function is undefined.
+
 .. versionchanged:: 3.7
     When used with C-API subinterpreters, registered functions
     are local to the interpreter they were registered in.
diff -pruN 3.12.0~a7-1/Doc/library/binascii.rst 3.12.0~b1-1/Doc/library/binascii.rst
--- 3.12.0~a7-1/Doc/library/binascii.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/binascii.rst	2023-05-22 12:07:36.000000000 +0000
@@ -6,8 +6,8 @@
               representations.
 
 .. index::
-   module: uu
-   module: base64
+   pair: module; uu
+   pair: module; base64
 
 --------------
 
diff -pruN 3.12.0~a7-1/Doc/library/bisect.rst 3.12.0~b1-1/Doc/library/bisect.rst
--- 3.12.0~a7-1/Doc/library/bisect.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/bisect.rst	2023-05-22 12:07:36.000000000 +0000
@@ -24,6 +24,8 @@ method to determine whether a value has
 functions only call the :meth:`__lt__` method and will return an insertion
 point between values in an array.
 
+.. _bisect functions:
+
 The following functions are provided:
 
 
@@ -55,7 +57,7 @@ The following functions are provided:
 .. function:: bisect_right(a, x, lo=0, hi=len(a), *, key=None)
               bisect(a, x, lo=0, hi=len(a), *, key=None)
 
-   Similar to :func:`bisect_left`, but returns an insertion point which comes
+   Similar to :py:func:`~bisect.bisect_left`, but returns an insertion point which comes
    after (to the right of) any existing entries of *x* in *a*.
 
    The returned insertion point *ip* partitions the array *a* into two slices
@@ -70,7 +72,7 @@ The following functions are provided:
 
    Insert *x* in *a* in sorted order.
 
-   This function first runs :func:`bisect_left` to locate an insertion point.
+   This function first runs :py:func:`~bisect.bisect_left` to locate an insertion point.
    Next, it runs the :meth:`insert` method on *a* to insert *x* at the
    appropriate position to maintain sort order.
 
@@ -87,10 +89,10 @@ The following functions are provided:
 .. function:: insort_right(a, x, lo=0, hi=len(a), *, key=None)
               insort(a, x, lo=0, hi=len(a), *, key=None)
 
-   Similar to :func:`insort_left`, but inserting *x* in *a* after any existing
+   Similar to :py:func:`~bisect.insort_left`, but inserting *x* in *a* after any existing
    entries of *x*.
 
-   This function first runs :func:`bisect_right` to locate an insertion point.
+   This function first runs :py:func:`~bisect.bisect_right` to locate an insertion point.
    Next, it runs the :meth:`insert` method on *a* to insert *x* at the
    appropriate position to maintain sort order.
 
@@ -120,7 +122,7 @@ thoughts in mind:
   they are used.  Consequently, if the search functions are used in a loop,
   the key function may be called again and again on the same array elements.
   If the key function isn't fast, consider wrapping it with
-  :func:`functools.cache` to avoid duplicate computations.  Alternatively,
+  :py:func:`functools.cache` to avoid duplicate computations.  Alternatively,
   consider searching an array of precomputed keys to locate the insertion
   point (as shown in the examples section below).
 
@@ -140,7 +142,7 @@ thoughts in mind:
 Searching Sorted Lists
 ----------------------
 
-The above :func:`bisect` functions are useful for finding insertion points but
+The above `bisect functions`_ are useful for finding insertion points but
 can be tricky or awkward to use for common searching tasks. The following five
 functions show how to transform them into the standard lookups for sorted
 lists::
@@ -186,8 +188,8 @@ Examples
 
 .. _bisect-example:
 
-The :func:`bisect` function can be useful for numeric table lookups. This
-example uses :func:`bisect` to look up a letter grade for an exam score (say)
+The :py:func:`~bisect.bisect` function can be useful for numeric table lookups. This
+example uses :py:func:`~bisect.bisect` to look up a letter grade for an exam score (say)
 based on a set of ordered numeric breakpoints: 90 and up is an 'A', 80 to 89 is
 a 'B', and so on::
 
@@ -198,8 +200,8 @@ a 'B', and so on::
    >>> [grade(score) for score in [33, 99, 77, 70, 89, 90, 100]]
    ['F', 'A', 'C', 'C', 'B', 'A', 'A']
 
-The :func:`bisect` and :func:`insort` functions also work with lists of
-tuples.  The *key* argument can serve to extract the field used for ordering
+The :py:func:`~bisect.bisect` and :py:func:`~bisect.insort` functions also work with
+lists of tuples.  The *key* argument can serve to extract the field used for ordering
 records in a table::
 
     >>> from collections import namedtuple
@@ -210,10 +212,10 @@ records in a table::
     >>> Movie = namedtuple('Movie', ('name', 'released', 'director'))
 
     >>> movies = [
-    ...     Movie('Jaws', 1975, 'Speilberg'),
+    ...     Movie('Jaws', 1975, 'Spielberg'),
     ...     Movie('Titanic', 1997, 'Cameron'),
     ...     Movie('The Birds', 1963, 'Hitchcock'),
-    ...     Movie('Aliens', 1986, 'Scott')
+    ...     Movie('Aliens', 1986, 'Cameron')
     ... ]
 
     >>> # Find the first movie released after 1960
@@ -228,8 +230,8 @@ records in a table::
     >>> pprint(movies)
     [Movie(name='The Birds', released=1963, director='Hitchcock'),
      Movie(name='Love Story', released=1970, director='Hiller'),
-     Movie(name='Jaws', released=1975, director='Speilberg'),
-     Movie(name='Aliens', released=1986, director='Scott'),
+     Movie(name='Jaws', released=1975, director='Spielberg'),
+     Movie(name='Aliens', released=1986, director='Cameron'),
      Movie(name='Titanic', released=1997, director='Cameron')]
 
 If the key function is expensive, it is possible to avoid repeated function
diff -pruN 3.12.0~a7-1/Doc/library/calendar.rst 3.12.0~b1-1/Doc/library/calendar.rst
--- 3.12.0~a7-1/Doc/library/calendar.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/calendar.rst	2023-05-22 12:07:36.000000000 +0000
@@ -28,6 +28,58 @@ interpreted as prescribed by the ISO 860
 2 BC, and so on.
 
 
+.. class:: Day
+
+   Enumeration defining the days of the week as integer constants, from 0 to 6.
+
+   .. attribute:: MONDAY
+
+   .. attribute:: TUESDAY
+
+   .. attribute:: WEDNESDAY
+
+   .. attribute:: THURSDAY
+
+   .. attribute:: FRIDAY
+
+   .. attribute:: SATURDAY
+
+   .. attribute:: SUNDAY
+
+   .. versionadded:: 3.12
+
+
+.. class:: Month
+
+   Enumeration defining months of the year as integer constants, from 1 to 12.
+
+   .. attribute:: JANUARY
+
+   .. attribute:: FEBRUARY
+
+   .. attribute:: MARCH
+
+   .. attribute:: APRIL
+
+   .. attribute:: MAY
+
+   .. attribute:: JUNE
+
+   .. attribute:: JULY
+
+   .. attribute:: AUGUST
+
+   .. attribute:: SEPTEMBER
+
+   .. attribute:: OCTOBER
+
+   .. attribute:: NOVEMBER
+
+   .. attribute:: DECEMBER
+
+   .. versionadded:: 3.12
+
+
 .. class:: Calendar(firstweekday=0)
 
    Creates a :class:`Calendar` object. *firstweekday* is an integer specifying the
diff -pruN 3.12.0~a7-1/Doc/library/cmath.rst 3.12.0~b1-1/Doc/library/cmath.rst
--- 3.12.0~a7-1/Doc/library/cmath.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/cmath.rst	2023-05-22 12:07:36.000000000 +0000
@@ -301,7 +301,7 @@ Constants
    .. versionadded:: 3.6
 
 
-.. index:: module: math
+.. index:: pair: module; math
 
 Note that the selection of functions is similar, but not identical, to that in
 module :mod:`math`.  The reason for having two modules is that some users aren't
diff -pruN 3.12.0~a7-1/Doc/library/collections.abc.rst 3.12.0~b1-1/Doc/library/collections.abc.rst
--- 3.12.0~a7-1/Doc/library/collections.abc.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/collections.abc.rst	2023-05-22 12:07:36.000000000 +0000
@@ -177,6 +177,7 @@ ABC                            Inherits
 :class:`AsyncIterable` [1]_                           ``__aiter__``
 :class:`AsyncIterator` [1]_    :class:`AsyncIterable` ``__anext__``           ``__aiter__``
 :class:`AsyncGenerator` [1]_   :class:`AsyncIterator` ``asend``, ``athrow``   ``aclose``, ``__aiter__``, ``__anext__``
+:class:`Buffer` [1]_                                  ``__buffer__``
 ============================== ====================== ======================= ====================================================
 
 
@@ -272,6 +273,12 @@ Collections Abstract Base Classes -- Det
       The index() method added support for *stop* and *start*
       arguments.
 
+   .. deprecated-removed:: 3.12 3.14
+      The :class:`ByteString` ABC has been deprecated.
+      For use in typing, prefer a union, like ``bytes | bytearray``, or
+      :class:`collections.abc.Buffer`.
+      For use as an ABC, prefer :class:`Sequence` or :class:`collections.abc.Buffer`.
+
 .. class:: Set
            MutableSet
 
@@ -346,6 +353,13 @@ Collections Abstract Base Classes -- Det
 
    .. versionadded:: 3.6
 
+.. class:: Buffer
+
+   ABC for classes that provide the :meth:`~object.__buffer__` method,
+   implementing the :ref:`buffer protocol <bufferobjects>`. See :pep:`688`.
+
+   .. versionadded:: 3.12
+
 Examples and Recipes
 --------------------
 
diff -pruN 3.12.0~a7-1/Doc/library/contextlib.rst 3.12.0~b1-1/Doc/library/contextlib.rst
--- 3.12.0~a7-1/Doc/library/contextlib.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/contextlib.rst	2023-05-22 12:07:36.000000000 +0000
@@ -304,8 +304,15 @@ Functions and classes provided:
 
    This context manager is :ref:`reentrant <reentrant-cms>`.
 
+   If the code within the :keyword:`!with` block raises an
+   :exc:`ExceptionGroup`, suppressed exceptions are removed from the
+   group.  If any exceptions in the group are not suppressed, a group containing them is re-raised.
+
    .. versionadded:: 3.4
 
+   .. versionchanged:: 3.12
+      ``suppress`` now supports suppressing exceptions raised as
+      part of an :exc:`ExceptionGroup`.
 
 .. function:: redirect_stdout(new_target)
 
diff -pruN 3.12.0~a7-1/Doc/library/copy.rst 3.12.0~b1-1/Doc/library/copy.rst
--- 3.12.0~a7-1/Doc/library/copy.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/copy.rst	2023-05-22 12:07:36.000000000 +0000
@@ -68,7 +68,7 @@ Shallow copies of dictionaries can be ma
 of lists by assigning a slice of the entire list, for example,
 ``copied_list = original_list[:]``.
 
-.. index:: module: pickle
+.. index:: pair: module; pickle
 
 Classes can use the same interfaces to control copying that they use to control
 pickling.  See the description of module :mod:`pickle` for information on these
diff -pruN 3.12.0~a7-1/Doc/library/copyreg.rst 3.12.0~b1-1/Doc/library/copyreg.rst
--- 3.12.0~a7-1/Doc/library/copyreg.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/copyreg.rst	2023-05-22 12:07:36.000000000 +0000
@@ -7,8 +7,8 @@
 **Source code:** :source:`Lib/copyreg.py`
 
 .. index::
-   module: pickle
-   module: copy
+   pair: module; pickle
+   pair: module; copy
 
 --------------
 
@@ -28,8 +28,8 @@ Such constructors may be factory functio
 .. function:: pickle(type, function, constructor_ob=None)
 
    Declares that *function* should be used as a "reduction" function for objects
-   of type *type*.  *function* should return either a string or a tuple
-   containing two or three elements. See the :attr:`~pickle.Pickler.dispatch_table`
+   of type *type*.  *function* must return either a string or a tuple
+   containing between two and six elements. See the :attr:`~pickle.Pickler.dispatch_table`
    for more details on the interface of *function*.
 
    The *constructor_ob* parameter is a legacy feature and is now ignored, but if
diff -pruN 3.12.0~a7-1/Doc/library/csv.rst 3.12.0~b1-1/Doc/library/csv.rst
--- 3.12.0~a7-1/Doc/library/csv.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/csv.rst	2023-05-22 12:07:36.000000000 +0000
@@ -327,7 +327,7 @@ The :mod:`csv` module defines the follow
 
    Instructs :class:`writer` objects to quote all non-numeric fields.
 
-   Instructs the reader to convert all non-quoted fields to type *float*.
+   Instructs :class:`reader` objects to convert all non-quoted fields to type *float*.
 
 
 .. data:: QUOTE_NONE
@@ -337,7 +337,25 @@ The :mod:`csv` module defines the follow
    character.  If *escapechar* is not set, the writer will raise :exc:`Error` if
    any characters that require escaping are encountered.
 
-   Instructs :class:`reader` to perform no special processing of quote characters.
+   Instructs :class:`reader` objects to perform no special processing of quote characters.
+
+.. data:: QUOTE_NOTNULL
+
+   Instructs :class:`writer` objects to quote all fields which are not
+   ``None``.  This is similar to :data:`QUOTE_ALL`, except that if a
+   field value is ``None`` an empty (unquoted) string is written.
+
+   Instructs :class:`reader` objects to interpret an empty (unquoted) field as None and
+   to otherwise behave as :data:`QUOTE_ALL`.
+
+.. data:: QUOTE_STRINGS
+
+   Instructs :class:`writer` objects to always place quotes around fields
+   which are strings.  This is similar to :data:`QUOTE_NONNUMERIC`, except that if a
+   field value is ``None`` an empty (unquoted) string is written.
+
+   Instructs :class:`reader` objects to interpret an empty (unquoted) string as ``None`` and
+   to otherwise behave as :data:`QUOTE_NONNUMERIC`.
 
 The :mod:`csv` module defines the following exception:
 
diff -pruN 3.12.0~a7-1/Doc/library/ctypes.rst 3.12.0~b1-1/Doc/library/ctypes.rst
--- 3.12.0~a7-1/Doc/library/ctypes.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/ctypes.rst	2023-05-22 12:07:36.000000000 +0000
@@ -390,7 +390,7 @@ regular, non-variadic, function argument
 
    libc.printf.argtypes = [ctypes.c_char_p]
 
-Because specifying the attribute does inhibit portability it is advised to always
+Because specifying the attribute does not inhibit portability it is advised to always
 specify ``argtypes`` for all variadic functions.
 
 
diff -pruN 3.12.0~a7-1/Doc/library/curses.ascii.rst 3.12.0~b1-1/Doc/library/curses.ascii.rst
--- 3.12.0~a7-1/Doc/library/curses.ascii.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/curses.ascii.rst	2023-05-22 12:07:36.000000000 +0000
@@ -15,81 +15,81 @@ The :mod:`curses.ascii` module supplies
 functions to test membership in various ASCII character classes.  The constants
 supplied are names for control characters as follows:
 
-+--------------+----------------------------------------------+
-| Name         | Meaning                                      |
-+==============+==============================================+
-| :const:`NUL` |                                              |
-+--------------+----------------------------------------------+
-| :const:`SOH` | Start of heading, console interrupt          |
-+--------------+----------------------------------------------+
-| :const:`STX` | Start of text                                |
-+--------------+----------------------------------------------+
-| :const:`ETX` | End of text                                  |
-+--------------+----------------------------------------------+
-| :const:`EOT` | End of transmission                          |
-+--------------+----------------------------------------------+
-| :const:`ENQ` | Enquiry, goes with :const:`ACK` flow control |
-+--------------+----------------------------------------------+
-| :const:`ACK` | Acknowledgement                              |
-+--------------+----------------------------------------------+
-| :const:`BEL` | Bell                                         |
-+--------------+----------------------------------------------+
-| :const:`BS`  | Backspace                                    |
-+--------------+----------------------------------------------+
-| :const:`TAB` | Tab                                          |
-+--------------+----------------------------------------------+
-| :const:`HT`  | Alias for :const:`TAB`: "Horizontal tab"     |
-+--------------+----------------------------------------------+
-| :const:`LF`  | Line feed                                    |
-+--------------+----------------------------------------------+
-| :const:`NL`  | Alias for :const:`LF`: "New line"            |
-+--------------+----------------------------------------------+
-| :const:`VT`  | Vertical tab                                 |
-+--------------+----------------------------------------------+
-| :const:`FF`  | Form feed                                    |
-+--------------+----------------------------------------------+
-| :const:`CR`  | Carriage return                              |
-+--------------+----------------------------------------------+
-| :const:`SO`  | Shift-out, begin alternate character set     |
-+--------------+----------------------------------------------+
-| :const:`SI`  | Shift-in, resume default character set       |
-+--------------+----------------------------------------------+
-| :const:`DLE` | Data-link escape                             |
-+--------------+----------------------------------------------+
-| :const:`DC1` | XON, for flow control                        |
-+--------------+----------------------------------------------+
-| :const:`DC2` | Device control 2, block-mode flow control    |
-+--------------+----------------------------------------------+
-| :const:`DC3` | XOFF, for flow control                       |
-+--------------+----------------------------------------------+
-| :const:`DC4` | Device control 4                             |
-+--------------+----------------------------------------------+
-| :const:`NAK` | Negative acknowledgement                     |
-+--------------+----------------------------------------------+
-| :const:`SYN` | Synchronous idle                             |
-+--------------+----------------------------------------------+
-| :const:`ETB` | End transmission block                       |
-+--------------+----------------------------------------------+
-| :const:`CAN` | Cancel                                       |
-+--------------+----------------------------------------------+
-| :const:`EM`  | End of medium                                |
-+--------------+----------------------------------------------+
-| :const:`SUB` | Substitute                                   |
-+--------------+----------------------------------------------+
-| :const:`ESC` | Escape                                       |
-+--------------+----------------------------------------------+
-| :const:`FS`  | File separator                               |
-+--------------+----------------------------------------------+
-| :const:`GS`  | Group separator                              |
-+--------------+----------------------------------------------+
-| :const:`RS`  | Record separator, block-mode terminator      |
-+--------------+----------------------------------------------+
-| :const:`US`  | Unit separator                               |
-+--------------+----------------------------------------------+
-| :const:`SP`  | Space                                        |
-+--------------+----------------------------------------------+
-| :const:`DEL` | Delete                                       |
-+--------------+----------------------------------------------+
++---------------+----------------------------------------------+
+| Name          | Meaning                                      |
++===============+==============================================+
+| .. data:: NUL |                                              |
++---------------+----------------------------------------------+
+| .. data:: SOH | Start of heading, console interrupt          |
++---------------+----------------------------------------------+
+| .. data:: STX | Start of text                                |
++---------------+----------------------------------------------+
+| .. data:: ETX | End of text                                  |
++---------------+----------------------------------------------+
+| .. data:: EOT | End of transmission                          |
++---------------+----------------------------------------------+
+| .. data:: ENQ | Enquiry, goes with :const:`ACK` flow control |
++---------------+----------------------------------------------+
+| .. data:: ACK | Acknowledgement                              |
++---------------+----------------------------------------------+
+| .. data:: BEL | Bell                                         |
++---------------+----------------------------------------------+
+| .. data:: BS  | Backspace                                    |
++---------------+----------------------------------------------+
+| .. data:: TAB | Tab                                          |
++---------------+----------------------------------------------+
+| .. data:: HT  | Alias for :const:`TAB`: "Horizontal tab"     |
++---------------+----------------------------------------------+
+| .. data:: LF  | Line feed                                    |
++---------------+----------------------------------------------+
+| .. data:: NL  | Alias for :const:`LF`: "New line"            |
++---------------+----------------------------------------------+
+| .. data:: VT  | Vertical tab                                 |
++---------------+----------------------------------------------+
+| .. data:: FF  | Form feed                                    |
++---------------+----------------------------------------------+
+| .. data:: CR  | Carriage return                              |
++---------------+----------------------------------------------+
+| .. data:: SO  | Shift-out, begin alternate character set     |
++---------------+----------------------------------------------+
+| .. data:: SI  | Shift-in, resume default character set       |
++---------------+----------------------------------------------+
+| .. data:: DLE | Data-link escape                             |
++---------------+----------------------------------------------+
+| .. data:: DC1 | XON, for flow control                        |
++---------------+----------------------------------------------+
+| .. data:: DC2 | Device control 2, block-mode flow control    |
++---------------+----------------------------------------------+
+| .. data:: DC3 | XOFF, for flow control                       |
++---------------+----------------------------------------------+
+| .. data:: DC4 | Device control 4                             |
++---------------+----------------------------------------------+
+| .. data:: NAK | Negative acknowledgement                     |
++---------------+----------------------------------------------+
+| .. data:: SYN | Synchronous idle                             |
++---------------+----------------------------------------------+
+| .. data:: ETB | End transmission block                       |
++---------------+----------------------------------------------+
+| .. data:: CAN | Cancel                                       |
++---------------+----------------------------------------------+
+| .. data:: EM  | End of medium                                |
++---------------+----------------------------------------------+
+| .. data:: SUB | Substitute                                   |
++---------------+----------------------------------------------+
+| .. data:: ESC | Escape                                       |
++---------------+----------------------------------------------+
+| .. data:: FS  | File separator                               |
++---------------+----------------------------------------------+
+| .. data:: GS  | Group separator                              |
++---------------+----------------------------------------------+
+| .. data:: RS  | Record separator, block-mode terminator      |
++---------------+----------------------------------------------+
+| .. data:: US  | Unit separator                               |
++---------------+----------------------------------------------+
+| .. data:: SP  | Space                                        |
++---------------+----------------------------------------------+
+| .. data:: DEL | Delete                                       |
++---------------+----------------------------------------------+
 
 Note that many of these have little practical significance in modern usage.  The
 mnemonics derive from teleprinter conventions that predate digital computers.
diff -pruN 3.12.0~a7-1/Doc/library/curses.rst 3.12.0~b1-1/Doc/library/curses.rst
--- 3.12.0~a7-1/Doc/library/curses.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/curses.rst	2023-05-22 12:07:36.000000000 +0000
@@ -107,7 +107,7 @@ The module :mod:`curses` defines the fol
    Return the attribute value for displaying text in the specified color pair.
    Only the first 256 color pairs are supported. This
    attribute value can be combined with :const:`A_STANDOUT`, :const:`A_REVERSE`,
-   and the other :const:`A_\*` attributes.  :func:`pair_number` is the counterpart
+   and the other :const:`!A_\*` attributes.  :func:`pair_number` is the counterpart
    to this function.
 
 
@@ -223,7 +223,7 @@ The module :mod:`curses` defines the fol
 
 .. function:: getwin(file)
 
-   Read window related data stored in the file by an earlier :func:`putwin` call.
+   Read window related data stored in the file by an earlier :func:`window.putwin` call.
    The routine then creates and initializes a new window using that data, returning
    the new window object.
 
@@ -1323,9 +1323,9 @@ The :mod:`curses` module defines the fol
 
 
 .. data:: version
+.. data:: __version__
 
-   A bytes object representing the current version of the module.  Also available as
-   :const:`__version__`.
+   A bytes object representing the current version of the module.
 
 
 .. data:: ncurses_version
@@ -1339,51 +1339,55 @@ The :mod:`curses` module defines the fol
 
    .. versionadded:: 3.8
 
+.. data:: COLORS
+
+   The maximum number of colors the terminal can support.
+
+.. data:: COLOR_PAIRS
+
+   The maximum number of color pairs the terminal can support.
 
 Some constants are available to specify character cell attributes.
 The exact constants available are system dependent.
 
-+------------------+-------------------------------+
-| Attribute        | Meaning                       |
-+==================+===============================+
-| ``A_ALTCHARSET`` | Alternate character set mode  |
-+------------------+-------------------------------+
-| ``A_BLINK``      | Blink mode                    |
-+------------------+-------------------------------+
-| ``A_BOLD``       | Bold mode                     |
-+------------------+-------------------------------+
-| ``A_DIM``        | Dim mode                      |
-+------------------+-------------------------------+
-| ``A_INVIS``      | Invisible or blank mode       |
-+------------------+-------------------------------+
-| ``A_ITALIC``     | Italic mode                   |
-+------------------+-------------------------------+
-| ``A_NORMAL``     | Normal attribute              |
-+------------------+-------------------------------+
-| ``A_PROTECT``    | Protected mode                |
-+------------------+-------------------------------+
-| ``A_REVERSE``    | Reverse background and        |
-|                  | foreground colors             |
-+------------------+-------------------------------+
-| ``A_STANDOUT``   | Standout mode                 |
-+------------------+-------------------------------+
-| ``A_UNDERLINE``  | Underline mode                |
-+------------------+-------------------------------+
-| ``A_HORIZONTAL`` | Horizontal highlight          |
-+------------------+-------------------------------+
-| ``A_LEFT``       | Left highlight                |
-+------------------+-------------------------------+
-| ``A_LOW``        | Low highlight                 |
-+------------------+-------------------------------+
-| ``A_RIGHT``      | Right highlight               |
-+------------------+-------------------------------+
-| ``A_TOP``        | Top highlight                 |
-+------------------+-------------------------------+
-| ``A_VERTICAL``   | Vertical highlight            |
-+------------------+-------------------------------+
-| ``A_CHARTEXT``   | Bit-mask to extract a         |
-|                  | character                     |
-+------------------+-------------------------------+
++------------------------+-------------------------------+
+| Attribute              | Meaning                       |
++========================+===============================+
+| .. data:: A_ALTCHARSET | Alternate character set mode  |
++------------------------+-------------------------------+
+| .. data:: A_BLINK      | Blink mode                    |
++------------------------+-------------------------------+
+| .. data:: A_BOLD       | Bold mode                     |
++------------------------+-------------------------------+
+| .. data:: A_DIM        | Dim mode                      |
++------------------------+-------------------------------+
+| .. data:: A_INVIS      | Invisible or blank mode       |
++------------------------+-------------------------------+
+| .. data:: A_ITALIC     | Italic mode                   |
++------------------------+-------------------------------+
+| .. data:: A_NORMAL     | Normal attribute              |
++------------------------+-------------------------------+
+| .. data:: A_PROTECT    | Protected mode                |
++------------------------+-------------------------------+
+| .. data:: A_REVERSE    | Reverse background and        |
+|                        | foreground colors             |
++------------------------+-------------------------------+
+| .. data:: A_STANDOUT   | Standout mode                 |
++------------------------+-------------------------------+
+| .. data:: A_UNDERLINE  | Underline mode                |
++------------------------+-------------------------------+
+| .. data:: A_HORIZONTAL | Horizontal highlight          |
++------------------------+-------------------------------+
+| .. data:: A_LEFT       | Left highlight                |
++------------------------+-------------------------------+
+| .. data:: A_LOW        | Low highlight                 |
++------------------------+-------------------------------+
+| .. data:: A_RIGHT      | Right highlight               |
++------------------------+-------------------------------+
+| .. data:: A_TOP        | Top highlight                 |
++------------------------+-------------------------------+
+| .. data:: A_VERTICAL   | Vertical highlight            |
++------------------------+-------------------------------+
 
 .. versionadded:: 3.7
    ``A_ITALIC`` was added.
@@ -1391,220 +1395,220 @@ The exact constants available are system
 Several constants are available to extract corresponding attributes returned
 by some methods.
 
-+------------------+-------------------------------+
-| Bit-mask         | Meaning                       |
-+==================+===============================+
-| ``A_ATTRIBUTES`` | Bit-mask to extract           |
-|                  | attributes                    |
-+------------------+-------------------------------+
-| ``A_CHARTEXT``   | Bit-mask to extract a         |
-|                  | character                     |
-+------------------+-------------------------------+
-| ``A_COLOR``      | Bit-mask to extract           |
-|                  | color-pair field information  |
-+------------------+-------------------------------+
++-------------------------+-------------------------------+
+| Bit-mask                | Meaning                       |
++=========================+===============================+
+|  .. data:: A_ATTRIBUTES | Bit-mask to extract           |
+|                         | attributes                    |
++-------------------------+-------------------------------+
+|  .. data:: A_CHARTEXT   | Bit-mask to extract a         |
+|                         | character                     |
++-------------------------+-------------------------------+
+|  .. data:: A_COLOR      | Bit-mask to extract           |
+|                         | color-pair field information  |
++-------------------------+-------------------------------+
 
 Keys are referred to by integer constants with names starting with  ``KEY_``.
 The exact keycaps available are system dependent.
 
 .. XXX this table is far too large! should it be alphabetized?
 
-+-------------------+--------------------------------------------+
-| Key constant      | Key                                        |
-+===================+============================================+
-| ``KEY_MIN``       | Minimum key value                          |
-+-------------------+--------------------------------------------+
-| ``KEY_BREAK``     | Break key (unreliable)                     |
-+-------------------+--------------------------------------------+
-| ``KEY_DOWN``      | Down-arrow                                 |
-+-------------------+--------------------------------------------+
-| ``KEY_UP``        | Up-arrow                                   |
-+-------------------+--------------------------------------------+
-| ``KEY_LEFT``      | Left-arrow                                 |
-+-------------------+--------------------------------------------+
-| ``KEY_RIGHT``     | Right-arrow                                |
-+-------------------+--------------------------------------------+
-| ``KEY_HOME``      | Home key (upward+left arrow)               |
-+-------------------+--------------------------------------------+
-| ``KEY_BACKSPACE`` | Backspace (unreliable)                     |
-+-------------------+--------------------------------------------+
-| ``KEY_F0``        | Function keys.  Up to 64 function keys are |
-|                   | supported.                                 |
-+-------------------+--------------------------------------------+
-| ``KEY_Fn``        | Value of function key *n*                  |
-+-------------------+--------------------------------------------+
-| ``KEY_DL``        | Delete line                                |
-+-------------------+--------------------------------------------+
-| ``KEY_IL``        | Insert line                                |
-+-------------------+--------------------------------------------+
-| ``KEY_DC``        | Delete character                           |
-+-------------------+--------------------------------------------+
-| ``KEY_IC``        | Insert char or enter insert mode           |
-+-------------------+--------------------------------------------+
-| ``KEY_EIC``       | Exit insert char mode                      |
-+-------------------+--------------------------------------------+
-| ``KEY_CLEAR``     | Clear screen                               |
-+-------------------+--------------------------------------------+
-| ``KEY_EOS``       | Clear to end of screen                     |
-+-------------------+--------------------------------------------+
-| ``KEY_EOL``       | Clear to end of line                       |
-+-------------------+--------------------------------------------+
-| ``KEY_SF``        | Scroll 1 line forward                      |
-+-------------------+--------------------------------------------+
-| ``KEY_SR``        | Scroll 1 line backward (reverse)           |
-+-------------------+--------------------------------------------+
-| ``KEY_NPAGE``     | Next page                                  |
-+-------------------+--------------------------------------------+
-| ``KEY_PPAGE``     | Previous page                              |
-+-------------------+--------------------------------------------+
-| ``KEY_STAB``      | Set tab                                    |
-+-------------------+--------------------------------------------+
-| ``KEY_CTAB``      | Clear tab                                  |
-+-------------------+--------------------------------------------+
-| ``KEY_CATAB``     | Clear all tabs                             |
-+-------------------+--------------------------------------------+
-| ``KEY_ENTER``     | Enter or send (unreliable)                 |
-+-------------------+--------------------------------------------+
-| ``KEY_SRESET``    | Soft (partial) reset (unreliable)          |
-+-------------------+--------------------------------------------+
-| ``KEY_RESET``     | Reset or hard reset (unreliable)           |
-+-------------------+--------------------------------------------+
-| ``KEY_PRINT``     | Print                                      |
-+-------------------+--------------------------------------------+
-| ``KEY_LL``        | Home down or bottom (lower left)           |
-+-------------------+--------------------------------------------+
-| ``KEY_A1``        | Upper left of keypad                       |
-+-------------------+--------------------------------------------+
-| ``KEY_A3``        | Upper right of keypad                      |
-+-------------------+--------------------------------------------+
-| ``KEY_B2``        | Center of keypad                           |
-+-------------------+--------------------------------------------+
-| ``KEY_C1``        | Lower left of keypad                       |
-+-------------------+--------------------------------------------+
-| ``KEY_C3``        | Lower right of keypad                      |
-+-------------------+--------------------------------------------+
-| ``KEY_BTAB``      | Back tab                                   |
-+-------------------+--------------------------------------------+
-| ``KEY_BEG``       | Beg (beginning)                            |
-+-------------------+--------------------------------------------+
-| ``KEY_CANCEL``    | Cancel                                     |
-+-------------------+--------------------------------------------+
-| ``KEY_CLOSE``     | Close                                      |
-+-------------------+--------------------------------------------+
-| ``KEY_COMMAND``   | Cmd (command)                              |
-+-------------------+--------------------------------------------+
-| ``KEY_COPY``      | Copy                                       |
-+-------------------+--------------------------------------------+
-| ``KEY_CREATE``    | Create                                     |
-+-------------------+--------------------------------------------+
-| ``KEY_END``       | End                                        |
-+-------------------+--------------------------------------------+
-| ``KEY_EXIT``      | Exit                                       |
-+-------------------+--------------------------------------------+
-| ``KEY_FIND``      | Find                                       |
-+-------------------+--------------------------------------------+
-| ``KEY_HELP``      | Help                                       |
-+-------------------+--------------------------------------------+
-| ``KEY_MARK``      | Mark                                       |
-+-------------------+--------------------------------------------+
-| ``KEY_MESSAGE``   | Message                                    |
-+-------------------+--------------------------------------------+
-| ``KEY_MOVE``      | Move                                       |
-+-------------------+--------------------------------------------+
-| ``KEY_NEXT``      | Next                                       |
-+-------------------+--------------------------------------------+
-| ``KEY_OPEN``      | Open                                       |
-+-------------------+--------------------------------------------+
-| ``KEY_OPTIONS``   | Options                                    |
-+-------------------+--------------------------------------------+
-| ``KEY_PREVIOUS``  | Prev (previous)                            |
-+-------------------+--------------------------------------------+
-| ``KEY_REDO``      | Redo                                       |
-+-------------------+--------------------------------------------+
-| ``KEY_REFERENCE`` | Ref (reference)                            |
-+-------------------+--------------------------------------------+
-| ``KEY_REFRESH``   | Refresh                                    |
-+-------------------+--------------------------------------------+
-| ``KEY_REPLACE``   | Replace                                    |
-+-------------------+--------------------------------------------+
-| ``KEY_RESTART``   | Restart                                    |
-+-------------------+--------------------------------------------+
-| ``KEY_RESUME``    | Resume                                     |
-+-------------------+--------------------------------------------+
-| ``KEY_SAVE``      | Save                                       |
-+-------------------+--------------------------------------------+
-| ``KEY_SBEG``      | Shifted Beg (beginning)                    |
-+-------------------+--------------------------------------------+
-| ``KEY_SCANCEL``   | Shifted Cancel                             |
-+-------------------+--------------------------------------------+
-| ``KEY_SCOMMAND``  | Shifted Command                            |
-+-------------------+--------------------------------------------+
-| ``KEY_SCOPY``     | Shifted Copy                               |
-+-------------------+--------------------------------------------+
-| ``KEY_SCREATE``   | Shifted Create                             |
-+-------------------+--------------------------------------------+
-| ``KEY_SDC``       | Shifted Delete char                        |
-+-------------------+--------------------------------------------+
-| ``KEY_SDL``       | Shifted Delete line                        |
-+-------------------+--------------------------------------------+
-| ``KEY_SELECT``    | Select                                     |
-+-------------------+--------------------------------------------+
-| ``KEY_SEND``      | Shifted End                                |
-+-------------------+--------------------------------------------+
-| ``KEY_SEOL``      | Shifted Clear line                         |
-+-------------------+--------------------------------------------+
-| ``KEY_SEXIT``     | Shifted Exit                               |
-+-------------------+--------------------------------------------+
-| ``KEY_SFIND``     | Shifted Find                               |
-+-------------------+--------------------------------------------+
-| ``KEY_SHELP``     | Shifted Help                               |
-+-------------------+--------------------------------------------+
-| ``KEY_SHOME``     | Shifted Home                               |
-+-------------------+--------------------------------------------+
-| ``KEY_SIC``       | Shifted Input                              |
-+-------------------+--------------------------------------------+
-| ``KEY_SLEFT``     | Shifted Left arrow                         |
-+-------------------+--------------------------------------------+
-| ``KEY_SMESSAGE``  | Shifted Message                            |
-+-------------------+--------------------------------------------+
-| ``KEY_SMOVE``     | Shifted Move                               |
-+-------------------+--------------------------------------------+
-| ``KEY_SNEXT``     | Shifted Next                               |
-+-------------------+--------------------------------------------+
-| ``KEY_SOPTIONS``  | Shifted Options                            |
-+-------------------+--------------------------------------------+
-| ``KEY_SPREVIOUS`` | Shifted Prev                               |
-+-------------------+--------------------------------------------+
-| ``KEY_SPRINT``    | Shifted Print                              |
-+-------------------+--------------------------------------------+
-| ``KEY_SREDO``     | Shifted Redo                               |
-+-------------------+--------------------------------------------+
-| ``KEY_SREPLACE``  | Shifted Replace                            |
-+-------------------+--------------------------------------------+
-| ``KEY_SRIGHT``    | Shifted Right arrow                        |
-+-------------------+--------------------------------------------+
-| ``KEY_SRSUME``    | Shifted Resume                             |
-+-------------------+--------------------------------------------+
-| ``KEY_SSAVE``     | Shifted Save                               |
-+-------------------+--------------------------------------------+
-| ``KEY_SSUSPEND``  | Shifted Suspend                            |
-+-------------------+--------------------------------------------+
-| ``KEY_SUNDO``     | Shifted Undo                               |
-+-------------------+--------------------------------------------+
-| ``KEY_SUSPEND``   | Suspend                                    |
-+-------------------+--------------------------------------------+
-| ``KEY_UNDO``      | Undo                                       |
-+-------------------+--------------------------------------------+
-| ``KEY_MOUSE``     | Mouse event has occurred                   |
-+-------------------+--------------------------------------------+
-| ``KEY_RESIZE``    | Terminal resize event                      |
-+-------------------+--------------------------------------------+
-| ``KEY_MAX``       | Maximum key value                          |
-+-------------------+--------------------------------------------+
++-------------------------+--------------------------------------------+
+| Key constant            | Key                                        |
++=========================+============================================+
+| .. data:: KEY_MIN       | Minimum key value                          |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_BREAK     | Break key (unreliable)                     |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_DOWN      | Down-arrow                                 |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_UP        | Up-arrow                                   |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_LEFT      | Left-arrow                                 |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_RIGHT     | Right-arrow                                |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_HOME      | Home key (upward+left arrow)               |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_BACKSPACE | Backspace (unreliable)                     |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_F0        | Function keys.  Up to 64 function keys are |
+|                         | supported.                                 |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_Fn        | Value of function key *n*                  |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_DL        | Delete line                                |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_IL        | Insert line                                |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_DC        | Delete character                           |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_IC        | Insert char or enter insert mode           |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_EIC       | Exit insert char mode                      |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_CLEAR     | Clear screen                               |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_EOS       | Clear to end of screen                     |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_EOL       | Clear to end of line                       |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_SF        | Scroll 1 line forward                      |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_SR        | Scroll 1 line backward (reverse)           |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_NPAGE     | Next page                                  |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_PPAGE     | Previous page                              |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_STAB      | Set tab                                    |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_CTAB      | Clear tab                                  |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_CATAB     | Clear all tabs                             |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_ENTER     | Enter or send (unreliable)                 |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_SRESET    | Soft (partial) reset (unreliable)          |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_RESET     | Reset or hard reset (unreliable)           |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_PRINT     | Print                                      |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_LL        | Home down or bottom (lower left)           |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_A1        | Upper left of keypad                       |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_A3        | Upper right of keypad                      |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_B2        | Center of keypad                           |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_C1        | Lower left of keypad                       |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_C3        | Lower right of keypad                      |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_BTAB      | Back tab                                   |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_BEG       | Beg (beginning)                            |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_CANCEL    | Cancel                                     |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_CLOSE     | Close                                      |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_COMMAND   | Cmd (command)                              |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_COPY      | Copy                                       |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_CREATE    | Create                                     |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_END       | End                                        |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_EXIT      | Exit                                       |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_FIND      | Find                                       |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_HELP      | Help                                       |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_MARK      | Mark                                       |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_MESSAGE   | Message                                    |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_MOVE      | Move                                       |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_NEXT      | Next                                       |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_OPEN      | Open                                       |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_OPTIONS   | Options                                    |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_PREVIOUS  | Prev (previous)                            |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_REDO      | Redo                                       |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_REFERENCE | Ref (reference)                            |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_REFRESH   | Refresh                                    |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_REPLACE   | Replace                                    |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_RESTART   | Restart                                    |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_RESUME    | Resume                                     |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_SAVE      | Save                                       |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_SBEG      | Shifted Beg (beginning)                    |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_SCANCEL   | Shifted Cancel                             |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_SCOMMAND  | Shifted Command                            |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_SCOPY     | Shifted Copy                               |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_SCREATE   | Shifted Create                             |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_SDC       | Shifted Delete char                        |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_SDL       | Shifted Delete line                        |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_SELECT    | Select                                     |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_SEND      | Shifted End                                |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_SEOL      | Shifted Clear line                         |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_SEXIT     | Shifted Exit                               |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_SFIND     | Shifted Find                               |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_SHELP     | Shifted Help                               |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_SHOME     | Shifted Home                               |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_SIC       | Shifted Input                              |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_SLEFT     | Shifted Left arrow                         |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_SMESSAGE  | Shifted Message                            |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_SMOVE     | Shifted Move                               |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_SNEXT     | Shifted Next                               |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_SOPTIONS  | Shifted Options                            |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_SPREVIOUS | Shifted Prev                               |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_SPRINT    | Shifted Print                              |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_SREDO     | Shifted Redo                               |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_SREPLACE  | Shifted Replace                            |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_SRIGHT    | Shifted Right arrow                        |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_SRSUME    | Shifted Resume                             |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_SSAVE     | Shifted Save                               |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_SSUSPEND  | Shifted Suspend                            |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_SUNDO     | Shifted Undo                               |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_SUSPEND   | Suspend                                    |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_UNDO      | Undo                                       |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_MOUSE     | Mouse event has occurred                   |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_RESIZE    | Terminal resize event                      |
++-------------------------+--------------------------------------------+
+| .. data:: KEY_MAX       | Maximum key value                          |
++-------------------------+--------------------------------------------+
 
 On VT100s and their software emulations, such as X terminal emulators, there are
-normally at least four function keys (:const:`KEY_F1`, :const:`KEY_F2`,
-:const:`KEY_F3`, :const:`KEY_F4`) available, and the arrow keys mapped to
+normally at least four function keys (:const:`KEY_F1 <KEY_Fn>`, :const:`KEY_F2 <KEY_Fn>`,
+:const:`KEY_F3 <KEY_Fn>`, :const:`KEY_F4 <KEY_Fn>`) available, and the arrow keys mapped to
 :const:`KEY_UP`, :const:`KEY_DOWN`, :const:`KEY_LEFT` and :const:`KEY_RIGHT` in
 the obvious way.  If your machine has a PC keyboard, it is safe to expect arrow
 keys and twelve function keys (older PC keyboards may have only ten function
@@ -1635,117 +1639,143 @@ falls back on a crude printable ASCII ap
 
    These are available only after :func:`initscr` has  been called.
 
-+------------------+------------------------------------------+
-| ACS code         | Meaning                                  |
-+==================+==========================================+
-| ``ACS_BBSS``     | alternate name for upper right corner    |
-+------------------+------------------------------------------+
-| ``ACS_BLOCK``    | solid square block                       |
-+------------------+------------------------------------------+
-| ``ACS_BOARD``    | board of squares                         |
-+------------------+------------------------------------------+
-| ``ACS_BSBS``     | alternate name for horizontal line       |
-+------------------+------------------------------------------+
-| ``ACS_BSSB``     | alternate name for upper left corner     |
-+------------------+------------------------------------------+
-| ``ACS_BSSS``     | alternate name for top tee               |
-+------------------+------------------------------------------+
-| ``ACS_BTEE``     | bottom tee                               |
-+------------------+------------------------------------------+
-| ``ACS_BULLET``   | bullet                                   |
-+------------------+------------------------------------------+
-| ``ACS_CKBOARD``  | checker board (stipple)                  |
-+------------------+------------------------------------------+
-| ``ACS_DARROW``   | arrow pointing down                      |
-+------------------+------------------------------------------+
-| ``ACS_DEGREE``   | degree symbol                            |
-+------------------+------------------------------------------+
-| ``ACS_DIAMOND``  | diamond                                  |
-+------------------+------------------------------------------+
-| ``ACS_GEQUAL``   | greater-than-or-equal-to                 |
-+------------------+------------------------------------------+
-| ``ACS_HLINE``    | horizontal line                          |
-+------------------+------------------------------------------+
-| ``ACS_LANTERN``  | lantern symbol                           |
-+------------------+------------------------------------------+
-| ``ACS_LARROW``   | left arrow                               |
-+------------------+------------------------------------------+
-| ``ACS_LEQUAL``   | less-than-or-equal-to                    |
-+------------------+------------------------------------------+
-| ``ACS_LLCORNER`` | lower left-hand corner                   |
-+------------------+------------------------------------------+
-| ``ACS_LRCORNER`` | lower right-hand corner                  |
-+------------------+------------------------------------------+
-| ``ACS_LTEE``     | left tee                                 |
-+------------------+------------------------------------------+
-| ``ACS_NEQUAL``   | not-equal sign                           |
-+------------------+------------------------------------------+
-| ``ACS_PI``       | letter pi                                |
-+------------------+------------------------------------------+
-| ``ACS_PLMINUS``  | plus-or-minus sign                       |
-+------------------+------------------------------------------+
-| ``ACS_PLUS``     | big plus sign                            |
-+------------------+------------------------------------------+
-| ``ACS_RARROW``   | right arrow                              |
-+------------------+------------------------------------------+
-| ``ACS_RTEE``     | right tee                                |
-+------------------+------------------------------------------+
-| ``ACS_S1``       | scan line 1                              |
-+------------------+------------------------------------------+
-| ``ACS_S3``       | scan line 3                              |
-+------------------+------------------------------------------+
-| ``ACS_S7``       | scan line 7                              |
-+------------------+------------------------------------------+
-| ``ACS_S9``       | scan line 9                              |
-+------------------+------------------------------------------+
-| ``ACS_SBBS``     | alternate name for lower right corner    |
-+------------------+------------------------------------------+
-| ``ACS_SBSB``     | alternate name for vertical line         |
-+------------------+------------------------------------------+
-| ``ACS_SBSS``     | alternate name for right tee             |
-+------------------+------------------------------------------+
-| ``ACS_SSBB``     | alternate name for lower left corner     |
-+------------------+------------------------------------------+
-| ``ACS_SSBS``     | alternate name for bottom tee            |
-+------------------+------------------------------------------+
-| ``ACS_SSSB``     | alternate name for left tee              |
-+------------------+------------------------------------------+
-| ``ACS_SSSS``     | alternate name for crossover or big plus |
-+------------------+------------------------------------------+
-| ``ACS_STERLING`` | pound sterling                           |
-+------------------+------------------------------------------+
-| ``ACS_TTEE``     | top tee                                  |
-+------------------+------------------------------------------+
-| ``ACS_UARROW``   | up arrow                                 |
-+------------------+------------------------------------------+
-| ``ACS_ULCORNER`` | upper left corner                        |
-+------------------+------------------------------------------+
-| ``ACS_URCORNER`` | upper right corner                       |
-+------------------+------------------------------------------+
-| ``ACS_VLINE``    | vertical line                            |
-+------------------+------------------------------------------+
++------------------------+------------------------------------------+
+| ACS code               | Meaning                                  |
++========================+==========================================+
+| .. data:: ACS_BBSS     | alternate name for upper right corner    |
++------------------------+------------------------------------------+
+| .. data:: ACS_BLOCK    | solid square block                       |
++------------------------+------------------------------------------+
+| .. data:: ACS_BOARD    | board of squares                         |
++------------------------+------------------------------------------+
+| .. data:: ACS_BSBS     | alternate name for horizontal line       |
++------------------------+------------------------------------------+
+| .. data:: ACS_BSSB     | alternate name for upper left corner     |
++------------------------+------------------------------------------+
+| .. data:: ACS_BSSS     | alternate name for top tee               |
++------------------------+------------------------------------------+
+| .. data:: ACS_BTEE     | bottom tee                               |
++------------------------+------------------------------------------+
+| .. data:: ACS_BULLET   | bullet                                   |
++------------------------+------------------------------------------+
+| .. data:: ACS_CKBOARD  | checker board (stipple)                  |
++------------------------+------------------------------------------+
+| .. data:: ACS_DARROW   | arrow pointing down                      |
++------------------------+------------------------------------------+
+| .. data:: ACS_DEGREE   | degree symbol                            |
++------------------------+------------------------------------------+
+| .. data:: ACS_DIAMOND  | diamond                                  |
++------------------------+------------------------------------------+
+| .. data:: ACS_GEQUAL   | greater-than-or-equal-to                 |
++------------------------+------------------------------------------+
+| .. data:: ACS_HLINE    | horizontal line                          |
++------------------------+------------------------------------------+
+| .. data:: ACS_LANTERN  | lantern symbol                           |
++------------------------+------------------------------------------+
+| .. data:: ACS_LARROW   | left arrow                               |
++------------------------+------------------------------------------+
+| .. data:: ACS_LEQUAL   | less-than-or-equal-to                    |
++------------------------+------------------------------------------+
+| .. data:: ACS_LLCORNER | lower left-hand corner                   |
++------------------------+------------------------------------------+
+| .. data:: ACS_LRCORNER | lower right-hand corner                  |
++------------------------+------------------------------------------+
+| .. data:: ACS_LTEE     | left tee                                 |
++------------------------+------------------------------------------+
+| .. data:: ACS_NEQUAL   | not-equal sign                           |
++------------------------+------------------------------------------+
+| .. data:: ACS_PI       | letter pi                                |
++------------------------+------------------------------------------+
+| .. data:: ACS_PLMINUS  | plus-or-minus sign                       |
++------------------------+------------------------------------------+
+| .. data:: ACS_PLUS     | big plus sign                            |
++------------------------+------------------------------------------+
+| .. data:: ACS_RARROW   | right arrow                              |
++------------------------+------------------------------------------+
+| .. data:: ACS_RTEE     | right tee                                |
++------------------------+------------------------------------------+
+| .. data:: ACS_S1       | scan line 1                              |
++------------------------+------------------------------------------+
+| .. data:: ACS_S3       | scan line 3                              |
++------------------------+------------------------------------------+
+| .. data:: ACS_S7       | scan line 7                              |
++------------------------+------------------------------------------+
+| .. data:: ACS_S9       | scan line 9                              |
++------------------------+------------------------------------------+
+| .. data:: ACS_SBBS     | alternate name for lower right corner    |
++------------------------+------------------------------------------+
+| .. data:: ACS_SBSB     | alternate name for vertical line         |
++------------------------+------------------------------------------+
+| .. data:: ACS_SBSS     | alternate name for right tee             |
++------------------------+------------------------------------------+
+| .. data:: ACS_SSBB     | alternate name for lower left corner     |
++------------------------+------------------------------------------+
+| .. data:: ACS_SSBS     | alternate name for bottom tee            |
++------------------------+------------------------------------------+
+| .. data:: ACS_SSSB     | alternate name for left tee              |
++------------------------+------------------------------------------+
+| .. data:: ACS_SSSS     | alternate name for crossover or big plus |
++------------------------+------------------------------------------+
+| .. data:: ACS_STERLING | pound sterling                           |
++------------------------+------------------------------------------+
+| .. data:: ACS_TTEE     | top tee                                  |
++------------------------+------------------------------------------+
+| .. data:: ACS_UARROW   | up arrow                                 |
++------------------------+------------------------------------------+
+| .. data:: ACS_ULCORNER | upper left corner                        |
++------------------------+------------------------------------------+
+| .. data:: ACS_URCORNER | upper right corner                       |
++------------------------+------------------------------------------+
+| .. data:: ACS_VLINE    | vertical line                            |
++------------------------+------------------------------------------+
+
+The following table lists mouse button constants used by :meth:`getmouse`:
+
++----------------------------------+---------------------------------------------+
+| Mouse button constant            | Meaning                                     |
++==================================+=============================================+
+| .. data:: BUTTONn_PRESSED        | Mouse button *n* pressed                    |
++----------------------------------+---------------------------------------------+
+| .. data:: BUTTONn_RELEASED       | Mouse button *n* released                   |
++----------------------------------+---------------------------------------------+
+| .. data:: BUTTONn_CLICKED        | Mouse button *n* clicked                    |
++----------------------------------+---------------------------------------------+
+| .. data:: BUTTONn_DOUBLE_CLICKED | Mouse button *n* double clicked             |
++----------------------------------+---------------------------------------------+
+| .. data:: BUTTONn_TRIPLE_CLICKED | Mouse button *n* triple clicked             |
++----------------------------------+---------------------------------------------+
+| .. data:: BUTTON_SHIFT           | Shift was down during button state change   |
++----------------------------------+---------------------------------------------+
+| .. data:: BUTTON_CTRL            | Control was down during button state change |
++----------------------------------+---------------------------------------------+
+| .. data:: BUTTON_ALT             | Control was down during button state change |
++----------------------------------+---------------------------------------------+
+
+   .. versionchanged:: 3.10
+      The ``BUTTON5_*`` constants are now exposed if they are provided by the
+      underlying curses library.
 
 The following table lists the predefined colors:
 
-+-------------------+----------------------------+
-| Constant          | Color                      |
-+===================+============================+
-| ``COLOR_BLACK``   | Black                      |
-+-------------------+----------------------------+
-| ``COLOR_BLUE``    | Blue                       |
-+-------------------+----------------------------+
-| ``COLOR_CYAN``    | Cyan (light greenish blue) |
-+-------------------+----------------------------+
-| ``COLOR_GREEN``   | Green                      |
-+-------------------+----------------------------+
-| ``COLOR_MAGENTA`` | Magenta (purplish red)     |
-+-------------------+----------------------------+
-| ``COLOR_RED``     | Red                        |
-+-------------------+----------------------------+
-| ``COLOR_WHITE``   | White                      |
-+-------------------+----------------------------+
-| ``COLOR_YELLOW``  | Yellow                     |
-+-------------------+----------------------------+
++-------------------------+----------------------------+
+| Constant                | Color                      |
++=========================+============================+
+| .. data:: COLOR_BLACK   | Black                      |
++-------------------------+----------------------------+
+| .. data:: COLOR_BLUE    | Blue                       |
++-------------------------+----------------------------+
+| .. data:: COLOR_CYAN    | Cyan (light greenish blue) |
++-------------------------+----------------------------+
+| .. data:: COLOR_GREEN   | Green                      |
++-------------------------+----------------------------+
+| .. data:: COLOR_MAGENTA | Magenta (purplish red)     |
++-------------------------+----------------------------+
+| .. data:: COLOR_RED     | Red                        |
++-------------------------+----------------------------+
+| .. data:: COLOR_WHITE   | White                      |
++-------------------------+----------------------------+
+| .. data:: COLOR_YELLOW  | Yellow                     |
++-------------------------+----------------------------+
 
 
 :mod:`curses.textpad` --- Text input widget for curses programs
@@ -1851,19 +1881,19 @@ You can instantiate a :class:`Textbox` o
       Move operations do nothing if the cursor is at an edge where the movement
       is not possible.  The following synonyms are supported where possible:
 
-      +------------------------+------------------+
-      | Constant               | Keystroke        |
-      +========================+==================+
-      | :const:`KEY_LEFT`      | :kbd:`Control-B` |
-      +------------------------+------------------+
-      | :const:`KEY_RIGHT`     | :kbd:`Control-F` |
-      +------------------------+------------------+
-      | :const:`KEY_UP`        | :kbd:`Control-P` |
-      +------------------------+------------------+
-      | :const:`KEY_DOWN`      | :kbd:`Control-N` |
-      +------------------------+------------------+
-      | :const:`KEY_BACKSPACE` | :kbd:`Control-h` |
-      +------------------------+------------------+
+      +--------------------------------+------------------+
+      | Constant                       | Keystroke        |
+      +================================+==================+
+      | :const:`~curses.KEY_LEFT`      | :kbd:`Control-B` |
+      +--------------------------------+------------------+
+      | :const:`~curses.KEY_RIGHT`     | :kbd:`Control-F` |
+      +--------------------------------+------------------+
+      | :const:`~curses.KEY_UP`        | :kbd:`Control-P` |
+      +--------------------------------+------------------+
+      | :const:`~curses.KEY_DOWN`      | :kbd:`Control-N` |
+      +--------------------------------+------------------+
+      | :const:`~curses.KEY_BACKSPACE` | :kbd:`Control-h` |
+      +--------------------------------+------------------+
 
       All other keystrokes are treated as a command to insert the given
       character and move right (with line wrapping).
diff -pruN 3.12.0~a7-1/Doc/library/dataclasses.rst 3.12.0~b1-1/Doc/library/dataclasses.rst
--- 3.12.0~a7-1/Doc/library/dataclasses.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/dataclasses.rst	2023-05-22 12:07:36.000000000 +0000
@@ -12,8 +12,8 @@
 --------------
 
 This module provides a decorator and functions for automatically
-adding generated :term:`special method`\s such as :meth:`__init__` and
-:meth:`__repr__` to user-defined classes.  It was originally described
+adding generated :term:`special method`\s such as :meth:`~object.__init__` and
+:meth:`~object.__repr__` to user-defined classes.  It was originally described
 in :pep:`557`.
 
 The member variables to use in these generated methods are defined
@@ -31,7 +31,7 @@ using :pep:`526` type annotations.  For
       def total_cost(self) -> float:
           return self.unit_price * self.quantity_on_hand
 
-will add, among other things, a :meth:`__init__` that looks like::
+will add, among other things, a :meth:`~object.__init__` that looks like::
 
   def __init__(self, name: str, unit_price: float, quantity_on_hand: int = 0):
       self.name = name
@@ -86,86 +86,86 @@ Module contents
 
    The parameters to :func:`dataclass` are:
 
-   - ``init``: If true (the default), a :meth:`__init__` method will be
+   - ``init``: If true (the default), a :meth:`~object.__init__` method will be
      generated.
 
-     If the class already defines :meth:`__init__`, this parameter is
+     If the class already defines :meth:`~object.__init__`, this parameter is
      ignored.
 
-   - ``repr``: If true (the default), a :meth:`__repr__` method will be
+   - ``repr``: If true (the default), a :meth:`~object.__repr__` method will be
      generated.  The generated repr string will have the class name and
      the name and repr of each field, in the order they are defined in
      the class.  Fields that are marked as being excluded from the repr
      are not included.  For example:
      ``InventoryItem(name='widget', unit_price=3.0, quantity_on_hand=10)``.
 
-     If the class already defines :meth:`__repr__`, this parameter is
+     If the class already defines :meth:`~object.__repr__`, this parameter is
      ignored.
 
-   - ``eq``: If true (the default), an :meth:`__eq__` method will be
+   - ``eq``: If true (the default), an :meth:`~object.__eq__` method will be
      generated.  This method compares the class as if it were a tuple
      of its fields, in order.  Both instances in the comparison must
      be of the identical type.
 
-     If the class already defines :meth:`__eq__`, this parameter is
+     If the class already defines :meth:`~object.__eq__`, this parameter is
      ignored.
 
-   - ``order``: If true (the default is ``False``), :meth:`__lt__`,
-     :meth:`__le__`, :meth:`__gt__`, and :meth:`__ge__` methods will be
+   - ``order``: If true (the default is ``False``), :meth:`~object.__lt__`,
+     :meth:`~object.__le__`, :meth:`~object.__gt__`, and :meth:`~object.__ge__` methods will be
      generated.  These compare the class as if it were a tuple of its
      fields, in order.  Both instances in the comparison must be of the
      identical type.  If ``order`` is true and ``eq`` is false, a
      :exc:`ValueError` is raised.
 
-     If the class already defines any of :meth:`__lt__`,
-     :meth:`__le__`, :meth:`__gt__`, or :meth:`__ge__`, then
+     If the class already defines any of :meth:`~object.__lt__`,
+     :meth:`~object.__le__`, :meth:`~object.__gt__`, or :meth:`~object.__ge__`, then
      :exc:`TypeError` is raised.
 
-   - ``unsafe_hash``: If ``False`` (the default), a :meth:`__hash__` method
+   - ``unsafe_hash``: If ``False`` (the default), a :meth:`~object.__hash__` method
      is generated according to how ``eq`` and ``frozen`` are set.
 
-     :meth:`__hash__` is used by built-in :meth:`hash()`, and when objects are
+     :meth:`~object.__hash__` is used by built-in :meth:`hash()`, and when objects are
      added to hashed collections such as dictionaries and sets.  Having a
-     :meth:`__hash__` implies that instances of the class are immutable.
+     :meth:`~object.__hash__` implies that instances of the class are immutable.
      Mutability is a complicated property that depends on the programmer's
-     intent, the existence and behavior of :meth:`__eq__`, and the values of
+     intent, the existence and behavior of :meth:`~object.__eq__`, and the values of
      the ``eq`` and ``frozen`` flags in the :func:`dataclass` decorator.
 
-     By default, :func:`dataclass` will not implicitly add a :meth:`__hash__`
+     By default, :func:`dataclass` will not implicitly add a :meth:`~object.__hash__`
      method unless it is safe to do so.  Neither will it add or change an
-     existing explicitly defined :meth:`__hash__` method.  Setting the class
+     existing explicitly defined :meth:`~object.__hash__` method.  Setting the class
      attribute ``__hash__ = None`` has a specific meaning to Python, as
-     described in the :meth:`__hash__` documentation.
+     described in the :meth:`~object.__hash__` documentation.
 
-     If :meth:`__hash__` is not explicitly defined, or if it is set to ``None``,
-     then :func:`dataclass` *may* add an implicit :meth:`__hash__` method.
+     If :meth:`~object.__hash__` is not explicitly defined, or if it is set to ``None``,
+     then :func:`dataclass` *may* add an implicit :meth:`~object.__hash__` method.
      Although not recommended, you can force :func:`dataclass` to create a
-     :meth:`__hash__` method with ``unsafe_hash=True``. This might be the case
+     :meth:`~object.__hash__` method with ``unsafe_hash=True``. This might be the case
      if your class is logically immutable but can nonetheless be mutated.
      This is a specialized use case and should be considered carefully.
 
-     Here are the rules governing implicit creation of a :meth:`__hash__`
-     method.  Note that you cannot both have an explicit :meth:`__hash__`
+     Here are the rules governing implicit creation of a :meth:`~object.__hash__`
+     method.  Note that you cannot both have an explicit :meth:`~object.__hash__`
      method in your dataclass and set ``unsafe_hash=True``; this will result
      in a :exc:`TypeError`.
 
      If ``eq`` and ``frozen`` are both true, by default :func:`dataclass` will
-     generate a :meth:`__hash__` method for you.  If ``eq`` is true and
-     ``frozen`` is false, :meth:`__hash__` will be set to ``None``, marking it
+     generate a :meth:`~object.__hash__` method for you.  If ``eq`` is true and
+     ``frozen`` is false, :meth:`~object.__hash__` will be set to ``None``, marking it
      unhashable (which it is, since it is mutable).  If ``eq`` is false,
-     :meth:`__hash__` will be left untouched meaning the :meth:`__hash__`
+     :meth:`~object.__hash__` will be left untouched meaning the :meth:`~object.__hash__`
      method of the superclass will be used (if the superclass is
      :class:`object`, this means it will fall back to id-based hashing).
 
    - ``frozen``: If true (the default is ``False``), assigning to fields will
      generate an exception.  This emulates read-only frozen instances.  If
-     :meth:`__setattr__` or :meth:`__delattr__` is defined in the class, then
+     :meth:`~object.__setattr__` or :meth:`~object.__delattr__` is defined in the class, then
      :exc:`TypeError` is raised.  See the discussion below.
 
    - ``match_args``: If true (the default is ``True``), the
      ``__match_args__`` tuple will be created from the list of
-     parameters to the generated :meth:`__init__` method (even if
-     :meth:`__init__` is not generated, see above).  If false, or if
+     parameters to the generated :meth:`~object.__init__` method (even if
+     :meth:`~object.__init__` is not generated, see above).  If false, or if
      ``__match_args__`` is already defined in the class, then
      ``__match_args__`` will not be generated.
 
@@ -173,18 +173,18 @@ Module contents
 
    - ``kw_only``: If true (the default value is ``False``), then all
      fields will be marked as keyword-only.  If a field is marked as
-     keyword-only, then the only effect is that the :meth:`__init__`
+     keyword-only, then the only effect is that the :meth:`~object.__init__`
      parameter generated from a keyword-only field must be specified
-     with a keyword when :meth:`__init__` is called.  There is no
+     with a keyword when :meth:`~object.__init__` is called.  There is no
      effect on any other aspect of dataclasses.  See the
      :term:`parameter` glossary entry for details.  Also see the
      :const:`KW_ONLY` section.
 
     .. versionadded:: 3.10
 
-   - ``slots``: If true (the default is ``False``), :attr:`__slots__` attribute
+   - ``slots``: If true (the default is ``False``), :attr:`~object.__slots__` attribute
      will be generated and new class will be returned instead of the original one.
-     If :attr:`__slots__` is already defined in the class, then :exc:`TypeError`
+     If :attr:`~object.__slots__` is already defined in the class, then :exc:`TypeError`
      is raised.
 
     .. versionadded:: 3.10
@@ -215,7 +215,7 @@ Module contents
          b: int = 0   # assign a default value for 'b'
 
    In this example, both ``a`` and ``b`` will be included in the added
-   :meth:`__init__` method, which will be defined as::
+   :meth:`~object.__init__` method, which will be defined as::
 
      def __init__(self, a: int, b: int = 0):
 
@@ -256,13 +256,13 @@ Module contents
      error to specify both ``default`` and ``default_factory``.
 
    - ``init``: If true (the default), this field is included as a
-     parameter to the generated :meth:`__init__` method.
+     parameter to the generated :meth:`~object.__init__` method.
 
    - ``repr``: If true (the default), this field is included in the
-     string returned by the generated :meth:`__repr__` method.
+     string returned by the generated :meth:`~object.__repr__` method.
 
    - ``hash``: This can be a bool or ``None``.  If true, this field is
-     included in the generated :meth:`__hash__` method.  If ``None`` (the
+     included in the generated :meth:`~object.__hash__` method.  If ``None`` (the
      default), use the value of ``compare``: this would normally be
      the expected behavior.  A field should be considered in the hash
      if it's used for comparisons.  Setting this value to anything
@@ -275,8 +275,8 @@ Module contents
      is excluded from the hash, it will still be used for comparisons.
 
    - ``compare``: If true (the default), this field is included in the
-     generated equality and comparison methods (:meth:`__eq__`,
-     :meth:`__gt__`, et al.).
+     generated equality and comparison methods (:meth:`~object.__eq__`,
+     :meth:`~object.__gt__`, et al.).
 
    - ``metadata``: This can be a mapping or None. None is treated as
      an empty dict.  This value is wrapped in
@@ -287,7 +287,7 @@ Module contents
      namespace in the metadata.
 
    - ``kw_only``: If true, this field will be marked as keyword-only.
-     This is used when the generated :meth:`__init__` method's
+     This is used when the generated :meth:`~object.__init__` method's
      parameters are computed.
 
     .. versionadded:: 3.10
@@ -435,13 +435,13 @@ Module contents
    Class, raises :exc:`TypeError`.  If values in ``changes`` do not
    specify fields, raises :exc:`TypeError`.
 
-   The newly returned object is created by calling the :meth:`__init__`
+   The newly returned object is created by calling the :meth:`~object.__init__`
    method of the dataclass.  This ensures that
    :meth:`__post_init__`, if present, is also called.
 
    Init-only variables without default values, if any exist, must be
    specified on the call to :func:`replace` so that they can be passed to
-   :meth:`__init__` and :meth:`__post_init__`.
+   :meth:`~object.__init__` and :meth:`__post_init__`.
 
    It is an error for ``changes`` to contain any fields that are
    defined as having ``init=False``.  A :exc:`ValueError` will be raised
@@ -480,7 +480,7 @@ Module contents
    :const:`KW_ONLY` is otherwise completely ignored.  This includes the
    name of such a field.  By convention, a name of ``_`` is used for a
    :const:`KW_ONLY` field.  Keyword-only fields signify
-   :meth:`__init__` parameters that must be specified as keywords when
+   :meth:`~object.__init__` parameters that must be specified as keywords when
    the class is instantiated.
 
    In this example, the fields ``y`` and ``z`` will be marked as keyword-only fields::
@@ -501,35 +501,38 @@ Module contents
 
 .. exception:: FrozenInstanceError
 
-   Raised when an implicitly defined :meth:`__setattr__` or
-   :meth:`__delattr__` is called on a dataclass which was defined with
+   Raised when an implicitly defined :meth:`~object.__setattr__` or
+   :meth:`~object.__delattr__` is called on a dataclass which was defined with
    ``frozen=True``. It is a subclass of :exc:`AttributeError`.
 
+.. _post-init-processing:
+
 Post-init processing
 --------------------
 
-The generated :meth:`__init__` code will call a method named
-:meth:`__post_init__`, if :meth:`__post_init__` is defined on the
-class.  It will normally be called as ``self.__post_init__()``.
-However, if any ``InitVar`` fields are defined, they will also be
-passed to :meth:`__post_init__` in the order they were defined in the
-class.  If no :meth:`__init__` method is generated, then
-:meth:`__post_init__` will not automatically be called.
+.. function:: __post_init__()
 
-Among other uses, this allows for initializing field values that
-depend on one or more other fields.  For example::
+   When defined on the class, it will be called by the generated
+   :meth:`~object.__init__`, normally as ``self.__post_init__()``.
+   However, if any ``InitVar`` fields are defined, they will also be
+   passed to :meth:`__post_init__` in the order they were defined in the
+   class.  If no :meth:`~object.__init__` method is generated, then
+   :meth:`__post_init__` will not automatically be called.
 
-    @dataclass
-    class C:
-        a: float
-        b: float
-        c: float = field(init=False)
+   Among other uses, this allows for initializing field values that
+   depend on one or more other fields.  For example::
 
-        def __post_init__(self):
-            self.c = self.a + self.b
+     @dataclass
+     class C:
+         a: float
+         b: float
+         c: float = field(init=False)
+
+         def __post_init__(self):
+             self.c = self.a + self.b
 
-The :meth:`__init__` method generated by :func:`dataclass` does not call base
-class :meth:`__init__` methods. If the base class has an :meth:`__init__` method
+The :meth:`~object.__init__` method generated by :func:`dataclass` does not call base
+class :meth:`~object.__init__` methods. If the base class has an :meth:`~object.__init__` method
 that has to be called, it is common to call this method in a
 :meth:`__post_init__` method::
 
@@ -545,7 +548,7 @@ that has to be called, it is common to c
         def __post_init__(self):
             super().__init__(self.side, self.side)
 
-Note, however, that in general the dataclass-generated :meth:`__init__` methods
+Note, however, that in general the dataclass-generated :meth:`~object.__init__` methods
 don't need to be called, since the derived dataclass will take care of
 initializing all fields of any base class that is a dataclass itself.
 
@@ -573,7 +576,7 @@ if the type of a field is of type ``data
 is an ``InitVar``, it is considered a pseudo-field called an init-only
 field.  As it is not a true field, it is not returned by the
 module-level :func:`fields` function.  Init-only fields are added as
-parameters to the generated :meth:`__init__` method, and are passed to
+parameters to the generated :meth:`~object.__init__` method, and are passed to
 the optional :meth:`__post_init__` method.  They are not otherwise used
 by dataclasses.
 
@@ -601,12 +604,12 @@ Frozen instances
 It is not possible to create truly immutable Python objects.  However,
 by passing ``frozen=True`` to the :meth:`dataclass` decorator you can
 emulate immutability.  In that case, dataclasses will add
-:meth:`__setattr__` and :meth:`__delattr__` methods to the class.  These
+:meth:`~object.__setattr__` and :meth:`~object.__delattr__` methods to the class.  These
 methods will raise a :exc:`FrozenInstanceError` when invoked.
 
 There is a tiny performance penalty when using ``frozen=True``:
-:meth:`__init__` cannot use simple assignment to initialize fields, and
-must use :meth:`object.__setattr__`.
+:meth:`~object.__init__` cannot use simple assignment to initialize fields, and
+must use :meth:`~object.__setattr__`.
 
 Inheritance
 -----------
@@ -634,14 +637,14 @@ example::
 The final list of fields is, in order, ``x``, ``y``, ``z``.  The final
 type of ``x`` is ``int``, as specified in class ``C``.
 
-The generated :meth:`__init__` method for ``C`` will look like::
+The generated :meth:`~object.__init__` method for ``C`` will look like::
 
   def __init__(self, x: int = 15, y: int = 0, z: int = 10):
 
-Re-ordering of keyword-only parameters in :meth:`__init__`
-----------------------------------------------------------
+Re-ordering of keyword-only parameters in :meth:`~object.__init__`
+------------------------------------------------------------------
 
-After the parameters needed for :meth:`__init__` are computed, any
+After the parameters needed for :meth:`~object.__init__` are computed, any
 keyword-only parameters are moved to come after all regular
 (non-keyword-only) parameters.  This is a requirement of how
 keyword-only parameters are implemented in Python: they must come
@@ -662,7 +665,7 @@ fields, and ``Base.x`` and ``D.z`` are r
       z: int = 10
       t: int = field(kw_only=True, default=0)
 
-The generated :meth:`__init__` method for ``D`` will look like::
+The generated :meth:`~object.__init__` method for ``D`` will look like::
 
   def __init__(self, x: Any = 15.0, z: int = 10, *, y: int = 0, w: int = 1, t: int = 0):
 
@@ -671,7 +674,7 @@ the list of fields: parameters derived f
 followed by parameters derived from keyword-only fields.
 
 The relative ordering of keyword-only parameters is maintained in the
-re-ordered :meth:`__init__` parameter list.
+re-ordered :meth:`~object.__init__` parameter list.
 
 
 Default factory functions
@@ -683,10 +686,10 @@ example, to create a new instance of a l
 
   mylist: list = field(default_factory=list)
 
-If a field is excluded from :meth:`__init__` (using ``init=False``)
+If a field is excluded from :meth:`~object.__init__` (using ``init=False``)
 and the field also specifies ``default_factory``, then the default
 factory function will always be called from the generated
-:meth:`__init__` function.  This happens because there is no other
+:meth:`~object.__init__` function.  This happens because there is no other
 way to give the field an initial value.
 
 Mutable default values
@@ -714,7 +717,7 @@ Using dataclasses, *if* this code was va
 
   @dataclass
   class D:
-      x: List = []
+      x: list = []      # This code raises ValueError
       def add(self, element):
           self.x += element
 
diff -pruN 3.12.0~a7-1/Doc/library/datetime.rst 3.12.0~b1-1/Doc/library/datetime.rst
--- 3.12.0~a7-1/Doc/library/datetime.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/datetime.rst	2023-05-22 12:07:36.000000000 +0000
@@ -737,18 +737,16 @@ Instance methods:
 .. method:: date.strftime(format)
 
    Return a string representing the date, controlled by an explicit format string.
-   Format codes referring to hours, minutes or seconds will see 0 values. For a
-   complete list of formatting directives, see
-   :ref:`strftime-strptime-behavior`.
+   Format codes referring to hours, minutes or seconds will see 0 values.
+   See also :ref:`strftime-strptime-behavior` and :meth:`date.isoformat`.
 
 
 .. method:: date.__format__(format)
 
    Same as :meth:`.date.strftime`. This makes it possible to specify a format
    string for a :class:`.date` object in :ref:`formatted string
-   literals <f-strings>` and when using :meth:`str.format`. For a
-   complete list of formatting directives, see
-   :ref:`strftime-strptime-behavior`.
+   literals <f-strings>` and when using :meth:`str.format`.
+   See also :ref:`strftime-strptime-behavior` and :meth:`date.isoformat`.
 
 Examples of Usage: :class:`date`
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -898,6 +896,10 @@ Other constructors, all class methods:
       in UTC. As such, the recommended way to create an object representing the
       current time in UTC is by calling ``datetime.now(timezone.utc)``.
 
+   .. deprecated:: 3.12
+
+      Use :meth:`datetime.now` with :attr:`UTC` instead.
+
 
 .. classmethod:: datetime.fromtimestamp(timestamp, tz=None)
 
@@ -966,6 +968,10 @@ Other constructors, all class methods:
       :c:func:`gmtime` function. Raise :exc:`OSError` instead of
       :exc:`ValueError` on :c:func:`gmtime` failure.
 
+   .. deprecated:: 3.12
+
+      Use :meth:`datetime.fromtimestamp` with :attr:`UTC` instead.
+
 
 .. classmethod:: datetime.fromordinal(ordinal)
 
@@ -1045,14 +1051,14 @@ Other constructors, all class methods:
    Return a :class:`.datetime` corresponding to *date_string*, parsed according to
    *format*.
 
-   This is equivalent to::
+   If *format* does not contain microseconds or timezone information, this is equivalent to::
 
      datetime(*(time.strptime(date_string, format)[0:6]))
 
    :exc:`ValueError` is raised if the date_string and format
    can't be parsed by :func:`time.strptime` or if it returns a value which isn't a
-   time tuple. For a complete list of formatting directives, see
-   :ref:`strftime-strptime-behavior`.
+   time tuple.  See also :ref:`strftime-strptime-behavior` and
+   :meth:`datetime.fromisoformat`.
 
 
 
@@ -1510,20 +1516,21 @@ Instance methods:
    (which :func:`time.ctime` invokes, but which
    :meth:`datetime.ctime` does not invoke) conforms to the C standard.
 
+
 .. method:: datetime.strftime(format)
 
-   Return a string representing the date and time, controlled by an explicit format
-   string. For a complete list of formatting directives, see
-   :ref:`strftime-strptime-behavior`.
+   Return a string representing the date and time,
+   controlled by an explicit format string.
+   See also :ref:`strftime-strptime-behavior` and :meth:`datetime.isoformat`.
 
 
 .. method:: datetime.__format__(format)
 
    Same as :meth:`.datetime.strftime`. This makes it possible to specify a format
    string for a :class:`.datetime` object in :ref:`formatted string
-   literals <f-strings>` and when using :meth:`str.format`. For a
-   complete list of formatting directives, see
-   :ref:`strftime-strptime-behavior`.
+   literals <f-strings>` and when using :meth:`str.format`.
+   See also :ref:`strftime-strptime-behavior` and :meth:`datetime.isoformat`.
+
 
 Examples of Usage: :class:`.datetime`
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -1868,17 +1875,15 @@ Instance methods:
 .. method:: time.strftime(format)
 
    Return a string representing the time, controlled by an explicit format
-   string. For a complete list of formatting directives, see
-   :ref:`strftime-strptime-behavior`.
+   string.  See also :ref:`strftime-strptime-behavior` and :meth:`time.isoformat`.
 
 
 .. method:: time.__format__(format)
 
-   Same as :meth:`.time.strftime`. This makes it possible to specify a format string
-   for a :class:`.time` object in :ref:`formatted string
-   literals <f-strings>` and when using :meth:`str.format`. For a
-   complete list of formatting directives, see
-   :ref:`strftime-strptime-behavior`.
+   Same as :meth:`.time.strftime`. This makes it possible to specify
+   a format string for a :class:`.time` object in :ref:`formatted string
+   literals <f-strings>` and when using :meth:`str.format`.
+   See also :ref:`strftime-strptime-behavior` and :meth:`time.isoformat`.
 
 
 .. method:: time.utcoffset()
@@ -2320,6 +2325,14 @@ versus :meth:`strptime`:
 :meth:`strftime` and :meth:`strptime` Format Codes
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+These methods accept format codes that can be used to parse and format dates::
+
+   >>> datetime.strptime('31/01/22 23:59:59.999999',
+   ...                   '%d/%m/%y %H:%M:%S.%f')
+   datetime.datetime(2022, 1, 31, 23, 59, 59, 999999)
+   >>> _.strftime('%a %d %b %Y, %I:%M%p')
+   'Mon 31 Jan 2022, 11:59PM'
+
 The following is a list of all the format codes that the 1989 C standard
 requires, and these work on all platforms with a standard C implementation.
 
@@ -2505,10 +2518,7 @@ Notes:
    Because the format depends on the current locale, care should be taken when
    making assumptions about the output value. Field orderings will vary (for
    example, "month/day/year" versus "day/month/year"), and the output may
-   contain Unicode characters encoded using the locale's default encoding (for
-   example, if the current locale is ``ja_JP``, the default encoding could be
-   any one of ``eucJP``, ``SJIS``, or ``utf-8``; use :meth:`locale.getlocale`
-   to determine the current locale's encoding).
+   contain non-ASCII characters.
 
 (2)
    The :meth:`strptime` method can parse years in the full [1, 9999] range, but
diff -pruN 3.12.0~a7-1/Doc/library/decimal.rst 3.12.0~b1-1/Doc/library/decimal.rst
--- 3.12.0~a7-1/Doc/library/decimal.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/decimal.rst	2023-05-22 12:07:36.000000000 +0000
@@ -926,7 +926,7 @@ Each thread has its own current context
 You can also use the :keyword:`with` statement and the :func:`localcontext`
 function to temporarily change the active context.
 
-.. function:: localcontext(ctx=None, \*\*kwargs)
+.. function:: localcontext(ctx=None, **kwargs)
 
    Return a context manager that will set the current context for the active thread
    to a copy of *ctx* on entry to the with-statement and restore the previous context
diff -pruN 3.12.0~a7-1/Doc/library/dis.rst 3.12.0~b1-1/Doc/library/dis.rst
--- 3.12.0~a7-1/Doc/library/dis.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/dis.rst	2023-05-22 12:07:36.000000000 +0000
@@ -59,7 +59,7 @@ the following command can be used to dis
      3           2 LOAD_GLOBAL              1 (NULL + len)
                 12 LOAD_FAST                0 (alist)
                 14 CALL                     1
-                24 RETURN_VALUE
+                22 RETURN_VALUE
 
 (The "2" is a line number).
 
@@ -402,7 +402,7 @@ The Python compiler currently generates
 
 **General instructions**
 
-In the following, We will refer to the interpreter stack as STACK and describe
+In the following, We will refer to the interpreter stack as ``STACK`` and describe
 operations on it as if it was a Python list. The top of the stack corresponds to
 ``STACK[-1]`` in this language.
 
@@ -414,7 +414,7 @@ operations on it as if it was a Python l
 
 .. opcode:: POP_TOP
 
-   Removes the top-of-stack item.::
+   Removes the top-of-stack item::
 
       STACK.pop()
 
@@ -422,7 +422,7 @@ operations on it as if it was a Python l
 .. opcode:: END_FOR
 
    Removes the top two values from the stack.
-   Equivalent to POP_TOP; POP_TOP.
+   Equivalent to ``POP_TOP``; ``POP_TOP``.
    Used to clean up at the end of loops, hence the name.
 
    .. versionadded:: 3.12
@@ -431,7 +431,7 @@ operations on it as if it was a Python l
 .. opcode:: COPY (i)
 
    Push the i-th item to the top of the stack without removing it from its original
-   location.::
+   location::
 
       assert i > 0
       STACK.append(STACK[-i])
@@ -441,7 +441,7 @@ operations on it as if it was a Python l
 
 .. opcode:: SWAP (i)
 
-   Swap the top of the stack with the i-th element.::
+   Swap the top of the stack with the i-th element::
 
       STACK[-i], STACK[-1] = stack[-1], STACK[-i]
 
@@ -513,7 +513,7 @@ not have to be) the original ``STACK[-2]
 .. opcode:: BINARY_OP (op)
 
    Implements the binary and in-place operators (depending on the value of
-   *op*).::
+   *op*)::
 
       rhs = STACK.pop()
       lhs = STACK.pop()
@@ -580,14 +580,14 @@ not have to be) the original ``STACK[-2]
 
    Implements ``STACK[-1] = get_awaitable(STACK[-1])``, where ``get_awaitable(o)``
    returns ``o`` if ``o`` is a coroutine object or a generator object with
-   the CO_ITERABLE_COROUTINE flag, or resolves
+   the :data:`~inspect.CO_ITERABLE_COROUTINE` flag, or resolves
    ``o.__await__``.
 
     If the ``where`` operand is nonzero, it indicates where the instruction
     occurs:
 
-    * ``1`` After a call to ``__aenter__``
-    * ``2`` After a call to ``__aexit__``
+    * ``1``: After a call to ``__aenter__``
+    * ``2``: After a call to ``__aexit__``
 
    .. versionadded:: 3.5
 
@@ -622,8 +622,8 @@ not have to be) the original ``STACK[-2]
 
    .. versionadded:: 3.8
 
-    .. versionchanged:: 3.11
-       Exception representation on the stack now consist of one, not three, items.
+   .. versionchanged:: 3.11
+      Exception representation on the stack now consist of one, not three, items.
 
 
 .. opcode:: CLEANUP_THROW
@@ -652,6 +652,7 @@ not have to be) the original ``STACK[-2]
 .. opcode:: SET_ADD (i)
 
    Implements::
+
       item = STACK.pop()
       set.add(STACK[-i], item)
 
@@ -705,11 +706,11 @@ iterations of the loop.
 
    Yields ``STACK.pop()`` from a :term:`generator`.
 
-    .. versionchanged:: 3.11
-       oparg set to be the stack depth.
+   .. versionchanged:: 3.11
+      oparg set to be the stack depth.
 
-    .. versionchanged:: 3.12
-       oparg set to be the exception block depth, for efficient closing of generators.
+   .. versionchanged:: 3.12
+      oparg set to be the exception block depth, for efficient closing of generators.
 
 
 .. opcode:: SETUP_ANNOTATIONS
@@ -726,32 +727,32 @@ iterations of the loop.
 
    Pops a value from the stack, which is used to restore the exception state.
 
-    .. versionchanged:: 3.11
-       Exception representation on the stack now consist of one, not three, items.
+   .. versionchanged:: 3.11
+      Exception representation on the stack now consist of one, not three, items.
 
 .. opcode:: RERAISE
 
-    Re-raises the exception currently on top of the stack. If oparg is non-zero,
-    pops an additional value from the stack which is used to set ``f_lasti``
-    of the current frame.
+   Re-raises the exception currently on top of the stack. If oparg is non-zero,
+   pops an additional value from the stack which is used to set ``f_lasti``
+   of the current frame.
 
-    .. versionadded:: 3.9
+   .. versionadded:: 3.9
 
-    .. versionchanged:: 3.11
-       Exception representation on the stack now consist of one, not three, items.
+   .. versionchanged:: 3.11
+      Exception representation on the stack now consist of one, not three, items.
 
 .. opcode:: PUSH_EXC_INFO
 
-    Pops a value from the stack. Pushes the current exception to the top of the stack.
-    Pushes the value originally popped back to the stack.
-    Used in exception handlers.
+   Pops a value from the stack. Pushes the current exception to the top of the stack.
+   Pushes the value originally popped back to the stack.
+   Used in exception handlers.
 
-    .. versionadded:: 3.11
+   .. versionadded:: 3.11
 
 .. opcode:: CHECK_EXC_MATCH
 
    Performs exception matching for ``except``. Tests whether the ``STACK[-2]``
-   is an exception matching ``STACK[-1]``. Pops STACK[-1] and pushes the boolean
+   is an exception matching ``STACK[-1]``. Pops ``STACK[-1]`` and pushes the boolean
    result of the test.
 
    .. versionadded:: 3.11
@@ -770,16 +771,16 @@ iterations of the loop.
 
 .. opcode:: WITH_EXCEPT_START
 
-    Calls the function in position 4 on the stack with arguments (type, val, tb)
-    representing the exception at the top of the stack.
-    Used to implement the call ``context_manager.__exit__(*exc_info())`` when an exception
-    has occurred in a :keyword:`with` statement.
-
-    .. versionadded:: 3.9
-
-    .. versionchanged:: 3.11
-       The ``__exit__`` function is in position 4 of the stack rather than 7.
-       Exception representation on the stack now consist of one, not three, items.
+   Calls the function in position 4 on the stack with arguments (type, val, tb)
+   representing the exception at the top of the stack.
+   Used to implement the call ``context_manager.__exit__(*exc_info())`` when an exception
+   has occurred in a :keyword:`with` statement.
+
+   .. versionadded:: 3.9
+
+   .. versionchanged:: 3.11
+      The ``__exit__`` function is in position 4 of the stack rather than 7.
+      Exception representation on the stack now consist of one, not three, items.
 
 
 .. opcode:: LOAD_ASSERTION_ERROR
@@ -863,7 +864,7 @@ iterations of the loop.
 .. opcode:: UNPACK_SEQUENCE (count)
 
    Unpacks ``STACK[-1]`` into *count* individual values, which are put onto the stack
-   right-to-left.::
+   right-to-left::
 
       STACK.extend(STACK.pop()[:count:-1])
 
@@ -1028,7 +1029,7 @@ iterations of the loop.
    This bytecode distinguishes two cases: if ``STACK[-1]`` has a method with the
    correct name, the bytecode pushes the unbound method and ``STACK[-1]``.
    ``STACK[-1]`` will be used as the first argument (``self``) by :opcode:`CALL`
-   when calling the unbound method. Otherwise, ``NULL`` and the object return by
+   when calling the unbound method. Otherwise, ``NULL`` and the object returned by
    the attribute lookup are pushed.
 
    .. versionchanged:: 3.12
@@ -1036,6 +1037,24 @@ iterations of the loop.
       pushed to the stack before the attribute or unbound method respectively.
 
 
+.. opcode:: LOAD_SUPER_ATTR (namei)
+
+   This opcode implements :func:`super` (e.g. ``super().method()`` and
+   ``super().attr``). It works the same as :opcode:`LOAD_ATTR`, except that
+   ``namei`` is shifted left by 2 bits instead of 1, and instead of expecting a
+   single receiver on the stack, it expects three objects (from top of stack
+   down): ``self`` (the first argument to the current method), ``cls`` (the
+   class within which the current method was defined), and the global ``super``.
+
+   The low bit of ``namei`` signals to attempt a method load, as with
+   :opcode:`LOAD_ATTR`.
+
+   The second-low bit of ``namei``, if set, means that this was a two-argument
+   call to :func:`super` (unset means zero-argument).
+
+   .. versionadded:: 3.12
+
+
 .. opcode:: COMPARE_OP (opname)
 
    Performs a Boolean operation.  The operation name can be found in
@@ -1177,6 +1196,14 @@ iterations of the loop.
 
    .. versionadded:: 3.12
 
+.. opcode:: LOAD_FAST_AND_CLEAR (var_num)
+
+   Pushes a reference to the local ``co_varnames[var_num]`` onto the stack (or
+   pushes ``NULL`` onto the stack if the local variable has not been
+   initialized) and sets ``co_varnames[var_num]`` to ``NULL``.
+
+   .. versionadded:: 3.12
+
 .. opcode:: STORE_FAST (var_num)
 
    Stores ``STACK.pop()`` into the local ``co_varnames[var_num]``.
@@ -1189,7 +1216,7 @@ iterations of the loop.
 
 .. opcode:: MAKE_CELL (i)
 
-   Creates a new cell in slot ``i``.  If that slot is empty then
+   Creates a new cell in slot ``i``.  If that slot is nonempty then
    that value is stored into the new cell.
 
    .. versionadded:: 3.11
@@ -1314,9 +1341,9 @@ iterations of the loop.
 
 .. opcode:: PUSH_NULL
 
-    Pushes a ``NULL`` to the stack.
-    Used in the call sequence to match the ``NULL`` pushed by
-    :opcode:`LOAD_METHOD` for non-method calls.
+   Pushes a ``NULL`` to the stack.
+   Used in the call sequence to match the ``NULL`` pushed by
+   :opcode:`LOAD_METHOD` for non-method calls.
 
    .. versionadded:: 3.11
 
@@ -1348,7 +1375,7 @@ iterations of the loop.
 
 .. opcode:: BUILD_SLICE (argc)
 
-   .. index:: builtin: slice
+   .. index:: pair: built-in function; slice
 
    Pushes a slice object on the stack.  *argc* must be 2 or 3.  If it is 2, implements::
 
@@ -1416,38 +1443,38 @@ iterations of the loop.
 
 .. opcode:: RESUME (where)
 
-    A no-op. Performs internal tracing, debugging and optimization checks.
+   A no-op. Performs internal tracing, debugging and optimization checks.
 
-    The ``where`` operand marks where the ``RESUME`` occurs:
+   The ``where`` operand marks where the ``RESUME`` occurs:
 
-    * ``0`` The start of a function, which is neither a generator, coroutine
-      nor an async generator
-    * ``1`` After a ``yield`` expression
-    * ``2`` After a ``yield from`` expression
-    * ``3`` After an ``await`` expression
+   * ``0`` The start of a function, which is neither a generator, coroutine
+     nor an async generator
+   * ``1`` After a ``yield`` expression
+   * ``2`` After a ``yield from`` expression
+   * ``3`` After an ``await`` expression
 
    .. versionadded:: 3.11
 
 
 .. opcode:: RETURN_GENERATOR
 
-    Create a generator, coroutine, or async generator from the current frame.
-    Used as first opcode of in code object for the above mentioned callables.
-    Clear the current frame and return the newly created generator.
+   Create a generator, coroutine, or async generator from the current frame.
+   Used as first opcode of in code object for the above mentioned callables.
+   Clear the current frame and return the newly created generator.
 
-    .. versionadded:: 3.11
+   .. versionadded:: 3.11
 
 
 .. opcode:: SEND (delta)
 
-    Equivalent to ``STACK[-1] = STACK[-2].send(STACK[-1])``. Used in ``yield from``
-    and ``await`` statements.
+   Equivalent to ``STACK[-1] = STACK[-2].send(STACK[-1])``. Used in ``yield from``
+   and ``await`` statements.
 
-    If the call raises :exc:`StopIteration`, pop both items, push the
-    exception's ``value`` attribute, and increment the bytecode counter by
-    *delta*.
+   If the call raises :exc:`StopIteration`, pop both items, push the
+   exception's ``value`` attribute, and increment the bytecode counter by
+   *delta*.
 
-    .. versionadded:: 3.11
+   .. versionadded:: 3.11
 
 
 .. opcode:: HAVE_ARGUMENT
@@ -1475,15 +1502,15 @@ iterations of the loop.
    argument and sets ``STACK[-1]`` to the result. Used to implement
    functionality that is necessary but not performance critical.
 
-    The operand determines which intrinsic function is called:
+   The operand determines which intrinsic function is called:
 
-    * ``0`` Not valid
-    * ``1`` Prints the argument to standard out. Used in the REPL.
-    * ``2`` Performs ``import *`` for the named module.
-    * ``3`` Extracts the return value from a ``StopIteration`` exception.
-    * ``4`` Wraps an aync generator value
-    * ``5`` Performs the unary ``+`` operation
-    * ``6`` Converts a list to a tuple
+   * ``0`` Not valid
+   * ``1`` Prints the argument to standard out. Used in the REPL.
+   * ``2`` Performs ``import *`` for the named module.
+   * ``3`` Extracts the return value from a ``StopIteration`` exception.
+   * ``4`` Wraps an aync generator value
+   * ``5`` Performs the unary ``+`` operation
+   * ``6`` Converts a list to a tuple
 
    .. versionadded:: 3.12
 
@@ -1493,17 +1520,17 @@ iterations of the loop.
    arguments and sets ``STACK[-1]`` to the result. Used to implement functionality that is
    necessary but not performance critical.
 
-    The operand determines which intrinsic function is called:
+   The operand determines which intrinsic function is called:
 
-    * ``0`` Not valid
-    * ``1`` Calculates the :exc:`ExceptionGroup` to raise from a ``try-except*``.
+   * ``0`` Not valid
+   * ``1`` Calculates the :exc:`ExceptionGroup` to raise from a ``try-except*``.
 
    .. versionadded:: 3.12
 
 
 **Pseudo-instructions**
 
-These opcodes do not appear in python bytecode, they are used by the compiler
+These opcodes do not appear in Python bytecode. They are used by the compiler
 but are replaced by real opcodes or removed before bytecode is generated.
 
 .. opcode:: SETUP_FINALLY (target)
@@ -1515,7 +1542,7 @@ but are replaced by real opcodes or remo
 
 .. opcode:: SETUP_CLEANUP (target)
 
-   Like ``SETUP_FINALLY``, but in case of exception also pushes the last
+   Like ``SETUP_FINALLY``, but in case of an exception also pushes the last
    instruction (``lasti``) to the stack so that ``RERAISE`` can restore it.
    If an exception occurs, the value stack level and the last instruction on
    the frame are restored to their current state, and control is transferred
@@ -1524,7 +1551,7 @@ but are replaced by real opcodes or remo
 
 .. opcode:: SETUP_WITH (target)
 
-   Like ``SETUP_CLEANUP``, but in case of exception one more item is popped
+   Like ``SETUP_CLEANUP``, but in case of an exception one more item is popped
    from the stack before control is transferred to the exception handler at
    ``target``.
 
@@ -1558,9 +1585,9 @@ Opcode collections
 These collections are provided for automatic introspection of bytecode
 instructions:
 
-   .. versionchanged:: 3.12
-      The collections now contain pseudo instructions as well. These are
-      opcodes with values ``>= MIN_PSEUDO_OPCODE``.
+.. versionchanged:: 3.12
+   The collections now contain pseudo instructions as well. These are
+   opcodes with values ``>= MIN_PSEUDO_OPCODE``.
 
 .. data:: opname
 
@@ -1581,7 +1608,7 @@ instructions:
 
    Sequence of bytecodes that use their argument.
 
-    .. versionadded:: 3.12
+   .. versionadded:: 3.12
 
 
 .. data:: hasconst
@@ -1591,10 +1618,10 @@ instructions:
 
 .. data:: hasfree
 
-   Sequence of bytecodes that access a free variable (note that 'free' in this
+   Sequence of bytecodes that access a free variable. 'free' in this
    context refers to names in the current scope that are referenced by inner
    scopes or names in outer scopes that are referenced from this scope.  It does
-   *not* include references to global or builtin scopes).
+   *not* include references to global or builtin scopes.
 
 
 .. data:: hasname
@@ -1625,4 +1652,4 @@ instructions:
 
    Sequence of bytecodes that set an exception handler.
 
-    .. versionadded:: 3.12
+   .. versionadded:: 3.12
diff -pruN 3.12.0~a7-1/Doc/library/enum.rst 3.12.0~b1-1/Doc/library/enum.rst
--- 3.12.0~a7-1/Doc/library/enum.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/enum.rst	2023-05-22 12:07:36.000000000 +0000
@@ -119,7 +119,8 @@ Module Contents
    :func:`~enum.property`
 
       Allows :class:`Enum` members to have attributes without conflicting with
-      member names.
+      member names.  The ``value`` and ``name`` attributes are implemented this
+      way.
 
    :func:`unique`
 
@@ -169,7 +170,7 @@ Data Types
    final *enum*, as well as creating the enum members, properly handling
    duplicates, providing iteration over the enum class, etc.
 
-   .. method:: EnumType.__call__(cls, value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)
+   .. method:: EnumType.__call__(cls, value, names=None, \*, module=None, qualname=None, type=None, start=1, boundary=None)
 
       This method is called in two different ways:
 
@@ -317,7 +318,7 @@ Data Types
          >>> PowersOfThree.SECOND.value
          9
 
-   .. method:: Enum.__init_subclass__(cls, **kwds)
+   .. method:: Enum.__init_subclass__(cls, \**kwds)
 
       A *classmethod* that is used to further configure subsequent subclasses.
       By default, does nothing.
@@ -405,18 +406,18 @@ Data Types
    with an *IntEnum* member, the resulting value loses its enumeration status.
 
       >>> from enum import IntEnum
-      >>> class Numbers(IntEnum):
+      >>> class Number(IntEnum):
       ...     ONE = 1
       ...     TWO = 2
       ...     THREE = 3
       ...
-      >>> Numbers.THREE
-      <Numbers.THREE: 3>
-      >>> Numbers.ONE + Numbers.TWO
+      >>> Number.THREE
+      <Number.THREE: 3>
+      >>> Number.ONE + Number.TWO
       3
-      >>> Numbers.THREE + 5
+      >>> Number.THREE + 5
       8
-      >>> Numbers.THREE == 3
+      >>> Number.THREE == 3
       True
 
    .. note::
@@ -696,7 +697,8 @@ Data Types
 
    .. attribute:: STRICT
 
-      Out-of-range values cause a :exc:`ValueError` to be raised::
+      Out-of-range values cause a :exc:`ValueError` to be raised. This is the
+      default for :class:`Flag`::
 
          >>> from enum import Flag, STRICT, auto
          >>> class StrictFlag(Flag, boundary=STRICT):
@@ -714,7 +716,7 @@ Data Types
    .. attribute:: CONFORM
 
       Out-of-range values have invalid values removed, leaving a valid *Flag*
-      value. This is the default for :class:`Flag`::
+      value::
 
          >>> from enum import Flag, CONFORM, auto
          >>> class ConformFlag(Flag, boundary=CONFORM):
diff -pruN 3.12.0~a7-1/Doc/library/exceptions.rst 3.12.0~b1-1/Doc/library/exceptions.rst
--- 3.12.0~a7-1/Doc/library/exceptions.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/exceptions.rst	2023-05-22 12:07:36.000000000 +0000
@@ -4,8 +4,8 @@ Built-in Exceptions
 ===================
 
 .. index::
-   statement: try
-   statement: except
+   pair: statement; try
+   pair: statement; except
 
 In Python, all exceptions must be instances of a class that derives from
 :class:`BaseException`.  In a :keyword:`try` statement with an :keyword:`except`
@@ -14,7 +14,7 @@ classes derived from that class (but not
 derived).  Two exception classes that are not related via subclassing are never
 equivalent, even if they have the same name.
 
-.. index:: statement: raise
+.. index:: pair: statement; raise
 
 The built-in exceptions listed below can be generated by the interpreter or
 built-in functions.  Except where mentioned, they have an "associated value"
@@ -175,7 +175,7 @@ The following exceptions are the excepti
 
 .. exception:: AssertionError
 
-   .. index:: statement: assert
+   .. index:: pair: statement; assert
 
    Raised when an :keyword:`assert` statement fails.
 
@@ -318,7 +318,7 @@ The following exceptions are the excepti
 .. exception:: OSError([arg])
                OSError(errno, strerror[, filename[, winerror[, filename2]]])
 
-   .. index:: module: errno
+   .. index:: pair: module; errno
 
    This exception is raised when a system function returns a system-related
    error, including I/O failures such as "file not found" or "disk full"
diff -pruN 3.12.0~a7-1/Doc/library/fnmatch.rst 3.12.0~b1-1/Doc/library/fnmatch.rst
--- 3.12.0~a7-1/Doc/library/fnmatch.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/fnmatch.rst	2023-05-22 12:07:36.000000000 +0000
@@ -8,7 +8,7 @@
 
 .. index:: single: filenames; wildcard expansion
 
-.. index:: module: re
+.. index:: pair: module; re
 
 --------------
 
@@ -38,7 +38,7 @@ special characters used in shell-style w
 For a literal match, wrap the meta-characters in brackets.
 For example, ``'[?]'`` matches the character ``'?'``.
 
-.. index:: module: glob
+.. index:: pair: module; glob
 
 Note that the filename separator (``'/'`` on Unix) is *not* special to this
 module.  See module :mod:`glob` for pathname expansion (:mod:`glob` uses
diff -pruN 3.12.0~a7-1/Doc/library/functions.rst 3.12.0~b1-1/Doc/library/functions.rst
--- 3.12.0~a7-1/Doc/library/functions.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/functions.rst	2023-05-22 12:07:36.000000000 +0000
@@ -147,7 +147,7 @@ are always available.  They are listed h
    or omitted, this returns ``False``; otherwise, it returns ``True``.  The
    :class:`bool` class is a subclass of :class:`int` (see :ref:`typesnumeric`).
    It cannot be subclassed further.  Its only instances are ``False`` and
-   ``True`` (see :ref:`bltin-boolean-values`).
+   ``True`` (see :ref:`typebool`).
 
    .. index:: pair: Boolean; type
 
@@ -168,6 +168,13 @@ are always available.  They are listed h
    If :func:`sys.breakpointhook` is not accessible, this function will
    raise :exc:`RuntimeError`.
 
+   By default, the behavior of :func:`breakpoint` can be changed with
+   the :envvar:`PYTHONBREAKPOINT` environment variable.
+   See :func:`sys.breakpointhook` for usage details.
+
+   Note that this is not guaranteed if :func:`sys.breakpointhook`
+   has been replaced.
+
    .. audit-event:: builtins.breakpoint breakpointhook breakpoint
 
    .. versionadded:: 3.7
@@ -562,7 +569,7 @@ are always available.  They are listed h
       Raises an :ref:`auditing event <auditing>` ``exec`` with the code object
       as the argument. Code compilation events may also be raised.
 
-.. index:: builtin: exec
+.. index:: pair: built-in function; exec
 
 .. function:: exec(object, globals=None, locals=None, /, *, closure=None)
 
@@ -1340,7 +1347,7 @@ are always available.  They are listed h
       single: I/O control; buffering
       single: binary mode
       single: text mode
-      module: sys
+      pair: module; sys
 
    See also the file handling modules, such as :mod:`fileinput`, :mod:`io`
    (where :func:`open` is declared), :mod:`os`, :mod:`os.path`, :mod:`tempfile`,
@@ -1444,8 +1451,9 @@ are always available.  They are listed h
    arguments are converted to text strings, :func:`print` cannot be used with
    binary mode file objects.  For these, use ``file.write(...)`` instead.
 
-   Whether the output is buffered is usually determined by *file*, but if the
-   *flush* keyword argument is true, the stream is forcibly flushed.
+   Output buffering is usually determined by *file*.
+   However, if *flush* is true, the stream is forcibly flushed.
+
 
    .. versionchanged:: 3.3
       Added the *flush* keyword argument.
@@ -1680,7 +1688,7 @@ are always available.  They are listed h
 
       class C:
           @staticmethod
-          def f(arg1, arg2, ...): ...
+          def f(arg1, arg2, argN): ...
 
    The ``@staticmethod`` form is a function :term:`decorator` -- see
    :ref:`function` for details.
@@ -1829,7 +1837,7 @@ are always available.  They are listed h
 .. class:: type(object)
            type(name, bases, dict, **kwds)
 
-   .. index:: object: type
+   .. index:: pair: object; type
 
    With one argument, return the type of an *object*.  The return value is a
    type object and generally the same object as returned by
@@ -1985,8 +1993,8 @@ are always available.  They are listed h
 .. function:: __import__(name, globals=None, locals=None, fromlist=(), level=0)
 
    .. index::
-      statement: import
-      module: imp
+      pair: statement; import
+      pair: module; builtins
 
    .. note::
 
diff -pruN 3.12.0~a7-1/Doc/library/functools.rst 3.12.0~b1-1/Doc/library/functools.rst
--- 3.12.0~a7-1/Doc/library/functools.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/functools.rst	2023-05-22 12:07:36.000000000 +0000
@@ -49,8 +49,13 @@ The :mod:`functools` module defines the
         >>> factorial(12)      # makes two new recursive calls, the other 10 are cached
         479001600
 
-   The cache is threadsafe so the wrapped function can be used in multiple
-   threads.
+   The cache is threadsafe so that the wrapped function can be used in
+   multiple threads.  This means that the underlying data structure will
+   remain coherent during concurrent updates.
+
+   It is possible for the wrapped function to be called more than once if
+   another thread makes an additional call before the initial call has been
+   completed and cached.
 
    .. versionadded:: 3.9
 
@@ -105,19 +110,12 @@ The :mod:`functools` module defines the
    ``__slots__`` without including ``__dict__`` as one of the defined slots
    (as such classes don't provide a ``__dict__`` attribute at all).
 
-   If a mutable mapping is not available or if space-efficient key sharing
-   is desired, an effect similar to :func:`cached_property` can be achieved
-   by a stacking :func:`property` on top of :func:`cache`::
-
-       class DataSet:
-           def __init__(self, sequence_of_numbers):
-               self._data = sequence_of_numbers
-
-           @property
-           @cache
-           def stdev(self):
-               return statistics.stdev(self._data)
+   If a mutable mapping is not available or if space-efficient key sharing is
+   desired, an effect similar to :func:`cached_property` can also be achieved by
+   stacking :func:`property` on top of :func:`lru_cache`. See
+   :ref:`faq-cache-method-calls` for more details on how this differs from :func:`cached_property`.
 
+   .. versionadded:: 3.8
 
    .. versionchanged:: 3.12
       Prior to Python 3.12, ``cached_property`` included an undocumented lock to
@@ -126,8 +124,6 @@ The :mod:`functools` module defines the
       per-instance, which could result in unacceptably high lock contention. In
       Python 3.12+ this locking is removed.
 
-   .. versionadded:: 3.8
-
 
 .. function:: cmp_to_key(func)
 
@@ -159,8 +155,13 @@ The :mod:`functools` module defines the
    *maxsize* most recent calls.  It can save time when an expensive or I/O bound
    function is periodically called with the same arguments.
 
-   The cache is threadsafe so the wrapped function can be used in multiple
-   threads.
+   The cache is threadsafe so that the wrapped function can be used in
+   multiple threads.  This means that the underlying data structure will
+   remain coherent during concurrent updates.
+
+   It is possible for the wrapped function to be called more than once if
+   another thread makes an additional call before the initial call has been
+   completed and cached.
 
    Since a dictionary is used to cache results, the positional and keyword
    arguments to the function must be :term:`hashable`.
@@ -233,7 +234,7 @@ The :mod:`functools` module defines the
         @lru_cache(maxsize=32)
         def get_pep(num):
             'Retrieve text of a Python Enhancement Proposal'
-            resource = 'https://peps.python.org/pep-%04d/' % num
+            resource = f'https://peps.python.org/pep-{num:04d}'
             try:
                 with urllib.request.urlopen(resource) as s:
                     return s.read()
diff -pruN 3.12.0~a7-1/Doc/library/gc.rst 3.12.0~b1-1/Doc/library/gc.rst
--- 3.12.0~a7-1/Doc/library/gc.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/gc.rst	2023-05-22 12:07:36.000000000 +0000
@@ -50,6 +50,9 @@ The :mod:`gc` module provides the follow
    is run.  Not all items in some free lists may be freed due to the
    particular implementation, in particular :class:`float`.
 
+   The effect of calling ``gc.collect()`` while the interpreter is already
+   performing a collection is undefined.
+
 
 .. function:: set_debug(flags)
 
@@ -206,12 +209,17 @@ The :mod:`gc` module provides the follow
 
 .. function:: freeze()
 
-   Freeze all the objects tracked by gc - move them to a permanent generation
-   and ignore all the future collections. This can be used before a POSIX
-   fork() call to make the gc copy-on-write friendly or to speed up collection.
-   Also collection before a POSIX fork() call may free pages for future
-   allocation which can cause copy-on-write too so it's advised to disable gc
-   in parent process and freeze before fork and enable gc in child process.
+   Freeze all the objects tracked by the garbage collector; move them to a
+   permanent generation and ignore them in all the future collections.
+
+   If a process will ``fork()`` without ``exec()``, avoiding unnecessary
+   copy-on-write in child processes will maximize memory sharing and reduce
+   overall memory usage. This requires both avoiding creation of freed "holes"
+   in memory pages in the parent process and ensuring that GC collections in
+   child processes won't touch the ``gc_refs`` counter of long-lived objects
+   originating in the parent process. To accomplish both, call ``gc.disable()``
+   early in the parent process, ``gc.freeze()`` right before ``fork()``, and
+   ``gc.enable()`` early in child processes.
 
    .. versionadded:: 3.7
 
diff -pruN 3.12.0~a7-1/Doc/library/hashlib.rst 3.12.0~b1-1/Doc/library/hashlib.rst
--- 3.12.0~a7-1/Doc/library/hashlib.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/hashlib.rst	2023-05-22 12:07:36.000000000 +0000
@@ -430,9 +430,10 @@ Constructor functions also accept the fo
 
 .. figure:: hashlib-blake2-tree.png
    :alt: Explanation of tree mode parameters.
+   :class: invert-in-dark-mode
 
 See section 2.10 in `BLAKE2 specification
-<https://blake2.net/blake2_20130129.pdf>`_ for comprehensive review of tree
+<https://www.blake2.net/blake2_20130129.pdf>`_ for comprehensive review of tree
 hashing.
 
 
@@ -619,7 +620,7 @@ on the hash function used in digital sig
     by the signer.
 
     (`NIST SP-800-106 "Randomized Hashing for Digital Signatures"
-    <https://csrc.nist.gov/publications/detail/sp/800-106/final>`_)
+    <https://csrc.nist.gov/publications/detail/sp/800-106/archive/2009-02-25>`_)
 
 In BLAKE2 the salt is processed as a one-time input to the hash function during
 initialization, rather than as an input to each compression function.
@@ -628,7 +629,7 @@ initialization, rather than as an input
 
     *Salted hashing* (or just hashing) with BLAKE2 or any other general-purpose
     cryptographic hash function, such as SHA-256, is not suitable for hashing
-    passwords.  See `BLAKE2 FAQ <https://blake2.net/#qa>`_ for more
+    passwords.  See `BLAKE2 FAQ <https://www.blake2.net/#qa>`_ for more
     information.
 ..
 
@@ -764,9 +765,9 @@ Domain Dedication 1.0 Universal:
 
 * *Alexandr Sokolovskiy*
 
-.. _BLAKE2: https://blake2.net
+.. _BLAKE2: https://www.blake2.net
 .. _HMAC: https://en.wikipedia.org/wiki/Hash-based_message_authentication_code
-.. _BLAKE: https://131002.net/blake/
+.. _BLAKE: https://web.archive.org/web/20200918190133/https://131002.net/blake/
 .. _SHA-3: https://en.wikipedia.org/wiki/NIST_hash_function_competition
 .. _ChaCha: https://cr.yp.to/chacha.html
 .. _pyblake2: https://pythonhosted.org/pyblake2/
@@ -782,7 +783,7 @@ Domain Dedication 1.0 Universal:
    Module :mod:`base64`
       Another way to encode binary hashes for non-binary environments.
 
-   https://blake2.net
+   https://www.blake2.net
       Official BLAKE2 website.
 
    https://csrc.nist.gov/csrc/media/publications/fips/180/2/archive/2002-08-01/documents/fips180-2.pdf
diff -pruN 3.12.0~a7-1/Doc/library/http.client.rst 3.12.0~b1-1/Doc/library/http.client.rst
--- 3.12.0~a7-1/Doc/library/http.client.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/http.client.rst	2023-05-22 12:07:36.000000000 +0000
@@ -10,7 +10,7 @@
    pair: HTTP; protocol
    single: HTTP; http.client (standard module)
 
-.. index:: module: urllib.request
+.. index:: pair: module; urllib.request
 
 --------------
 
@@ -264,7 +264,10 @@ HTTPConnection Objects
             encode_chunked=False)
 
    This will send a request to the server using the HTTP request
-   method *method* and the selector *url*.
+   method *method* and the request URI *url*. The provided *url* must be
+   an absolute path to conform with :rfc:`RFC 2616 §5.1.2 <2616#section-5.1.2>`
+   (unless connecting to an HTTP proxy server or using the ``OPTIONS`` or
+   ``CONNECT`` methods).
 
    If *body* is specified, the specified data is sent after the headers are
    finished.  It may be a :class:`str`, a :term:`bytes-like object`, an
@@ -279,7 +282,10 @@ HTTPConnection Objects
    iterable are sent as is until the iterable is exhausted.
 
    The *headers* argument should be a mapping of extra HTTP headers to send
-   with the request.
+   with the request. A :rfc:`Host header <2616#section-14.23>`
+   must be provided to conform with :rfc:`RFC 2616 §5.1.2 <2616#section-5.1.2>`
+   (unless connecting to an HTTP proxy server or using the ``OPTIONS`` or
+   ``CONNECT`` methods).
 
    If *headers* contains neither Content-Length nor Transfer-Encoding,
    but there is a request body, one of those
@@ -298,6 +304,16 @@ HTTPConnection Objects
    HTTPConnection object assumes that all encoding is handled by the
    calling code.  If it is ``True``, the body will be chunk-encoded.
 
+   For example, to perform a ``GET`` request to ``https://docs.python.org/3/``::
+
+      >>> import http.client
+      >>> host = "docs.python.org"
+      >>> conn = http.client.HTTPSConnection(host)
+      >>> conn.request("GET", "/3/", headers={"Host": host})
+      >>> response = conn.getresponse()
+      >>> print(response.status, response.reason)
+      200 OK
+
    .. note::
       Chunked transfer encoding has been added to the HTTP protocol
       version 1.1.  Unless the HTTP server is known to handle HTTP 1.1,
@@ -353,6 +369,13 @@ HTTPConnection Objects
    The *headers* argument should be a mapping of extra HTTP headers to send with
    the CONNECT request.
 
+   As HTTP/1.1 is used for HTTP CONNECT tunnelling request, `as per the RFC
+   <https://datatracker.ietf.org/doc/html/rfc7231#section-4.3.6>`_, a HTTP ``Host:``
+   header must be provided, matching the authority-form of the request target
+   provided as the destination for the CONNECT request. If a HTTP ``Host:``
+   header is not provided via the headers argument, one is generated and
+   transmitted automatically.
+
    For example, to tunnel through a HTTPS proxy server running locally on port
    8080, we would pass the address of the proxy to the :class:`HTTPSConnection`
    constructor, and the address of the host that we eventually want to reach to
@@ -365,6 +388,22 @@ HTTPConnection Objects
 
    .. versionadded:: 3.2
 
+   .. versionchanged:: 3.12
+      HTTP CONNECT tunnelling requests use protocol HTTP/1.1, upgraded from
+      protocol HTTP/1.0. ``Host:`` HTTP headers are mandatory for HTTP/1.1, so
+      one will be automatically generated and transmitted if not provided in
+      the headers argument.
+
+
+.. method:: HTTPConnection.get_proxy_response_headers()
+
+   Returns a dictionary with the headers of the response received from
+   the proxy server to the CONNECT request.
+
+   If the CONNECT request was not sent, the method returns an empty dictionary.
+
+   .. versionadded:: 3.12
+
 
 .. method:: HTTPConnection.connect()
 
diff -pruN 3.12.0~a7-1/Doc/library/imp.rst 3.12.0~b1-1/Doc/library/imp.rst
--- 3.12.0~a7-1/Doc/library/imp.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/imp.rst	1970-01-01 00:00:00.000000000 +0000
@@ -1,411 +0,0 @@
-:mod:`imp` --- Access the :ref:`import <importsystem>` internals
-================================================================
-
-.. module:: imp
-   :synopsis: Access the implementation of the import statement.
-   :deprecated:
-
-**Source code:** :source:`Lib/imp.py`
-
-.. deprecated-removed:: 3.4 3.12
-   The :mod:`imp` module is deprecated in favor of :mod:`importlib`.
-
-.. index:: statement: import
-
---------------
-
-This module provides an interface to the mechanisms used to implement the
-:keyword:`import` statement.  It defines the following constants and functions:
-
-
-.. function:: get_magic()
-
-   .. index:: pair: file; byte-code
-
-   Return the magic string value used to recognize byte-compiled code files
-   (:file:`.pyc` files).  (This value may be different for each Python version.)
-
-   .. deprecated:: 3.4
-       Use :attr:`importlib.util.MAGIC_NUMBER` instead.
-
-
-.. function:: get_suffixes()
-
-   Return a list of 3-element tuples, each describing a particular type of
-   module. Each triple has the form ``(suffix, mode, type)``, where *suffix* is
-   a string to be appended to the module name to form the filename to search
-   for, *mode* is the mode string to pass to the built-in :func:`open` function
-   to open the file (this can be ``'r'`` for text files or ``'rb'`` for binary
-   files), and *type* is the file type, which has one of the values
-   :const:`PY_SOURCE`, :const:`PY_COMPILED`, or :const:`C_EXTENSION`, described
-   below.
-
-   .. deprecated:: 3.3
-      Use the constants defined on :mod:`importlib.machinery` instead.
-
-
-.. function:: find_module(name[, path])
-
-   Try to find the module *name*.  If *path* is omitted or ``None``, the list of
-   directory names given by ``sys.path`` is searched, but first a few special
-   places are searched: the function tries to find a built-in module with the
-   given name (:const:`C_BUILTIN`), then a frozen module (:const:`PY_FROZEN`),
-   and on some systems some other places are looked in as well (on Windows, it
-   looks in the registry which may point to a specific file).
-
-   Otherwise, *path* must be a list of directory names; each directory is
-   searched for files with any of the suffixes returned by :func:`get_suffixes`
-   above.  Invalid names in the list are silently ignored (but all list items
-   must be strings).
-
-   If search is successful, the return value is a 3-element tuple ``(file,
-   pathname, description)``:
-
-   *file* is an open :term:`file object` positioned at the beginning, *pathname*
-   is the pathname of the file found, and *description* is a 3-element tuple as
-   contained in the list returned by :func:`get_suffixes` describing the kind of
-   module found.
-
-   If the module is built-in or frozen then *file* and *pathname* are both ``None``
-   and the *description* tuple contains empty strings for its suffix and mode;
-   the module type is indicated as given in parentheses above.  If the search
-   is unsuccessful, :exc:`ImportError` is raised.  Other exceptions indicate
-   problems with the arguments or environment.
-
-   If the module is a package, *file* is ``None``, *pathname* is the package
-   path and the last item in the *description* tuple is :const:`PKG_DIRECTORY`.
-
-   This function does not handle hierarchical module names (names containing
-   dots).  In order to find *P.M*, that is, submodule *M* of package *P*, use
-   :func:`find_module` and :func:`load_module` to find and load package *P*, and
-   then use :func:`find_module` with the *path* argument set to ``P.__path__``.
-   When *P* itself has a dotted name, apply this recipe recursively.
-
-   .. deprecated:: 3.3
-      Use :func:`importlib.util.find_spec` instead unless Python 3.3
-      compatibility is required, in which case use
-      :func:`importlib.find_loader`. For example usage of the former case,
-      see the :ref:`importlib-examples` section of the :mod:`importlib`
-      documentation.
-
-
-.. function:: load_module(name, file, pathname, description)
-
-   Load a module that was previously found by :func:`find_module` (or by an
-   otherwise conducted search yielding compatible results).  This function does
-   more than importing the module: if the module was already imported, it will
-   reload the module!  The *name* argument indicates the full
-   module name (including the package name, if this is a submodule of a
-   package).  The *file* argument is an open file, and *pathname* is the
-   corresponding file name; these can be ``None`` and ``''``, respectively, when
-   the module is a package or not being loaded from a file.  The *description*
-   argument is a tuple, as would be returned by :func:`get_suffixes`, describing
-   what kind of module must be loaded.
-
-   If the load is successful, the return value is the module object; otherwise,
-   an exception (usually :exc:`ImportError`) is raised.
-
-   **Important:** the caller is responsible for closing the *file* argument, if
-   it was not ``None``, even when an exception is raised.  This is best done
-   using a :keyword:`try` ... :keyword:`finally` statement.
-
-   .. deprecated:: 3.3
-      If previously used in conjunction with :func:`imp.find_module` then
-      consider using :func:`importlib.import_module`, otherwise use the loader
-      returned by the replacement you chose for :func:`imp.find_module`. If you
-      called :func:`imp.load_module` and related functions directly with file
-      path arguments then use a combination of
-      :func:`importlib.util.spec_from_file_location` and
-      :func:`importlib.util.module_from_spec`. See the :ref:`importlib-examples`
-      section of the :mod:`importlib` documentation for details of the various
-      approaches.
-
-
-.. function:: new_module(name)
-
-   Return a new empty module object called *name*.  This object is *not* inserted
-   in ``sys.modules``.
-
-   .. deprecated:: 3.4
-      Use :func:`importlib.util.module_from_spec` instead.
-
-
-.. function:: reload(module)
-
-   Reload a previously imported *module*.  The argument must be a module object, so
-   it must have been successfully imported before.  This is useful if you have
-   edited the module source file using an external editor and want to try out the
-   new version without leaving the Python interpreter.  The return value is the
-   module object (the same as the *module* argument).
-
-   When ``reload(module)`` is executed:
-
-   * Python modules' code is recompiled and the module-level code reexecuted,
-     defining a new set of objects which are bound to names in the module's
-     dictionary.  The ``init`` function of extension modules is not called a second
-     time.
-
-   * As with all other objects in Python the old objects are only reclaimed after
-     their reference counts drop to zero.
-
-   * The names in the module namespace are updated to point to any new or changed
-     objects.
-
-   * Other references to the old objects (such as names external to the module) are
-     not rebound to refer to the new objects and must be updated in each namespace
-     where they occur if that is desired.
-
-   There are a number of other caveats:
-
-   When a module is reloaded, its dictionary (containing the module's global
-   variables) is retained.  Redefinitions of names will override the old
-   definitions, so this is generally not a problem.  If the new version of a module
-   does not define a name that was defined by the old version, the old definition
-   remains.  This feature can be used to the module's advantage if it maintains a
-   global table or cache of objects --- with a :keyword:`try` statement it can test
-   for the table's presence and skip its initialization if desired::
-
-      try:
-          cache
-      except NameError:
-          cache = {}
-
-   It is legal though generally not very useful to reload built-in or dynamically
-   loaded modules, except for :mod:`sys`, :mod:`__main__` and :mod:`builtins`.
-   In many cases, however, extension modules are not designed to be initialized
-   more than once, and may fail in arbitrary ways when reloaded.
-
-   If a module imports objects from another module using :keyword:`from` ...
-   :keyword:`import` ..., calling :func:`reload` for the other module does not
-   redefine the objects imported from it --- one way around this is to re-execute
-   the :keyword:`!from` statement, another is to use :keyword:`!import` and qualified
-   names (*module*.*name*) instead.
-
-   If a module instantiates instances of a class, reloading the module that defines
-   the class does not affect the method definitions of the instances --- they
-   continue to use the old class definition.  The same is true for derived classes.
-
-   .. versionchanged:: 3.3
-      Relies on both ``__name__`` and ``__loader__`` being defined on the module
-      being reloaded instead of just ``__name__``.
-
-   .. deprecated:: 3.4
-      Use :func:`importlib.reload` instead.
-
-
-The following functions are conveniences for handling :pep:`3147` byte-compiled
-file paths.
-
-.. versionadded:: 3.2
-
-.. function:: cache_from_source(path, debug_override=None)
-
-   Return the :pep:`3147` path to the byte-compiled file associated with the
-   source *path*.  For example, if *path* is ``/foo/bar/baz.py`` the return
-   value would be ``/foo/bar/__pycache__/baz.cpython-32.pyc`` for Python 3.2.
-   The ``cpython-32`` string comes from the current magic tag (see
-   :func:`get_tag`; if :attr:`sys.implementation.cache_tag` is not defined then
-   :exc:`NotImplementedError` will be raised). By passing in ``True`` or
-   ``False`` for *debug_override* you can override the system's value for
-   ``__debug__``, leading to optimized bytecode.
-
-   *path* need not exist.
-
-   .. versionchanged:: 3.3
-      If :attr:`sys.implementation.cache_tag` is ``None``, then
-      :exc:`NotImplementedError` is raised.
-
-   .. deprecated:: 3.4
-      Use :func:`importlib.util.cache_from_source` instead.
-
-   .. versionchanged:: 3.5
-      The *debug_override* parameter no longer creates a ``.pyo`` file.
-
-
-.. function:: source_from_cache(path)
-
-   Given the *path* to a :pep:`3147` file name, return the associated source code
-   file path.  For example, if *path* is
-   ``/foo/bar/__pycache__/baz.cpython-32.pyc`` the returned path would be
-   ``/foo/bar/baz.py``.  *path* need not exist, however if it does not conform
-   to :pep:`3147` format, a :exc:`ValueError` is raised. If
-   :attr:`sys.implementation.cache_tag` is not defined,
-   :exc:`NotImplementedError` is raised.
-
-   .. versionchanged:: 3.3
-      Raise :exc:`NotImplementedError` when
-      :attr:`sys.implementation.cache_tag` is not defined.
-
-   .. deprecated:: 3.4
-      Use :func:`importlib.util.source_from_cache` instead.
-
-
-.. function:: get_tag()
-
-   Return the :pep:`3147` magic tag string matching this version of Python's
-   magic number, as returned by :func:`get_magic`.
-
-   .. deprecated:: 3.4
-      Use :attr:`sys.implementation.cache_tag` directly starting
-      in Python 3.3.
-
-
-The following functions help interact with the import system's internal
-locking mechanism.  Locking semantics of imports are an implementation
-detail which may vary from release to release.  However, Python ensures
-that circular imports work without any deadlocks.
-
-
-.. function:: lock_held()
-
-   Return ``True`` if the global import lock is currently held, else
-   ``False``. On platforms without threads, always return ``False``.
-
-   On platforms with threads, a thread executing an import first holds a
-   global import lock, then sets up a per-module lock for the rest of the
-   import.  This blocks other threads from importing the same module until
-   the original import completes, preventing other threads from seeing
-   incomplete module objects constructed by the original thread.  An
-   exception is made for circular imports, which by construction have to
-   expose an incomplete module object at some point.
-
-   .. versionchanged:: 3.3
-      The locking scheme has changed to per-module locks for
-      the most part.  A global import lock is kept for some critical tasks,
-      such as initializing the per-module locks.
-
-   .. deprecated:: 3.4
-
-
-.. function:: acquire_lock()
-
-   Acquire the interpreter's global import lock for the current thread.
-   This lock should be used by import hooks to ensure thread-safety when
-   importing modules.
-
-   Once a thread has acquired the import lock, the same thread may acquire it
-   again without blocking; the thread must release it once for each time it has
-   acquired it.
-
-   On platforms without threads, this function does nothing.
-
-   .. versionchanged:: 3.3
-      The locking scheme has changed to per-module locks for
-      the most part.  A global import lock is kept for some critical tasks,
-      such as initializing the per-module locks.
-
-   .. deprecated:: 3.4
-
-
-.. function:: release_lock()
-
-   Release the interpreter's global import lock. On platforms without
-   threads, this function does nothing.
-
-   .. versionchanged:: 3.3
-      The locking scheme has changed to per-module locks for
-      the most part.  A global import lock is kept for some critical tasks,
-      such as initializing the per-module locks.
-
-   .. deprecated:: 3.4
-
-
-The following constants with integer values, defined in this module, are used
-to indicate the search result of :func:`find_module`.
-
-
-.. data:: PY_SOURCE
-
-   The module was found as a source file.
-
-   .. deprecated:: 3.3
-
-
-.. data:: PY_COMPILED
-
-   The module was found as a compiled code object file.
-
-   .. deprecated:: 3.3
-
-
-.. data:: C_EXTENSION
-
-   The module was found as dynamically loadable shared library.
-
-   .. deprecated:: 3.3
-
-
-.. data:: PKG_DIRECTORY
-
-   The module was found as a package directory.
-
-   .. deprecated:: 3.3
-
-
-.. data:: C_BUILTIN
-
-   The module was found as a built-in module.
-
-   .. deprecated:: 3.3
-
-
-.. data:: PY_FROZEN
-
-   The module was found as a frozen module.
-
-   .. deprecated:: 3.3
-
-
-.. class:: NullImporter(path_string)
-
-   The :class:`NullImporter` type is a :pep:`302` import hook that handles
-   non-directory path strings by failing to find any modules.  Calling this type
-   with an existing directory or empty string raises :exc:`ImportError`.
-   Otherwise, a :class:`NullImporter` instance is returned.
-
-   Instances have only one method:
-
-   .. method:: NullImporter.find_module(fullname [, path])
-
-      This method always returns ``None``, indicating that the requested module could
-      not be found.
-
-   .. versionchanged:: 3.3
-      ``None`` is inserted into ``sys.path_importer_cache`` instead of an
-      instance of :class:`NullImporter`.
-
-   .. deprecated:: 3.4
-      Insert ``None`` into ``sys.path_importer_cache`` instead.
-
-
-.. _examples-imp:
-
-Examples
---------
-
-The following function emulates what was the standard import statement up to
-Python 1.4 (no hierarchical module names).  (This *implementation* wouldn't work
-in that version, since :func:`find_module` has been extended and
-:func:`load_module` has been added in 1.4.) ::
-
-   import imp
-   import sys
-
-   def __import__(name, globals=None, locals=None, fromlist=None):
-       # Fast path: see if the module has already been imported.
-       try:
-           return sys.modules[name]
-       except KeyError:
-           pass
-
-       # If any of the following calls raises an exception,
-       # there's a problem we can't handle -- let the caller handle it.
-
-       fp, pathname, description = imp.find_module(name)
-
-       try:
-           return imp.load_module(name, fp, pathname, description)
-       finally:
-           # Since we may exit via an exception, close fp explicitly.
-           if fp:
-               fp.close()
diff -pruN 3.12.0~a7-1/Doc/library/importlib.metadata.rst 3.12.0~b1-1/Doc/library/importlib.metadata.rst
--- 3.12.0~a7-1/Doc/library/importlib.metadata.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/importlib.metadata.rst	2023-05-22 12:07:36.000000000 +0000
@@ -1,11 +1,11 @@
 .. _using:
 
-=================================
- Using :mod:`!importlib.metadata`
-=================================
+========================================================
+:mod:`!importlib.metadata` -- Accessing package metadata
+========================================================
 
 .. module:: importlib.metadata
-   :synopsis: The implementation of the importlib metadata.
+   :synopsis: Accessing package metadata
 
 .. versionadded:: 3.8
 .. versionchanged:: 3.10
@@ -13,7 +13,7 @@
 
 **Source code:** :source:`Lib/importlib/metadata/__init__.py`
 
-``importlib_metadata`` is a library that provides access to
+``importlib.metadata`` is a library that provides access to
 the metadata of an installed `Distribution Package <https://packaging.python.org/en/latest/glossary/#term-Distribution-Package>`_,
 such as its entry points
 or its top-level names (`Import Package <https://packaging.python.org/en/latest/glossary/#term-Import-Package>`_\s, modules, if any).
@@ -24,7 +24,7 @@ API`_ and `metadata API`_ of ``pkg_resou
 this package can eliminate the need to use the older and less efficient
 ``pkg_resources`` package.
 
-``importlib_metadata`` operates on third-party *distribution packages*
+``importlib.metadata`` operates on third-party *distribution packages*
 installed into Python's ``site-packages`` directory via tools such as
 `pip <https://pypi.org/project/pip/>`_.
 Specifically, it works with distributions with discoverable
@@ -178,7 +178,7 @@ The "selectable" entry points were intro
 no parameters and always returned a dictionary of entry points, keyed
 by group. With ``importlib_metadata`` 5.0 and Python 3.12,
 ``entry_points`` always returns an ``EntryPoints`` object. See
-`backports.entry_points_selectable <https://pypi.org/project/backports.entry_points_selectable>`_
+`backports.entry_points_selectable <https://pypi.org/project/backports.entry-points-selectable>`_
 for compatibility options.
 
 
@@ -308,6 +308,10 @@ Python module or `Import Package <https:
     >>> packages_distributions()
     {'importlib_metadata': ['importlib-metadata'], 'yaml': ['PyYAML'], 'jaraco': ['jaraco.classes', 'jaraco.functools'], ...}
 
+Some editable installs, `do not supply top-level names
+<https://github.com/pypa/packaging-problems/issues/609>`_, and thus this
+function is not reliable with such installs.
+
 .. versionadded:: 3.10
 
 .. _distributions:
@@ -364,7 +368,7 @@ system :ref:`finders <finders-and-loader
 ``importlib.metadata`` queries the list of :term:`meta path finders <meta path finder>` on
 :data:`sys.meta_path`.
 
-By default ``importlib_metadata`` installs a finder for distribution packages
+By default ``importlib.metadata`` installs a finder for distribution packages
 found on the file system.
 This finder doesn't actually find any *distributions*,
 but it can find their metadata.
diff -pruN 3.12.0~a7-1/Doc/library/importlib.resources.rst 3.12.0~b1-1/Doc/library/importlib.resources.rst
--- 3.12.0~a7-1/Doc/library/importlib.resources.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/importlib.resources.rst	2023-05-22 12:07:36.000000000 +0000
@@ -1,5 +1,5 @@
-:mod:`importlib.resources` -- Resources
----------------------------------------
+:mod:`importlib.resources` -- Package resource reading, opening and access
+--------------------------------------------------------------------------
 
 .. module:: importlib.resources
     :synopsis: Package resource reading, opening, and access
@@ -97,7 +97,7 @@ for example, a package and its resources
 
 
 Deprecated functions
---------------------
+^^^^^^^^^^^^^^^^^^^^
 
 An older, deprecated set of functions is still available, but is
 scheduled for removal in a future version of Python.
diff -pruN 3.12.0~a7-1/Doc/library/importlib.rst 3.12.0~b1-1/Doc/library/importlib.rst
--- 3.12.0~a7-1/Doc/library/importlib.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/importlib.rst	2023-05-22 12:07:36.000000000 +0000
@@ -127,28 +127,6 @@ Functions
     .. versionchanged:: 3.3
        Parent packages are automatically imported.
 
-.. function:: find_loader(name, path=None)
-
-   Find the loader for a module, optionally within the specified *path*. If the
-   module is in :attr:`sys.modules`, then ``sys.modules[name].__loader__`` is
-   returned (unless the loader would be ``None`` or is not set, in which case
-   :exc:`ValueError` is raised). Otherwise a search using :attr:`sys.meta_path`
-   is done. ``None`` is returned if no loader is found.
-
-   A dotted name does not have its parents implicitly imported as that requires
-   loading them and that may not be desired. To properly import a submodule you
-   will need to import all parent packages of the submodule and use the correct
-   argument to *path*.
-
-   .. versionadded:: 3.3
-
-   .. versionchanged:: 3.4
-      If ``__loader__`` is not set, raise :exc:`ValueError`, just like when the
-      attribute is set to ``None``.
-
-   .. deprecated:: 3.4
-      Use :func:`importlib.util.find_spec` instead.
-
 .. function:: invalidate_caches()
 
    Invalidate the internal caches of finders stored at
@@ -247,7 +225,6 @@ are also provided to help in implementin
 ABC hierarchy::
 
     object
-     +-- Finder (deprecated)
      +-- MetaPathFinder
      +-- PathEntryFinder
      +-- Loader
@@ -258,28 +235,6 @@ ABC hierarchy::
                                      +-- SourceLoader
 
 
-.. class:: Finder
-
-   An abstract base class representing a :term:`finder`.
-
-   .. deprecated:: 3.3
-      Use :class:`MetaPathFinder` or :class:`PathEntryFinder` instead.
-
-   .. abstractmethod:: find_module(fullname, path=None)
-
-      An abstract method for finding a :term:`loader` for the specified
-      module.  Originally specified in :pep:`302`, this method was meant
-      for use in :data:`sys.meta_path` and in the path-based import subsystem.
-
-      .. versionchanged:: 3.4
-         Returns ``None`` when called instead of raising
-         :exc:`NotImplementedError`.
-
-      .. deprecated:: 3.10
-         Implement :meth:`MetaPathFinder.find_spec` or
-         :meth:`PathEntryFinder.find_spec` instead.
-
-
 .. class:: MetaPathFinder
 
    An abstract base class representing a :term:`meta path finder`.
@@ -287,7 +242,7 @@ ABC hierarchy::
    .. versionadded:: 3.3
 
    .. versionchanged:: 3.10
-      No longer a subclass of :class:`Finder`.
+      No longer a subclass of :class:`!Finder`.
 
    .. method:: find_spec(fullname, path, target=None)
 
@@ -303,25 +258,6 @@ ABC hierarchy::
 
       .. versionadded:: 3.4
 
-   .. method:: find_module(fullname, path)
-
-      A legacy method for finding a :term:`loader` for the specified
-      module.  If this is a top-level import, *path* will be ``None``.
-      Otherwise, this is a search for a subpackage or module and *path*
-      will be the value of :attr:`__path__` from the parent
-      package. If a loader cannot be found, ``None`` is returned.
-
-      If :meth:`find_spec` is defined, backwards-compatible functionality is
-      provided.
-
-      .. versionchanged:: 3.4
-         Returns ``None`` when called instead of raising
-         :exc:`NotImplementedError`. Can use :meth:`find_spec` to provide
-         functionality.
-
-      .. deprecated:: 3.4
-         Use :meth:`find_spec` instead.
-
    .. method:: invalidate_caches()
 
       An optional method which, when called, should invalidate any internal
@@ -342,7 +278,7 @@ ABC hierarchy::
    .. versionadded:: 3.3
 
    .. versionchanged:: 3.10
-      No longer a subclass of :class:`Finder`.
+      No longer a subclass of :class:`!Finder`.
 
    .. method:: find_spec(fullname, target=None)
 
@@ -356,36 +292,6 @@ ABC hierarchy::
 
       .. versionadded:: 3.4
 
-   .. method:: find_loader(fullname)
-
-      A legacy method for finding a :term:`loader` for the specified
-      module.  Returns a 2-tuple of ``(loader, portion)`` where ``portion``
-      is a sequence of file system locations contributing to part of a namespace
-      package. The loader may be ``None`` while specifying ``portion`` to
-      signify the contribution of the file system locations to a namespace
-      package. An empty list can be used for ``portion`` to signify the loader
-      is not part of a namespace package. If ``loader`` is ``None`` and
-      ``portion`` is the empty list then no loader or location for a namespace
-      package were found (i.e. failure to find anything for the module).
-
-      If :meth:`find_spec` is defined then backwards-compatible functionality is
-      provided.
-
-      .. versionchanged:: 3.4
-         Returns ``(None, [])`` instead of raising :exc:`NotImplementedError`.
-         Uses :meth:`find_spec` when available to provide functionality.
-
-      .. deprecated:: 3.4
-         Use :meth:`find_spec` instead.
-
-   .. method:: find_module(fullname)
-
-      A concrete implementation of :meth:`Finder.find_module` which is
-      equivalent to ``self.find_loader(fullname)[0]``.
-
-      .. deprecated:: 3.4
-         Use :meth:`find_spec` instead.
-
    .. method:: invalidate_caches()
 
       An optional method which, when called, should invalidate any internal
@@ -881,13 +787,6 @@ find and load modules.
          is no longer valid then ``None`` is returned but no value is cached
          in :data:`sys.path_importer_cache`.
 
-   .. classmethod:: find_module(fullname, path=None)
-
-      A legacy wrapper around :meth:`find_spec`.
-
-      .. deprecated:: 3.4
-         Use :meth:`find_spec` instead.
-
    .. classmethod:: invalidate_caches()
 
       Calls :meth:`importlib.abc.PathEntryFinder.invalidate_caches` on all
@@ -938,13 +837,6 @@ find and load modules.
 
       .. versionadded:: 3.4
 
-   .. method:: find_loader(fullname)
-
-      Attempt to find the loader to handle *fullname* within :attr:`path`.
-
-      .. deprecated:: 3.10
-         Use :meth:`find_spec` instead.
-
    .. method:: invalidate_caches()
 
       Clear out the internal cache.
diff -pruN 3.12.0~a7-1/Doc/library/inspect.rst 3.12.0~b1-1/Doc/library/inspect.rst
--- 3.12.0~a7-1/Doc/library/inspect.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/inspect.rst	2023-05-22 12:07:36.000000000 +0000
@@ -1603,6 +1603,39 @@ the following flags:
    for any introspection needs.
 
 
+Buffer flags
+------------
+
+.. class:: BufferFlags
+
+   This is an :class:`enum.IntFlag` that represents the flags that
+   can be passed to the :meth:`~object.__buffer__` method of objects
+   implementing the :ref:`buffer protocol <bufferobjects>`.
+
+   The meaning of the flags is explained at :ref:`buffer-request-types`.
+
+   .. attribute:: BufferFlags.SIMPLE
+   .. attribute:: BufferFlags.WRITABLE
+   .. attribute:: BufferFlags.FORMAT
+   .. attribute:: BufferFlags.ND
+   .. attribute:: BufferFlags.STRIDES
+   .. attribute:: BufferFlags.C_CONTIGUOUS
+   .. attribute:: BufferFlags.F_CONTIGUOUS
+   .. attribute:: BufferFlags.ANY_CONTIGUOUS
+   .. attribute:: BufferFlags.INDIRECT
+   .. attribute:: BufferFlags.CONTIG
+   .. attribute:: BufferFlags.CONTIG_RO
+   .. attribute:: BufferFlags.STRIDED
+   .. attribute:: BufferFlags.STRIDED_RO
+   .. attribute:: BufferFlags.RECORDS
+   .. attribute:: BufferFlags.RECORDS_RO
+   .. attribute:: BufferFlags.FULL
+   .. attribute:: BufferFlags.FULL_RO
+   .. attribute:: BufferFlags.READ
+   .. attribute:: BufferFlags.WRITE
+
+   .. versionadded:: 3.12
+
 .. _inspect-module-cli:
 
 Command Line Interface
diff -pruN 3.12.0~a7-1/Doc/library/internet.rst 3.12.0~b1-1/Doc/library/internet.rst
--- 3.12.0~a7-1/Doc/library/internet.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/internet.rst	2023-05-22 12:07:36.000000000 +0000
@@ -9,7 +9,7 @@ Internet Protocols and Support
    single: Internet
    single: World Wide Web
 
-.. index:: module: socket
+.. index:: pair: module; socket
 
 The modules described in this chapter implement internet protocols and  support
 for related technology.  They are all implemented in Python. Most of these
diff -pruN 3.12.0~a7-1/Doc/library/itertools.rst 3.12.0~b1-1/Doc/library/itertools.rst
--- 3.12.0~a7-1/Doc/library/itertools.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/itertools.rst	2023-05-22 12:07:36.000000000 +0000
@@ -769,8 +769,8 @@ well as with the built-in itertools such
 
 A secondary purpose of the recipes is to serve as an incubator.  The
 ``accumulate()``, ``compress()``, and ``pairwise()`` itertools started out as
-recipes.  Currently, the ``iter_index()`` recipe is being tested to see
-whether it proves its worth.
+recipes.  Currently, the ``sliding_window()`` and ``iter_index()`` recipes
+are being tested to see whether they prove their worth.
 
 Substantially all of these recipes and many, many others can be installed from
 the `more-itertools project <https://pypi.org/project/more-itertools/>`_ found
@@ -789,6 +789,7 @@ which incur interpreter overhead.
 .. testcode::
 
    import collections
+   import functools
    import math
    import operator
    import random
@@ -806,6 +807,23 @@ which incur interpreter overhead.
        "Return function(0), function(1), ..."
        return map(function, count(start))
 
+   def repeatfunc(func, times=None, *args):
+       """Repeat calls to func with specified arguments.
+
+       Example:  repeatfunc(random.random)
+       """
+       if times is None:
+           return starmap(func, repeat(args))
+       return starmap(func, repeat(args, times))
+
+   def flatten(list_of_lists):
+       "Flatten one level of nesting"
+       return chain.from_iterable(list_of_lists)
+
+   def ncycles(iterable, n):
+       "Returns the sequence elements n times"
+       return chain.from_iterable(repeat(tuple(iterable), n))
+
    def tail(n, iterable):
        "Return an iterator over the last n items"
        # tail(3, 'ABCDEFG') --> E F G
@@ -825,70 +843,27 @@ which incur interpreter overhead.
        "Returns the nth item or a default value"
        return next(islice(iterable, n, None), default)
 
-   def all_equal(iterable):
-       "Returns True if all the elements are equal to each other"
-       g = groupby(iterable)
-       return next(g, True) and not next(g, False)
-
    def quantify(iterable, pred=bool):
        "Count how many times the predicate is True"
        return sum(map(pred, iterable))
 
-   def ncycles(iterable, n):
-       "Returns the sequence elements n times"
-       return chain.from_iterable(repeat(tuple(iterable), n))
-
-   def sum_of_squares(it):
-       "Add up the squares of the input values."
-       # sum_of_squares([10, 20, 30]) -> 1400
-       return math.sumprod(*tee(it))
-
-   def transpose(it):
-       "Swap the rows and columns of the input."
-       # transpose([(1, 2, 3), (11, 22, 33)]) --> (1, 11) (2, 22) (3, 33)
-       return zip(*it, strict=True)
-
-   def matmul(m1, m2):
-       "Multiply two matrices."
-       # matmul([(7, 5), (3, 5)], [[2, 5], [7, 9]]) --> (49, 80), (41, 60)
-       n = len(m2[0])
-       return batched(starmap(math.sumprod, product(m1, transpose(m2))), n)
-
-   def convolve(signal, kernel):
-       # See:  https://betterexplained.com/articles/intuitive-convolution/
-       # convolve(data, [0.25, 0.25, 0.25, 0.25]) --> Moving average (blur)
-       # convolve(data, [1, -1]) --> 1st finite difference (1st derivative)
-       # convolve(data, [1, -2, 1]) --> 2nd finite difference (2nd derivative)
-       kernel = tuple(kernel)[::-1]
-       n = len(kernel)
-       window = collections.deque([0], maxlen=n) * n
-       for x in chain(signal, repeat(0, n-1)):
-           window.append(x)
-           yield math.sumprod(kernel, window)
+   def all_equal(iterable):
+       "Returns True if all the elements are equal to each other"
+       g = groupby(iterable)
+       return next(g, True) and not next(g, False)
 
-   def polynomial_from_roots(roots):
-       """Compute a polynomial's coefficients from its roots.
+   def first_true(iterable, default=False, pred=None):
+       """Returns the first true value in the iterable.
 
-          (x - 5) (x + 4) (x - 3)  expands to:   x³ -4x² -17x + 60
-       """
-       # polynomial_from_roots([5, -4, 3]) --> [1, -4, -17, 60]
-       expansion = [1]
-       for r in roots:
-           expansion = convolve(expansion, (1, -r))
-       return list(expansion)
+       If no true value is found, returns *default*
 
-   def polynomial_eval(coefficients, x):
-       """Evaluate a polynomial at a specific value.
+       If *pred* is not None, returns the first item
+       for which pred(item) is true.
 
-       Computes with better numeric stability than Horner's method.
        """
-       # Evaluate x³ -4x² -17x + 60 at x = 2.5
-       # polynomial_eval([1, -4, -17, 60], x=2.5) --> 8.125
-       n = len(coefficients)
-       if n == 0:
-           return x * 0  # coerce zero to the type of x
-       powers = map(pow, repeat(x), reversed(range(n)))
-       return math.sumprod(coefficients, powers)
+       # first_true([a,b,c], x) --> a or b or c or x
+       # first_true([a,b], x, f) --> a if f(a) else b if f(b) else x
+       return next(filter(pred, iterable), default)
 
    def iter_index(iterable, value, start=0):
        "Return indices where a value occurs in a sequence or iterable."
@@ -913,44 +888,28 @@ which incur interpreter overhead.
            except ValueError:
                pass
 
-   def sieve(n):
-       "Primes less than n"
-       # sieve(30) --> 2 3 5 7 11 13 17 19 23 29
-       data = bytearray((0, 1)) * (n // 2)
-       data[:3] = 0, 0, 0
-       limit = math.isqrt(n) + 1
-       for p in compress(range(limit), data):
-           data[p*p : n : p+p] = bytes(len(range(p*p, n, p+p)))
-       data[2] = 1
-       return iter_index(data, 1) if n > 2 else iter([])
-
-   def factor(n):
-       "Prime factors of n."
-       # factor(99) --> 3 3 11
-       for prime in sieve(math.isqrt(n) + 1):
-           while True:
-               quotient, remainder = divmod(n, prime)
-               if remainder:
-                   break
-               yield prime
-               n = quotient
-               if n == 1:
-                   return
-       if n > 1:
-           yield n
+   def iter_except(func, exception, first=None):
+       """ Call a function repeatedly until an exception is raised.
 
-   def flatten(list_of_lists):
-       "Flatten one level of nesting"
-       return chain.from_iterable(list_of_lists)
+       Converts a call-until-exception interface to an iterator interface.
+       Like builtins.iter(func, sentinel) but uses an exception instead
+       of a sentinel to end the loop.
 
-   def repeatfunc(func, times=None, *args):
-       """Repeat calls to func with specified arguments.
+       Examples:
+           iter_except(functools.partial(heappop, h), IndexError)   # priority queue iterator
+           iter_except(d.popitem, KeyError)                         # non-blocking dict iterator
+           iter_except(d.popleft, IndexError)                       # non-blocking deque iterator
+           iter_except(q.get_nowait, Queue.Empty)                   # loop over a producer Queue
+           iter_except(s.pop, KeyError)                             # non-blocking set iterator
 
-       Example:  repeatfunc(random.random)
        """
-       if times is None:
-           return starmap(func, repeat(args))
-       return starmap(func, repeat(args, times))
+       try:
+           if first is not None:
+               yield first()            # For database APIs needing an initial cast to db.first()
+           while True:
+               yield func()
+       except exception:
+           pass
 
    def grouper(iterable, n, *, incomplete='fill', fillvalue=None):
        "Collect data into non-overlapping fixed-length chunks or blocks"
@@ -967,12 +926,6 @@ which incur interpreter overhead.
        else:
            raise ValueError('Expected fill, strict, or ignore')
 
-   def triplewise(iterable):
-       "Return overlapping triplets from an iterable"
-       # triplewise('ABCDEFG') --> ABC BCD CDE DEF EFG
-       for (a, _), (b, c) in pairwise(pairwise(iterable)):
-           yield a, b, c
-
    def sliding_window(iterable, n):
        # sliding_window('ABCDEFG', 4) --> ABCD BCDE CDEF DEFG
        it = iter(iterable)
@@ -1003,6 +956,12 @@ which incur interpreter overhead.
        t1, t2 = tee(iterable)
        return filterfalse(pred, t1), filter(pred, t2)
 
+   def subslices(seq):
+       "Return all contiguous non-empty subslices of a sequence"
+       # subslices('ABCD') --> A AB ABC ABCD B BC BCD C CD D
+       slices = starmap(slice, combinations(range(len(seq) + 1), 2))
+       return map(operator.getitem, repeat(seq), slices)
+
    def before_and_after(predicate, it):
        """ Variant of takewhile() that allows complete
            access to the remainder of the iterator.
@@ -1032,17 +991,6 @@ which incur interpreter overhead.
            yield from it
        return true_iterator(), remainder_iterator()
 
-   def subslices(seq):
-       "Return all contiguous non-empty subslices of a sequence"
-       # subslices('ABCD') --> A AB ABC ABCD B BC BCD C CD D
-       slices = starmap(slice, combinations(range(len(seq) + 1), 2))
-       return map(operator.getitem, repeat(seq), slices)
-
-   def powerset(iterable):
-       "powerset([1,2,3]) --> () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)"
-       s = list(iterable)
-       return chain.from_iterable(combinations(s, r) for r in range(len(s)+1))
-
    def unique_everseen(iterable, key=None):
        "List unique elements, preserving order. Remember all elements ever seen."
        # unique_everseen('AAAABBBCCDAABBB') --> A B C D
@@ -1072,41 +1020,94 @@ which incur interpreter overhead.
        # unique_justseen('ABBcCAD', str.lower) --> A B c A D
        return map(next, map(operator.itemgetter(1), groupby(iterable, key)))
 
-   def iter_except(func, exception, first=None):
-       """ Call a function repeatedly until an exception is raised.
 
-       Converts a call-until-exception interface to an iterator interface.
-       Like builtins.iter(func, sentinel) but uses an exception instead
-       of a sentinel to end the loop.
+The following recipes have a more mathematical flavor:
 
-       Examples:
-           iter_except(functools.partial(heappop, h), IndexError)   # priority queue iterator
-           iter_except(d.popitem, KeyError)                         # non-blocking dict iterator
-           iter_except(d.popleft, IndexError)                       # non-blocking deque iterator
-           iter_except(q.get_nowait, Queue.Empty)                   # loop over a producer Queue
-           iter_except(s.pop, KeyError)                             # non-blocking set iterator
+.. testcode::
 
-       """
-       try:
-           if first is not None:
-               yield first()            # For database APIs needing an initial cast to db.first()
+   def powerset(iterable):
+       "powerset([1,2,3]) --> () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)"
+       s = list(iterable)
+       return chain.from_iterable(combinations(s, r) for r in range(len(s)+1))
+
+   def sieve(n):
+       "Primes less than n"
+       # sieve(30) --> 2 3 5 7 11 13 17 19 23 29
+       data = bytearray((0, 1)) * (n // 2)
+       data[:3] = 0, 0, 0
+       limit = math.isqrt(n) + 1
+       for p in compress(range(limit), data):
+           data[p*p : n : p+p] = bytes(len(range(p*p, n, p+p)))
+       data[2] = 1
+       return iter_index(data, 1) if n > 2 else iter([])
+
+   def factor(n):
+       "Prime factors of n."
+       # factor(99) --> 3 3 11
+       for prime in sieve(math.isqrt(n) + 1):
            while True:
-               yield func()
-       except exception:
-           pass
+               quotient, remainder = divmod(n, prime)
+               if remainder:
+                   break
+               yield prime
+               n = quotient
+               if n == 1:
+                   return
+       if n > 1:
+           yield n
 
-   def first_true(iterable, default=False, pred=None):
-       """Returns the first true value in the iterable.
+   def sum_of_squares(it):
+       "Add up the squares of the input values."
+       # sum_of_squares([10, 20, 30]) -> 1400
+       return math.sumprod(*tee(it))
 
-       If no true value is found, returns *default*
+   def transpose(it):
+       "Swap the rows and columns of the input."
+       # transpose([(1, 2, 3), (11, 22, 33)]) --> (1, 11) (2, 22) (3, 33)
+       return zip(*it, strict=True)
 
-       If *pred* is not None, returns the first item
-       for which pred(item) is true.
+   def matmul(m1, m2):
+       "Multiply two matrices."
+       # matmul([(7, 5), (3, 5)], [[2, 5], [7, 9]]) --> (49, 80), (41, 60)
+       n = len(m2[0])
+       return batched(starmap(math.sumprod, product(m1, transpose(m2))), n)
+
+   def convolve(signal, kernel):
+       """Linear convolution of two iterables.
 
+       Article:  https://betterexplained.com/articles/intuitive-convolution/
+       Video:    https://www.youtube.com/watch?v=KuXjwB4LzSA
        """
-       # first_true([a,b,c], x) --> a or b or c or x
-       # first_true([a,b], x, f) --> a if f(a) else b if f(b) else x
-       return next(filter(pred, iterable), default)
+       # convolve(data, [0.25, 0.25, 0.25, 0.25]) --> Moving average (blur)
+       # convolve(data, [1, -1]) --> 1st finite difference (1st derivative)
+       # convolve(data, [1, -2, 1]) --> 2nd finite difference (2nd derivative)
+       kernel = tuple(kernel)[::-1]
+       n = len(kernel)
+       padded_signal = chain(repeat(0, n-1), signal, repeat(0, n-1))
+       for window in sliding_window(padded_signal, n):
+           yield math.sumprod(kernel, window)
+
+   def polynomial_from_roots(roots):
+       """Compute a polynomial's coefficients from its roots.
+
+          (x - 5) (x + 4) (x - 3)  expands to:   x³ -4x² -17x + 60
+       """
+       # polynomial_from_roots([5, -4, 3]) --> [1, -4, -17, 60]
+       factors = zip(repeat(1), map(operator.neg, roots))
+       return list(functools.reduce(convolve, factors, [1]))
+
+   def polynomial_eval(coefficients, x):
+       """Evaluate a polynomial at a specific value.
+
+       Computes with better numeric stability than Horner's method.
+       """
+       # Evaluate x³ -4x² -17x + 60 at x = 2.5
+       # polynomial_eval([1, -4, -17, 60], x=2.5) --> 8.125
+       n = len(coefficients)
+       if n == 0:
+           return x * 0  # coerce zero to the type of x
+       powers = map(pow, repeat(x), reversed(range(n)))
+       return math.sumprod(coefficients, powers)
 
    def nth_combination(iterable, r, index):
        "Equivalent to list(combinations(iterable, r))[index]"
@@ -1126,6 +1127,7 @@ which incur interpreter overhead.
            result.append(pool[-1-n])
        return tuple(result)
 
+
 .. doctest::
     :hide:
 
@@ -1401,9 +1403,6 @@ which incur interpreter overhead.
     >>> list(grouper('abcdefg', n=3, incomplete='ignore'))
     [('a', 'b', 'c'), ('d', 'e', 'f')]
 
-    >>> list(triplewise('ABCDEFG'))
-    [('A', 'B', 'C'), ('B', 'C', 'D'), ('C', 'D', 'E'), ('D', 'E', 'F'), ('E', 'F', 'G')]
-
     >>> list(sliding_window('ABCDEFG', 4))
     [('A', 'B', 'C', 'D'), ('B', 'C', 'D', 'E'), ('C', 'D', 'E', 'F'), ('D', 'E', 'F', 'G')]
 
@@ -1485,3 +1484,45 @@ which incur interpreter overhead.
     >>> combos = list(combinations(iterable, r))
     >>> all(nth_combination(iterable, r, i) == comb for i, comb in enumerate(combos))
     True
+
+
+.. testcode::
+    :hide:
+
+    # Old recipes and their tests which are guaranteed to continue to work.
+
+    def sumprod(vec1, vec2):
+        "Compute a sum of products."
+        return sum(starmap(operator.mul, zip(vec1, vec2, strict=True)))
+
+    def dotproduct(vec1, vec2):
+        return sum(map(operator.mul, vec1, vec2))
+
+    def pad_none(iterable):
+        """Returns the sequence elements and then returns None indefinitely.
+
+        Useful for emulating the behavior of the built-in map() function.
+        """
+        return chain(iterable, repeat(None))
+
+    def triplewise(iterable):
+        "Return overlapping triplets from an iterable"
+        # triplewise('ABCDEFG') --> ABC BCD CDE DEF EFG
+        for (a, _), (b, c) in pairwise(pairwise(iterable)):
+            yield a, b, c
+
+
+.. doctest::
+    :hide:
+
+    >>> dotproduct([1,2,3], [4,5,6])
+    32
+
+    >>> sumprod([1,2,3], [4,5,6])
+    32
+
+    >>> list(islice(pad_none('abc'), 0, 6))
+    ['a', 'b', 'c', None, None, None]
+
+    >>> list(triplewise('ABCDEFG'))
+    [('A', 'B', 'C'), ('B', 'C', 'D'), ('C', 'D', 'E'), ('D', 'E', 'F'), ('E', 'F', 'G')]
diff -pruN 3.12.0~a7-1/Doc/library/locale.rst 3.12.0~b1-1/Doc/library/locale.rst
--- 3.12.0~a7-1/Doc/library/locale.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/locale.rst	2023-05-22 12:07:36.000000000 +0000
@@ -16,7 +16,7 @@ functionality. The POSIX locale mechanis
 certain cultural issues in an application, without requiring the programmer to
 know all the specifics of each country where the software is executed.
 
-.. index:: module: _locale
+.. index:: pair: module; _locale
 
 The :mod:`locale` module is implemented on top of the :mod:`_locale` module,
 which in turn uses an ANSI C locale implementation if available.
@@ -464,7 +464,7 @@ The :mod:`locale` module defines the fol
 
 .. data:: LC_CTYPE
 
-   .. index:: module: string
+   .. index:: pair: module; string
 
    Locale category for the character type functions.  Depending on the settings of
    this category, the functions of module :mod:`string` dealing with case change
diff -pruN 3.12.0~a7-1/Doc/library/logging.config.rst 3.12.0~b1-1/Doc/library/logging.config.rst
--- 3.12.0~a7-1/Doc/library/logging.config.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/logging.config.rst	2023-05-22 12:07:36.000000000 +0000
@@ -87,6 +87,10 @@ in :mod:`logging` itself) and defining h
    provides a mechanism to present the choices and load the chosen
    configuration).
 
+   It will raise :exc:`FileNotFoundError` if the file
+   doesn't exist and :exc:`RuntimeError` if the file is invalid or
+   empty.
+
    :param fname: A filename, or a file-like object, or an instance derived
                  from :class:`~configparser.RawConfigParser`. If a
                  ``RawConfigParser``-derived instance is passed, it is used as
@@ -111,7 +115,7 @@ in :mod:`logging` itself) and defining h
                                     they or their ancestors are explicitly named
                                     in the logging configuration.
 
-    :param encoding: The encoding used to open file when *fname* is filename.
+   :param encoding: The encoding used to open file when *fname* is filename.
 
    .. versionchanged:: 3.4
       An instance of a subclass of :class:`~configparser.RawConfigParser` is
@@ -126,6 +130,10 @@ in :mod:`logging` itself) and defining h
     .. versionadded:: 3.10
        The *encoding* parameter is added.
 
+    .. versionchanged:: 3.12
+       An exception will be thrown if the provided file
+       doesn't exist or is invalid or empty.
+
 .. function:: listen(port=DEFAULT_LOGGING_CONFIG_PORT, verify=None)
 
    Starts up a socket server on the specified port, and listens for new
@@ -253,6 +261,7 @@ otherwise, the context is used to determ
    * ``datefmt``
    * ``style``
    * ``validate`` (since version >=3.8)
+   * ``defaults`` (since version >=3.12)
 
   An optional ``class`` key indicates the name of the formatter's
   class (as a dotted module and class name).  The instantiation
@@ -953,16 +962,22 @@ Sections which specify formatter configu
 .. code-block:: ini
 
    [formatter_form01]
-   format=F1 %(asctime)s %(levelname)s %(message)s
+   format=F1 %(asctime)s %(levelname)s %(message)s %(customfield)s
    datefmt=
    style=%
    validate=True
+   defaults={'customfield': 'defaultvalue'}
    class=logging.Formatter
 
 The arguments for the formatter configuration are the same as the keys
 in the dictionary schema :ref:`formatters section
 <logging-config-dictschema-formatters>`.
 
+The ``defaults`` entry, when :ref:`evaluated <func-eval>` in the context of
+the ``logging`` package's namespace, is a dictionary of default values for
+custom formatting fields. If not provided, it defaults to ``None``.
+
+
 .. note::
 
    Due to the use of :func:`eval` as described above, there are
diff -pruN 3.12.0~a7-1/Doc/library/marshal.rst 3.12.0~b1-1/Doc/library/marshal.rst
--- 3.12.0~a7-1/Doc/library/marshal.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/marshal.rst	2023-05-22 12:07:36.000000000 +0000
@@ -15,8 +15,8 @@ undocumented on purpose; it may change b
 rarely does). [#]_
 
 .. index::
-   module: pickle
-   module: shelve
+   pair: module; pickle
+   pair: module; shelve
 
 This is not a general "persistence" module.  For general persistence and
 transfer of Python objects through RPC calls, see the modules :mod:`pickle` and
diff -pruN 3.12.0~a7-1/Doc/library/math.rst 3.12.0~b1-1/Doc/library/math.rst
--- 3.12.0~a7-1/Doc/library/math.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/math.rst	2023-05-22 12:07:36.000000000 +0000
@@ -224,11 +224,11 @@ Number-theoretic and representation func
    of *x* and are floats.
 
 
-.. function:: nextafter(x, y)
+.. function:: nextafter(x, y, steps=1)
 
-   Return the next floating-point value after *x* towards *y*.
+   Return the floating-point value *steps* steps after *x* towards *y*.
 
-   If *x* is equal to *y*, return *y*.
+   If *x* is equal to *y*, return *y*, unless *steps* is zero.
 
    Examples:
 
@@ -239,6 +239,9 @@ Number-theoretic and representation func
 
    See also :func:`math.ulp`.
 
+   .. versionchanged:: 3.12
+      Added the *steps* argument.
+
    .. versionadded:: 3.9
 
 .. function:: perm(n, k=None)
diff -pruN 3.12.0~a7-1/Doc/library/multiprocessing.rst 3.12.0~b1-1/Doc/library/multiprocessing.rst
--- 3.12.0~a7-1/Doc/library/multiprocessing.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/multiprocessing.rst	2023-05-22 12:07:36.000000000 +0000
@@ -460,16 +460,16 @@ process which created it.
       ...     return x*x
       ...
       >>> with p:
-      ...   p.map(f, [1,2,3])
+      ...     p.map(f, [1,2,3])
       Process PoolWorker-1:
       Process PoolWorker-2:
       Process PoolWorker-3:
       Traceback (most recent call last):
       Traceback (most recent call last):
       Traceback (most recent call last):
-      AttributeError: 'module' object has no attribute 'f'
-      AttributeError: 'module' object has no attribute 'f'
-      AttributeError: 'module' object has no attribute 'f'
+      AttributeError: Can't get attribute 'f' on <module '__main__' (<class '_frozen_importlib.BuiltinImporter'>)>
+      AttributeError: Can't get attribute 'f' on <module '__main__' (<class '_frozen_importlib.BuiltinImporter'>)>
+      AttributeError: Can't get attribute 'f' on <module '__main__' (<class '_frozen_importlib.BuiltinImporter'>)>
 
    (If you try this it will actually output three full tracebacks
    interleaved in a semi-random fashion, and then you may have to
diff -pruN 3.12.0~a7-1/Doc/library/operator.rst 3.12.0~b1-1/Doc/library/operator.rst
--- 3.12.0~a7-1/Doc/library/operator.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/operator.rst	2023-05-22 12:07:36.000000000 +0000
@@ -244,7 +244,7 @@ Operations which work with sequences (so
 
 .. function:: length_hint(obj, default=0)
 
-   Return an estimated length for the object *o*. First try to return its
+   Return an estimated length for the object *obj*. First try to return its
    actual length, then an estimate using :meth:`object.__length_hint__`, and
    finally return the default value.
 
diff -pruN 3.12.0~a7-1/Doc/library/optparse.rst 3.12.0~b1-1/Doc/library/optparse.rst
--- 3.12.0~a7-1/Doc/library/optparse.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/optparse.rst	2023-05-22 12:07:36.000000000 +0000
@@ -954,7 +954,16 @@ The canonical way to create an :class:`O
 
 As you can see, most actions involve storing or updating a value somewhere.
 :mod:`optparse` always creates a special object for this, conventionally called
-``options`` (it happens to be an instance of :class:`optparse.Values`).  Option
+``options``, which is an instance of :class:`optparse.Values`.
+
+.. class:: Values
+
+   An object holding parsed argument names and values as attributes.
+   Normally created by calling when calling :meth:`OptionParser.parse_args`,
+   and can be overridden by a custom subclass passed to the *values* argument of
+   :meth:`OptionParser.parse_args` (as described in :ref:`optparse-parsing-arguments`).
+
+Option
 arguments (and various other values) are stored as attributes of this object,
 according to the :attr:`~Option.dest` (destination) option attribute.
 
@@ -991,6 +1000,14 @@ one that makes sense for *all* options.
 Option attributes
 ^^^^^^^^^^^^^^^^^
 
+.. class:: Option
+
+   A single command line argument,
+   with various attributes passed by keyword to the constructor.
+   Normally created with :meth:`OptionParser.add_option` rather than directly,
+   and can be overridden by a custom class via the *option_class* argument
+   to :class:`OptionParser`.
+
 The following option attributes may be passed as keyword arguments to
 :meth:`OptionParser.add_option`.  If you pass an option attribute that is not
 relevant to a particular option, or fail to pass a required option attribute,
@@ -2027,7 +2044,7 @@ Features of note:
      values.ensure_value(attr, value)
 
   If the ``attr`` attribute of ``values`` doesn't exist or is ``None``, then
-  ensure_value() first sets it to ``value``, and then returns 'value. This is
+  ensure_value() first sets it to ``value``, and then returns ``value``. This is
   very handy for actions like ``"extend"``, ``"append"``, and ``"count"``, all
   of which accumulate data in a variable and expect that variable to be of a
   certain type (a list for the first two, an integer for the latter).  Using
@@ -2035,3 +2052,27 @@ Features of note:
   about setting a default value for the option destinations in question; they
   can just leave the default as ``None`` and :meth:`ensure_value` will take care of
   getting it right when it's needed.
+
+Exceptions
+----------
+
+.. exception:: OptionError
+
+   Raised if an :class:`Option` instance is created with invalid or
+   inconsistent arguments.
+
+.. exception:: OptionConflictError
+
+   Raised if conflicting options are added to an :class:`OptionParser`.
+
+.. exception:: OptionValueError
+
+   Raised if an invalid option value is encountered on the command line.
+
+.. exception:: BadOptionError
+
+   Raised if an invalid option is passed on the command line.
+
+.. exception:: AmbiguousOptionError
+
+   Raised if an ambiguous option is passed on the command line.
diff -pruN 3.12.0~a7-1/Doc/library/os.path.rst 3.12.0~b1-1/Doc/library/os.path.rst
--- 3.12.0~a7-1/Doc/library/os.path.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/os.path.rst	2023-05-22 12:07:36.000000000 +0000
@@ -159,7 +159,7 @@ the :mod:`glob` module.)
    On Unix and Windows, return the argument with an initial component of ``~`` or
    ``~user`` replaced by that *user*'s home directory.
 
-   .. index:: module: pwd
+   .. index:: pair: module; pwd
 
    On Unix, an initial ``~`` is replaced by the environment variable :envvar:`HOME`
    if it is set; otherwise the current user's home directory is looked up in the
diff -pruN 3.12.0~a7-1/Doc/library/os.rst 3.12.0~b1-1/Doc/library/os.rst
--- 3.12.0~a7-1/Doc/library/os.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/os.rst	2023-05-22 12:07:36.000000000 +0000
@@ -493,6 +493,17 @@ process and user.
    .. versionadded:: 3.3
 
 
+.. data:: PRIO_DARWIN_THREAD
+          PRIO_DARWIN_PROCESS
+          PRIO_DARWIN_BG
+          PRIO_DARWIN_NONUI
+
+   Parameters for the :func:`getpriority` and :func:`setpriority` functions.
+
+   .. availability:: macOS
+
+   .. versionadded:: 3.12
+
 .. function:: getresuid()
 
    Return a tuple (ruid, euid, suid) denoting the current process's
@@ -1284,7 +1295,7 @@ or `the MSDN <https://msdn.microsoft.com
 
 .. function:: openpty()
 
-   .. index:: module: pty
+   .. index:: pair: module; pty
 
    Open a new pseudo-terminal pair. Return a pair of file descriptors
    ``(master, slave)`` for the pty and the tty, respectively. The new file
@@ -2890,7 +2901,7 @@ features:
    possible and call :func:`lstat` on the result. This does not apply to
    dangling symlinks or junction points, which will raise the usual exceptions.
 
-   .. index:: module: stat
+   .. index:: pair: module; stat
 
    Example::
 
@@ -3919,7 +3930,8 @@ to be ignored.
    the :envvar:`PATH` variable. The other variants, :func:`execl`, :func:`execle`,
    :func:`execv`, and :func:`execve`, will not use the :envvar:`PATH` variable to
    locate the executable; *path* must contain an appropriate absolute or relative
-   path.
+   path. Relative paths must include at least one slash, even on Windows, as
+   plain names will not be resolved.
 
    For :func:`execle`, :func:`execlpe`, :func:`execve`, and :func:`execvpe` (note
    that these all end in "e"), the *env* parameter must be a mapping which is
@@ -4592,7 +4604,7 @@ written in Python, such as a mail server
    :attr:`!children_system`, and :attr:`!elapsed` in that order.
 
    See the Unix manual page
-   :manpage:`times(2)` and `times(3) <https://www.freebsd.org/cgi/man.cgi?time(3)>`_ manual page on Unix or `the GetProcessTimes MSDN
+   :manpage:`times(2)` and `times(3) <https://man.freebsd.org/cgi/man.cgi?time(3)>`_ manual page on Unix or `the GetProcessTimes MSDN
    <https://docs.microsoft.com/windows/win32/api/processthreadsapi/nf-processthreadsapi-getprocesstimes>`_
    on Windows. On Windows, only :attr:`!user` and :attr:`!system` are known; the other attributes are zero.
 
diff -pruN 3.12.0~a7-1/Doc/library/pathlib.rst 3.12.0~b1-1/Doc/library/pathlib.rst
--- 3.12.0~a7-1/Doc/library/pathlib.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/pathlib.rst	2023-05-22 12:07:36.000000000 +0000
@@ -21,6 +21,7 @@ inherit from pure paths but also provide
 
 .. image:: pathlib-inheritance.png
    :align: center
+   :class: invert-in-dark-mode
 
 If you've never used this module before or just aren't sure which class is
 right for your task, :class:`Path` is most likely what you need. It instantiates
@@ -530,10 +531,10 @@ Pure paths provide the following methods
    unintended effects.
 
 
-.. method:: PurePath.joinpath(*other)
+.. method:: PurePath.joinpath(*pathsegments)
 
    Calling this method is equivalent to combining the path with each of
-   the *other* arguments in turn::
+   the given *pathsegments* in turn::
 
       >>> PurePosixPath('/etc').joinpath('passwd')
       PurePosixPath('/etc/passwd')
@@ -545,7 +546,7 @@ Pure paths provide the following methods
       PureWindowsPath('c:/Program Files')
 
 
-.. method:: PurePath.match(pattern)
+.. method:: PurePath.match(pattern, *, case_sensitive=None)
 
    Match this path against the provided glob-style pattern.  Return ``True``
    if matching is successful, ``False`` otherwise.
@@ -575,6 +576,11 @@ Pure paths provide the following methods
       >>> PureWindowsPath('b.py').match('*.PY')
       True
 
+   Set *case_sensitive* to ``True`` or ``False`` to override this behaviour.
+
+   .. versionadded:: 3.12
+      The *case_sensitive* argument.
+
 
 .. method:: PurePath.relative_to(other, walk_up=False)
 
@@ -680,6 +686,30 @@ Pure paths provide the following methods
       PureWindowsPath('README')
 
 
+.. method:: PurePath.with_segments(*pathsegments)
+
+   Create a new path object of the same type by combining the given
+   *pathsegments*. This method is called whenever a derivative path is created,
+   such as from :attr:`parent` and :meth:`relative_to`. Subclasses may
+   override this method to pass information to derivative paths, for example::
+
+      from pathlib import PurePosixPath
+
+      class MyPath(PurePosixPath):
+          def __init__(self, *pathsegments, session_id):
+              super().__init__(*pathsegments)
+              self.session_id = session_id
+
+          def with_segments(self, *pathsegments):
+              return type(self)(*pathsegments, session_id=self.session_id)
+
+      etc = MyPath('/etc', session_id=42)
+      hosts = etc / 'hosts'
+      print(hosts.session_id)  # 42
+
+   .. versionadded:: 3.12
+
+
 .. _concrete-paths:
 
 
@@ -819,9 +849,14 @@ call fails (for example because the path
    .. versionchanged:: 3.10
       The *follow_symlinks* parameter was added.
 
-.. method:: Path.exists()
+.. method:: Path.exists(*, follow_symlinks=True)
+
+   Return ``True`` if the path points to an existing file or directory.
 
-   Whether the path points to an existing file or directory::
+   This method normally follows symlinks; to check if a symlink exists, add
+   the argument ``follow_symlinks=False``.
+
+   ::
 
       >>> Path('.').exists()
       True
@@ -832,10 +867,8 @@ call fails (for example because the path
       >>> Path('nonexistentfile').exists()
       False
 
-   .. note::
-      If the path points to a symlink, :meth:`exists` returns whether the
-      symlink *points to* an existing file or directory.
-
+   .. versionchanged:: 3.12
+      The *follow_symlinks* parameter was added.
 
 .. method:: Path.expanduser()
 
@@ -852,7 +885,7 @@ call fails (for example because the path
    .. versionadded:: 3.5
 
 
-.. method:: Path.glob(pattern)
+.. method:: Path.glob(pattern, *, case_sensitive=None)
 
    Glob the given relative *pattern* in the directory represented by this path,
    yielding all matching files (of any kind)::
@@ -873,6 +906,11 @@ call fails (for example because the path
        PosixPath('setup.py'),
        PosixPath('test_pathlib.py')]
 
+   By default, or when the *case_sensitive* keyword-only argument is set to
+   ``None``, this method matches paths using platform-specific casing rules:
+   typically, case-sensitive on POSIX, and case-insensitive on Windows.
+   Set *case_sensitive* to ``True`` or ``False`` to override this behaviour.
+
    .. note::
       Using the "``**``" pattern in large directory trees may consume
       an inordinate amount of time.
@@ -883,6 +921,9 @@ call fails (for example because the path
       Return only directories if *pattern* ends with a pathname components
       separator (:data:`~os.sep` or :data:`~os.altsep`).
 
+   .. versionadded:: 3.12
+      The *case_sensitive* argument.
+
 .. method:: Path.group()
 
    Return the name of the group owning the file.  :exc:`KeyError` is raised
@@ -1268,7 +1309,7 @@ call fails (for example because the path
    .. versionadded:: 3.6
       The *strict* argument (pre-3.6 behavior is strict).
 
-.. method:: Path.rglob(pattern)
+.. method:: Path.rglob(pattern, *, case_sensitive=None)
 
    Glob the given relative *pattern* recursively.  This is like calling
    :func:`Path.glob` with "``**/``" added in front of the *pattern*, where
@@ -1281,12 +1322,20 @@ call fails (for example because the path
        PosixPath('setup.py'),
        PosixPath('test_pathlib.py')]
 
+   By default, or when the *case_sensitive* keyword-only argument is set to
+   ``None``, this method matches paths using platform-specific casing rules:
+   typically, case-sensitive on POSIX, and case-insensitive on Windows.
+   Set *case_sensitive* to ``True`` or ``False`` to override this behaviour.
+
    .. audit-event:: pathlib.Path.rglob self,pattern pathlib.Path.rglob
 
    .. versionchanged:: 3.11
       Return only directories if *pattern* ends with a pathname components
       separator (:data:`~os.sep` or :data:`~os.altsep`).
 
+   .. versionadded:: 3.12
+      The *case_sensitive* argument.
+
 .. method:: Path.rmdir()
 
    Remove this directory.  The directory must be empty.
diff -pruN 3.12.0~a7-1/Doc/library/pdb.rst 3.12.0~b1-1/Doc/library/pdb.rst
--- 3.12.0~a7-1/Doc/library/pdb.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/pdb.rst	2023-05-22 12:07:36.000000000 +0000
@@ -20,8 +20,8 @@ supports post-mortem debugging and can b
 
 .. index::
    single: Pdb (class in pdb)
-   module: bdb
-   module: cmd
+   pair: module; bdb
+   pair: module; cmd
 
 The debugger is extensible -- it is actually defined as the class :class:`Pdb`.
 This is currently undocumented but easily understood by reading the source.  The
@@ -36,73 +36,91 @@ extension interface uses the modules :mo
    Module :mod:`traceback`
       Standard interface to extract, format and print stack traces of Python programs.
 
-The debugger's prompt is ``(Pdb)``. Typical usage to run a program under control
-of the debugger is::
+The typical usage to break into the debugger is to insert::
 
-   >>> import pdb
-   >>> import mymodule
-   >>> pdb.run('mymodule.test()')
-   > <string>(0)?()
-   (Pdb) continue
-   > <string>(1)?()
+   import pdb; pdb.set_trace()
+
+Or::
+
+   breakpoint()
+
+at the location you want to break into the debugger, and then run the program.
+You can then step through the code following this statement, and continue
+running without the debugger using the :pdbcmd:`continue` command.
+
+.. versionadded:: 3.7
+   The built-in :func:`breakpoint()`, when called with defaults, can be used
+   instead of ``import pdb; pdb.set_trace()``.
+
+::
+
+   def double(x):
+      breakpoint()
+      return x * 2
+   val = 3
+   print(f"{val} * 2 is {double(val)}")
+
+The debugger's prompt is ``(Pdb)``, which is the indicator that you are in debug mode::
+
+   > ...(3)double()
+   -> return x * 2
+   (Pdb) p x
+   3
    (Pdb) continue
-   NameError: 'spam'
-   > <string>(1)?()
-   (Pdb)
+   3 * 2 is 6
 
 .. versionchanged:: 3.3
    Tab-completion via the :mod:`readline` module is available for commands and
    command arguments, e.g. the current global and local names are offered as
    arguments of the ``p`` command.
 
-:file:`pdb.py` can also be invoked as a script to debug other scripts.  For
+
+You can also invoke :mod:`pdb` from the command line to debug other scripts.  For
 example::
 
    python -m pdb myscript.py
 
-When invoked as a script, pdb will automatically enter post-mortem debugging if
+When invoked as a module, pdb will automatically enter post-mortem debugging if
 the program being debugged exits abnormally.  After post-mortem debugging (or
 after normal exit of the program), pdb will restart the program.  Automatic
 restarting preserves pdb's state (such as breakpoints) and in most cases is more
 useful than quitting the debugger upon program's exit.
 
 .. versionadded:: 3.2
-   :file:`pdb.py` now accepts a ``-c`` option that executes commands as if given
+   ``-c`` option is introduced to execute commands as if given
    in a :file:`.pdbrc` file, see :ref:`debugger-commands`.
 
 .. versionadded:: 3.7
-   :file:`pdb.py` now accepts a ``-m`` option that execute modules similar to the way
+   ``-m`` option is introduced to execute modules similar to the way
    ``python -m`` does. As with a script, the debugger will pause execution just
    before the first line of the module.
 
+Typical usage to execute a statement under control of the debugger is::
 
-The typical usage to break into the debugger is to insert::
-
-   import pdb; pdb.set_trace()
-
-at the location you want to break into the debugger, and then run the program.
-You can then step through the code following this statement, and continue
-running without the debugger using the :pdbcmd:`continue` command.
-
-.. versionadded:: 3.7
-   The built-in :func:`breakpoint()`, when called with defaults, can be used
-   instead of ``import pdb; pdb.set_trace()``.
+   >>> import pdb
+   >>> def f(x):
+   ...     print(1 / x)
+   >>> pdb.run("f(2)")
+   > <string>(1)<module>()
+   (Pdb) continue
+   0.5
+   >>>
 
 The typical usage to inspect a crashed program is::
 
    >>> import pdb
-   >>> import mymodule
-   >>> mymodule.test()
+   >>> def f(x):
+   ...     print(1 / x)
+   ...
+   >>> f(0)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
-     File "./mymodule.py", line 4, in test
-       test2()
-     File "./mymodule.py", line 3, in test2
-       print(spam)
-   NameError: spam
+     File "<stdin>", line 2, in f
+   ZeroDivisionError: division by zero
    >>> pdb.pm()
-   > ./mymodule.py(3)test2()
-   -> print(spam)
+   > <stdin>(2)f()
+   (Pdb) p x
+   0
    (Pdb)
 
 
@@ -245,6 +263,21 @@ the commands; the input is split at the
 middle of a quoted string. A workaround for strings with double semicolons
 is to use implicit string concatenation ``';'';'`` or ``";"";"``.
 
+To set a temporary global variable, use a *convenience variable*. A *convenience
+variable* is a variable whose name starts with ``$``.  For example, ``$foo = 1``
+sets a global variable ``$foo`` which you can use in the debugger session.  The
+*convenience variables* are cleared when the program resumes execution so it's
+less likely to interfere with your program compared to using normal variables
+like ``foo = 1``.
+
+There are three preset *convenience variables*:
+
+* ``$_frame``: the current frame you are debugging
+* ``$_retval``: the return value if the frame is returning
+* ``$_exception``: the exception if the frame is raising an exception
+
+.. versionadded:: 3.12
+
 .. index::
    pair: .pdbrc; file
    triple: debugger; configuration; file
@@ -275,7 +308,7 @@ can be overridden by the local file.
 
 .. pdbcommand:: w(here)
 
-   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.  An arrow (``>``)
    indicates the current frame, which determines the context of most commands.
 
 .. pdbcommand:: d(own) [count]
@@ -315,14 +348,14 @@ can be overridden by the local file.
    With a space separated list of breakpoint numbers, clear those breakpoints.
    Without argument, clear all breaks (but first ask confirmation).
 
-.. pdbcommand:: disable [bpnumber ...]
+.. pdbcommand:: disable bpnumber [bpnumber ...]
 
    Disable the breakpoints given as a space separated list of breakpoint
    numbers.  Disabling a breakpoint means it cannot cause the program to stop
    execution, but unlike clearing a breakpoint, it remains in the list of
    breakpoints and can be (re-)enabled.
 
-.. pdbcommand:: enable [bpnumber ...]
+.. pdbcommand:: enable bpnumber [bpnumber ...]
 
    Enable the breakpoints specified.
 
@@ -442,7 +475,7 @@ can be overridden by the local file.
 
 .. pdbcommand:: a(rgs)
 
-   Print the argument list of the current function.
+   Print the arguments of the current function and their current values.
 
 .. pdbcommand:: p expression
 
@@ -476,6 +509,50 @@ can be overridden by the local file.
 
    Without *expression*, list all display expressions for the current frame.
 
+   .. note::
+
+      Display evaluates *expression* and compares to the result of the previous
+      evaluation of *expression*, so when the result is mutable, display may not
+      be able to pick up the changes.
+
+   Example::
+
+      lst = []
+      breakpoint()
+      pass
+      lst.append(1)
+      print(lst)
+
+   Display won't realize ``lst`` has been changed because the result of evaluation
+   is modified in place by ``lst.append(1)`` before being compared::
+
+      > example.py(3)<module>()
+      -> pass
+      (Pdb) display lst
+      display lst: []
+      (Pdb) n
+      > example.py(4)<module>()
+      -> lst.append(1)
+      (Pdb) n
+      > example.py(5)<module>()
+      -> print(lst)
+      (Pdb)
+
+   You can do some tricks with copy mechanism to make it work::
+
+      > example.py(3)<module>()
+      -> pass
+      (Pdb) display lst[:]
+      display lst[:]: []
+      (Pdb) n
+      > example.py(4)<module>()
+      -> lst.append(1)
+      (Pdb) n
+      > example.py(5)<module>()
+      -> print(lst)
+      display lst[:]: [1]  [old: []]
+      (Pdb)
+
    .. versionadded:: 3.2
 
 .. pdbcommand:: undisplay [expression]
@@ -525,9 +602,17 @@ can be overridden by the local file.
 
    Execute the (one-line) *statement* in the context of the current stack frame.
    The exclamation point can be omitted unless the first word of the statement
-   resembles a debugger command.  To set a global variable, you can prefix the
-   assignment command with a :keyword:`global` statement on the same line,
-   e.g.::
+   resembles a debugger command, e.g.:
+
+   .. code-block:: none
+
+      (Pdb) ! n=42
+      (Pdb)
+
+   To set a global variable, you can prefix the assignment command with a
+   :keyword:`global` statement on the same line, e.g.:
+
+   .. code-block:: none
 
       (Pdb) global list_options; list_options = ['-l']
       (Pdb)
@@ -552,7 +637,7 @@ can be overridden by the local file.
 
 .. pdbcommand:: retval
 
-   Print the return value for the last return of a function.
+   Print the return value for the last return of the current function.
 
 .. rubric:: Footnotes
 
diff -pruN 3.12.0~a7-1/Doc/library/pkgutil.rst 3.12.0~b1-1/Doc/library/pkgutil.rst
--- 3.12.0~a7-1/Doc/library/pkgutil.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/pkgutil.rst	2023-05-22 12:07:36.000000000 +0000
@@ -25,9 +25,9 @@ support.
       from pkgutil import extend_path
       __path__ = extend_path(__path__, __name__)
 
-   This will add to the package's ``__path__`` all subdirectories of directories
-   on :data:`sys.path` named after the package.  This is useful if one wants to
-   distribute different parts of a single logical package as multiple
+   For each directory on :data:`sys.path` that has a subdirectory that matches the
+   package name, add the subdirectory to the package's :attr:`__path__`.  This is useful
+   if one wants to distribute different parts of a single logical package as multiple
    directories.
 
    It also looks for :file:`\*.pkg` files beginning where ``*`` matches the
@@ -48,33 +48,6 @@ support.
    this function to raise an exception (in line with :func:`os.path.isdir`
    behavior).
 
-
-.. class:: ImpImporter(dirname=None)
-
-   :pep:`302` Finder that wraps Python's "classic" import algorithm.
-
-   If *dirname* is a string, a :pep:`302` finder is created that searches that
-   directory.  If *dirname* is ``None``, a :pep:`302` finder is created that
-   searches the current :data:`sys.path`, plus any modules that are frozen or
-   built-in.
-
-   Note that :class:`ImpImporter` does not currently support being used by
-   placement on :data:`sys.meta_path`.
-
-   .. deprecated:: 3.3
-      This emulation is no longer needed, as the standard import mechanism
-      is now fully :pep:`302` compliant and available in :mod:`importlib`.
-
-
-.. class:: ImpLoader(fullname, file, filename, etc)
-
-   :term:`Loader <loader>` that wraps Python's "classic" import algorithm.
-
-   .. deprecated:: 3.3
-      This emulation is no longer needed, as the standard import mechanism
-      is now fully :pep:`302` compliant and available in :mod:`importlib`.
-
-
 .. function:: find_loader(fullname)
 
    Retrieve a module :term:`loader` for the given *fullname*.
@@ -82,7 +55,7 @@ support.
    This is a backwards compatibility wrapper around
    :func:`importlib.util.find_spec` that converts most failures to
    :exc:`ImportError` and only returns the loader rather than the full
-   :class:`ModuleSpec`.
+   :class:`importlib.machinery.ModuleSpec`.
 
    .. versionchanged:: 3.3
       Updated to be based directly on :mod:`importlib` rather than relying
@@ -91,6 +64,10 @@ support.
    .. versionchanged:: 3.4
       Updated to be based on :pep:`451`
 
+   .. deprecated-removed:: 3.12 3.14
+      Use :func:`importlib.util.find_spec` instead.
+
+
 .. function:: get_importer(path_item)
 
    Retrieve a :term:`finder` for the given *path_item*.
@@ -123,6 +100,9 @@ support.
    .. versionchanged:: 3.4
       Updated to be based on :pep:`451`
 
+   .. deprecated-removed:: 3.12 3.14
+      Use :func:`importlib.util.find_spec` instead.
+
 
 .. function:: iter_importers(fullname='')
 
diff -pruN 3.12.0~a7-1/Doc/library/plistlib.rst 3.12.0~b1-1/Doc/library/plistlib.rst
--- 3.12.0~a7-1/Doc/library/plistlib.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/plistlib.rst	2023-05-22 12:07:36.000000000 +0000
@@ -46,7 +46,7 @@ or :class:`datetime.datetime` objects.
 
 .. seealso::
 
-   `PList manual page <https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/PropertyLists/>`_
+   `PList manual page <https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/PropertyLists/>`_
       Apple's documentation of the file format.
 
 
diff -pruN 3.12.0~a7-1/Doc/library/posix.rst 3.12.0~b1-1/Doc/library/posix.rst
--- 3.12.0~a7-1/Doc/library/posix.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/posix.rst	2023-05-22 12:07:36.000000000 +0000
@@ -11,7 +11,7 @@ This module provides access to operating
 standardized by the C Standard and the POSIX standard (a thinly disguised Unix
 interface).
 
-.. index:: module: os
+.. index:: pair: module; os
 
 **Do not import this module directly.**  Instead, import the module :mod:`os`,
 which provides a *portable* version of this interface.  On Unix, the :mod:`os`
diff -pruN 3.12.0~a7-1/Doc/library/pprint.rst 3.12.0~b1-1/Doc/library/pprint.rst
--- 3.12.0~a7-1/Doc/library/pprint.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/pprint.rst	2023-05-22 12:07:36.000000000 +0000
@@ -159,7 +159,7 @@ The :mod:`pprint` module defines one cla
 
 .. function:: isreadable(object)
 
-   .. index:: builtin: eval
+   .. index:: pair: built-in function; eval
 
    Determine if the formatted representation of *object* is "readable", or can be
    used to reconstruct the value using :func:`eval`.  This always returns ``False``
@@ -218,7 +218,7 @@ created.
 
 .. method:: PrettyPrinter.isreadable(object)
 
-   .. index:: builtin: eval
+   .. index:: pair: built-in function; eval
 
    Determine if the formatted representation of the object is "readable," or can be
    used to reconstruct the value using :func:`eval`.  Note that this returns
diff -pruN 3.12.0~a7-1/Doc/library/pwd.rst 3.12.0~b1-1/Doc/library/pwd.rst
--- 3.12.0~a7-1/Doc/library/pwd.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/pwd.rst	2023-05-22 12:07:36.000000000 +0000
@@ -39,7 +39,7 @@ raised if the entry asked for cannot be
 
 .. note::
 
-   .. index:: module: crypt
+   .. index:: pair: module; crypt
 
    In traditional Unix the field ``pw_passwd`` usually contains a password
    encrypted with a DES derived algorithm (see module :mod:`crypt`).  However most
diff -pruN 3.12.0~a7-1/Doc/library/pyexpat.rst 3.12.0~b1-1/Doc/library/pyexpat.rst
--- 3.12.0~a7-1/Doc/library/pyexpat.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/pyexpat.rst	2023-05-22 12:07:36.000000000 +0000
@@ -33,7 +33,7 @@ can be set to handler functions.  When a
 parser, the handler functions are called for the character data and markup in
 the XML document.
 
-.. index:: module: pyexpat
+.. index:: pair: module; pyexpat
 
 This module uses the :mod:`pyexpat` module to provide access to the Expat
 parser.  Direct use of the :mod:`pyexpat` module is deprecated.
diff -pruN 3.12.0~a7-1/Doc/library/random.rst 3.12.0~b1-1/Doc/library/random.rst
--- 3.12.0~a7-1/Doc/library/random.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/random.rst	2023-05-22 12:07:36.000000000 +0000
@@ -334,8 +334,10 @@ be found in any statistics text.
 
 .. function:: gammavariate(alpha, beta)
 
-   Gamma distribution.  (*Not* the gamma function!)  Conditions on the
-   parameters are ``alpha > 0`` and ``beta > 0``.
+   Gamma distribution.  (*Not* the gamma function!)  The shape and
+   scale parameters, *alpha* and *beta*, must have positive values.
+   (Calling conventions vary and some sources define 'beta'
+   as the inverse of the scale).
 
    The probability distribution function is::
 
@@ -346,7 +348,8 @@ be found in any statistics text.
 
 .. function:: gauss(mu=0.0, sigma=1.0)
 
-   Normal distribution, also called the Gaussian distribution.  *mu* is the mean,
+   Normal distribution, also called the Gaussian distribution.
+   *mu* is the mean,
    and *sigma* is the standard deviation.  This is slightly faster than
    the :func:`normalvariate` function defined below.
 
diff -pruN 3.12.0~a7-1/Doc/library/readline.rst 3.12.0~b1-1/Doc/library/readline.rst
--- 3.12.0~a7-1/Doc/library/readline.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/readline.rst	2023-05-22 12:07:36.000000000 +0000
@@ -19,7 +19,7 @@ function.
 
 Readline keybindings may be configured via an initialization file, typically
 ``.inputrc`` in your home directory.  See `Readline Init File
-<https://tiswww.cwru.edu/php/chet/readline/rluserman.html#SEC9>`_
+<https://tiswww.cwru.edu/php/chet/readline/rluserman.html#Readline-Init-File>`_
 in the GNU Readline manual for information about the format and
 allowable constructs of that file, and the capabilities of the
 Readline library in general.
diff -pruN 3.12.0~a7-1/Doc/library/resource.rst 3.12.0~b1-1/Doc/library/resource.rst
--- 3.12.0~a7-1/Doc/library/resource.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/resource.rst	2023-05-22 12:07:36.000000000 +0000
@@ -244,7 +244,7 @@ platform.
    used by all of this user id's processes.
    This limit is enforced only if bit 1 of the vm.overcommit sysctl is set.
    Please see
-   `tuning(7) <https://www.freebsd.org/cgi/man.cgi?query=tuning&sektion=7>`__
+   `tuning(7) <https://man.freebsd.org/cgi/man.cgi?query=tuning&sektion=7>`__
    for a complete description of this sysctl.
 
    .. availability:: FreeBSD.
diff -pruN 3.12.0~a7-1/Doc/library/runpy.rst 3.12.0~b1-1/Doc/library/runpy.rst
--- 3.12.0~a7-1/Doc/library/runpy.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/runpy.rst	2023-05-22 12:07:36.000000000 +0000
@@ -30,7 +30,7 @@ The :mod:`runpy` module provides two fun
 .. function:: run_module(mod_name, init_globals=None, run_name=None, alter_sys=False)
 
    .. index::
-      module: __main__
+      pair: module; __main__
 
    Execute the code of the specified module and return the resulting module
    globals dictionary. The module's code is first located using the standard
@@ -101,7 +101,7 @@ The :mod:`runpy` module provides two fun
 .. function:: run_path(path_name, init_globals=None, run_name=None)
 
    .. index::
-      module: __main__
+      pair: module; __main__
 
    Execute the code at the named filesystem location and return the resulting
    module globals dictionary. As with a script name supplied to the CPython
diff -pruN 3.12.0~a7-1/Doc/library/sched.rst 3.12.0~b1-1/Doc/library/sched.rst
--- 3.12.0~a7-1/Doc/library/sched.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/sched.rst	2023-05-22 12:07:36.000000000 +0000
@@ -36,7 +36,7 @@ scheduler:
 Example::
 
    >>> import sched, time
-   >>> s = sched.scheduler(time.time, time.sleep)
+   >>> s = sched.scheduler(time.monotonic, time.sleep)
    >>> def print_time(a='default'):
    ...     print("From print_time", time.time(), a)
    ...
diff -pruN 3.12.0~a7-1/Doc/library/select.rst 3.12.0~b1-1/Doc/library/select.rst
--- 3.12.0~a7-1/Doc/library/select.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/select.rst	2023-05-22 12:07:36.000000000 +0000
@@ -505,7 +505,7 @@ Kqueue Objects
 Kevent Objects
 --------------
 
-https://www.freebsd.org/cgi/man.cgi?query=kqueue&sektion=2
+https://man.freebsd.org/cgi/man.cgi?query=kqueue&sektion=2
 
 .. attribute:: kevent.ident
 
diff -pruN 3.12.0~a7-1/Doc/library/shelve.rst 3.12.0~b1-1/Doc/library/shelve.rst
--- 3.12.0~a7-1/Doc/library/shelve.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/shelve.rst	2023-05-22 12:07:36.000000000 +0000
@@ -6,7 +6,7 @@
 
 **Source code:** :source:`Lib/shelve.py`
 
-.. index:: module: pickle
+.. index:: pair: module; pickle
 
 --------------
 
@@ -95,8 +95,8 @@ Restrictions
 ------------
 
   .. index::
-     module: dbm.ndbm
-     module: dbm.gnu
+     pair: module; dbm.ndbm
+     pair: module; dbm.gnu
 
 * The choice of which database package will be used (such as :mod:`dbm.ndbm` or
   :mod:`dbm.gnu`) depends on which interface is available.  Therefore it is not
diff -pruN 3.12.0~a7-1/Doc/library/shutil.rst 3.12.0~b1-1/Doc/library/shutil.rst
--- 3.12.0~a7-1/Doc/library/shutil.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/shutil.rst	2023-05-22 12:07:36.000000000 +0000
@@ -433,23 +433,43 @@ Directory and files operations
    When no *path* is specified, the results of :func:`os.environ` are used,
    returning either the "PATH" value or a fallback of :attr:`os.defpath`.
 
-   On Windows, the current directory is always prepended to the *path* whether
-   or not you use the default or provide your own, which is the behavior the
-   command shell uses when finding executables.  Additionally, when finding the
-   *cmd* in the *path*, the ``PATHEXT`` environment variable is checked.  For
-   example, if you call ``shutil.which("python")``, :func:`which` will search
-   ``PATHEXT`` to know that it should look for ``python.exe`` within the *path*
-   directories.  For example, on Windows::
+   On Windows, the current directory is prepended to the *path* if *mode* does
+   not include ``os.X_OK``. When the *mode* does include ``os.X_OK``, the
+   Windows API ``NeedCurrentDirectoryForExePathW`` will be consulted to
+   determine if the current directory should be prepended to *path*. To avoid
+   consulting the current working directory for executables: set the environment
+   variable ``NoDefaultCurrentDirectoryInExePath``.
+
+   Also on Windows, the ``PATHEXT`` variable is used to resolve commands
+   that may not already include an extension. For example, if you call
+   ``shutil.which("python")``, :func:`which` will search ``PATHEXT``
+   to know that it should look for ``python.exe`` within the *path*
+   directories. For example, on Windows::
 
       >>> shutil.which("python")
       'C:\\Python33\\python.EXE'
 
+   This is also applied when *cmd* is a path that contains a directory
+   component::
+
+      >> shutil.which("C:\\Python33\\python")
+      'C:\\Python33\\python.EXE'
+
    .. versionadded:: 3.3
 
    .. versionchanged:: 3.8
       The :class:`bytes` type is now accepted.  If *cmd* type is
       :class:`bytes`, the result type is also :class:`bytes`.
 
+   .. versionchanged:: 3.12
+      On Windows, the current directory is no longer prepended to the search
+      path if *mode* includes ``os.X_OK`` and WinAPI
+      ``NeedCurrentDirectoryForExePathW(cmd)`` is false, else the current
+      directory is prepended even if it is already in the search path;
+      ``PATHEXT`` is used now even when *cmd* includes a directory component
+      or ends with an extension that is in ``PATHEXT``; and filenames that
+      have no extension can now be found.
+
 .. exception:: Error
 
    This exception collects exceptions that are raised during a multi-file
@@ -642,7 +662,7 @@ provided.  They rely on the :mod:`zipfil
    Remove the archive format *name* from the list of supported formats.
 
 
-.. function:: unpack_archive(filename[, extract_dir[, format]])
+.. function:: unpack_archive(filename[, extract_dir[, format[, filter]]])
 
    Unpack an archive. *filename* is the full path of the archive.
 
@@ -656,6 +676,14 @@ provided.  They rely on the :mod:`zipfil
    registered for that extension.  In case none is found,
    a :exc:`ValueError` is raised.
 
+   The keyword-only *filter* argument is passed to the underlying unpacking
+   function. For zip files, *filter* is not accepted.
+   For tar files, it is recommended to set it to ``'data'``,
+   unless using features specific to tar and UNIX-like filesystems.
+   (See :ref:`tarfile-extraction-filter` for details.)
+   The ``'data'`` filter will become the default for tar files
+   in Python 3.14.
+
    .. audit-event:: shutil.unpack_archive filename,extract_dir,format shutil.unpack_archive
 
    .. warning::
@@ -668,6 +696,9 @@ provided.  They rely on the :mod:`zipfil
    .. versionchanged:: 3.7
       Accepts a :term:`path-like object` for *filename* and *extract_dir*.
 
+   .. versionchanged:: 3.12
+      Added the *filter* argument.
+
 .. function:: register_unpack_format(name, extensions, function[, extra_args[, description]])
 
    Registers an unpack format. *name* is the name of the format and
@@ -675,11 +706,14 @@ provided.  They rely on the :mod:`zipfil
    ``.zip`` for Zip files.
 
    *function* is the callable that will be used to unpack archives. The
-   callable will receive the path of the archive, followed by the directory
-   the archive must be extracted to.
+   callable will receive:
 
-   When provided, *extra_args* is a sequence of ``(name, value)`` tuples that
-   will be passed as keywords arguments to the callable.
+   - the path of the archive, as a positional argument;
+   - the directory the archive must be extracted to, as a positional argument;
+   - possibly a *filter* keyword argument, if it was given to
+     :func:`unpack_archive`;
+   - additional keyword arguments, specified by *extra_args* as a sequence
+     of ``(name, value)`` tuples.
 
    *description* can be provided to describe the format, and will be returned
    by the :func:`get_unpack_formats` function.
diff -pruN 3.12.0~a7-1/Doc/library/site.rst 3.12.0~b1-1/Doc/library/site.rst
--- 3.12.0~a7-1/Doc/library/site.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/site.rst	2023-05-22 12:07:36.000000000 +0000
@@ -51,7 +51,7 @@ searched for site-packages; otherwise th
 
 .. index::
    single: # (hash); comment
-   statement: import
+   pair: statement; import
 
 A path configuration file is a file whose name has the form :file:`{name}.pth`
 and exists in one of the four directories mentioned above; its contents are
@@ -109,7 +109,7 @@ directory precedes the :file:`foo` direc
 alphabetically before :file:`foo.pth`; and :file:`spam` is omitted because it is
 not mentioned in either path configuration file.
 
-.. index:: module: sitecustomize
+.. index:: pair: module; sitecustomize
 
 After these path manipulations, an attempt is made to import a module named
 :mod:`sitecustomize`, which can perform arbitrary site-specific customizations.
@@ -121,7 +121,7 @@ with :file:`pythonw.exe` on Windows (whi
 attempted output from :mod:`sitecustomize` is ignored.  Any other exception
 causes a silent and perhaps mysterious failure of the process.
 
-.. index:: module: usercustomize
+.. index:: pair: module; usercustomize
 
 After this, an attempt is made to import a module named :mod:`usercustomize`,
 which can perform arbitrary user-specific customizations, if
diff -pruN 3.12.0~a7-1/Doc/library/smtplib.rst 3.12.0~b1-1/Doc/library/smtplib.rst
--- 3.12.0~a7-1/Doc/library/smtplib.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/smtplib.rst	2023-05-22 12:07:36.000000000 +0000
@@ -25,7 +25,7 @@ Protocol) and :rfc:`1869` (SMTP Service
 
    An :class:`SMTP` instance encapsulates an SMTP connection.  It has methods
    that support a full repertoire of SMTP and ESMTP operations. If the optional
-   host and port parameters are given, the SMTP :meth:`connect` method is
+   *host* and *port* parameters are given, the SMTP :meth:`connect` method is
    called with those parameters during initialization.  If specified,
    *local_hostname* is used as the FQDN of the local host in the HELO/EHLO
    command.  Otherwise, the local hostname is found using
@@ -34,12 +34,12 @@ Protocol) and :rfc:`1869` (SMTP Service
    *timeout* parameter specifies a timeout in seconds for blocking operations
    like the connection attempt (if not specified, the global default timeout
    setting will be used).  If the timeout expires, :exc:`TimeoutError` is
-   raised.  The optional source_address parameter allows binding
+   raised.  The optional *source_address* parameter allows binding
    to some specific source address in a machine with multiple network
    interfaces, and/or to some specific source TCP port. It takes a 2-tuple
-   (host, port), for the socket to bind to as its source address before
-   connecting. If omitted (or if host or port are ``''`` and/or 0 respectively)
-   the OS default behavior will be used.
+   ``(host, port)``, for the socket to bind to as its source address before
+   connecting. If omitted (or if *host* or *port* are ``''`` and/or ``0``
+   respectively) the OS default behavior will be used.
 
    For normal use, you should only require the initialization/connect,
    :meth:`sendmail`, and :meth:`SMTP.quit` methods.
diff -pruN 3.12.0~a7-1/Doc/library/socket.rst 3.12.0~b1-1/Doc/library/socket.rst
--- 3.12.0~a7-1/Doc/library/socket.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/socket.rst	2023-05-22 12:07:36.000000000 +0000
@@ -19,7 +19,7 @@ all modern Unix systems, Windows, MacOS,
 
 .. include:: ../includes/wasm-notavail.rst
 
-.. index:: object: socket
+.. index:: pair: object; socket
 
 The Python interface is a straightforward transliteration of the Unix system
 call and library interface for sockets to Python's object-oriented style: the
@@ -509,6 +509,17 @@ Constants
    .. versionadded:: 3.9
 
 
+.. data:: AF_DIVERT
+          PF_DIVERT
+
+   These two constants, documented in the FreeBSD divert(4) manual page, are
+   also defined in the socket module.
+
+   .. availability:: FreeBSD >= 14.0.
+
+   .. versionadded:: 3.12
+
+
 .. data:: AF_PACKET
           PF_PACKET
           PACKET_*
@@ -1775,7 +1786,7 @@ to sockets.
    much data, if any, was successfully sent.
 
    .. versionchanged:: 3.5
-      The socket timeout is no more reset each time data is sent successfully.
+      The socket timeout is no longer reset each time data is sent successfully.
       The socket timeout is now the maximum total duration to send all data.
 
    .. versionchanged:: 3.5
@@ -1916,7 +1927,7 @@ to sockets.
 .. method:: socket.setsockopt(level, optname, None, optlen: int)
    :noindex:
 
-   .. index:: module: struct
+   .. index:: pair: module; struct
 
    Set the value of the given socket option (see the Unix manual page
    :manpage:`setsockopt(2)`).  The needed symbolic constants are defined in the
@@ -1998,8 +2009,8 @@ can be changed by calling :func:`setdefa
 
 * In *non-blocking mode*, operations fail (with an error that is unfortunately
   system-dependent) if they cannot be completed immediately: functions from the
-  :mod:`select` can be used to know when and whether a socket is available for
-  reading or writing.
+  :mod:`select` module can be used to know when and whether a socket is available
+  for reading or writing.
 
 * In *timeout mode*, operations fail if they cannot be completed within the
   timeout specified for the socket (they raise a :exc:`timeout` exception)
@@ -2188,7 +2199,7 @@ manager protocol instead, open a socket
     socket.socket(socket.AF_CAN, socket.SOCK_DGRAM, socket.CAN_BCM)
 
 After binding (:const:`CAN_RAW`) or connecting (:const:`CAN_BCM`) the socket, you
-can use the :meth:`socket.send`, and the :meth:`socket.recv` operations (and
+can use the :meth:`socket.send` and :meth:`socket.recv` operations (and
 their counterparts) on the socket object as usual.
 
 This last example might require special privileges::
diff -pruN 3.12.0~a7-1/Doc/library/socketserver.rst 3.12.0~b1-1/Doc/library/socketserver.rst
--- 3.12.0~a7-1/Doc/library/socketserver.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/socketserver.rst	2023-05-22 12:07:36.000000000 +0000
@@ -140,9 +140,16 @@ server is the address family.
            ForkingUDPServer
            ThreadingTCPServer
            ThreadingUDPServer
+           ForkingUnixStreamServer
+           ForkingUnixDatagramServer
+           ThreadingUnixStreamServer
+           ThreadingUnixDatagramServer
 
    These classes are pre-defined using the mix-in classes.
 
+.. versionadded:: 3.12
+   The ``ForkingUnixStreamServer`` and ``ForkingUnixDatagramServer`` classes
+   were added.
 
 To implement a service, you must derive a class from :class:`BaseRequestHandler`
 and redefine its :meth:`~BaseRequestHandler.handle` method.
diff -pruN 3.12.0~a7-1/Doc/library/sqlite3.rst 3.12.0~b1-1/Doc/library/sqlite3.rst
--- 3.12.0~a7-1/Doc/library/sqlite3.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/sqlite3.rst	2023-05-22 12:07:36.000000000 +0000
@@ -310,7 +310,7 @@ Module functions
        to avoid data corruption.
        See :attr:`threadsafety` for more information.
 
-   :param Connection factory:
+   :param ~sqlite3.Connection factory:
        A custom subclass of :class:`Connection` to create the connection with,
        if not the default :class:`Connection` class.
 
@@ -337,7 +337,7 @@ Module functions
        The default will change to ``False`` in a future Python release.
    :type autocommit: bool
 
-   :rtype: Connection
+   :rtype: ~sqlite3.Connection
 
    .. audit-event:: sqlite3.connect database sqlite3.connect
    .. audit-event:: sqlite3.connect/handle connection_handle sqlite3.connect
@@ -573,6 +573,38 @@ Module constants
       package, a third-party library which used to upstream changes to
       :mod:`!sqlite3`. Today, it carries no meaning or practical value.
 
+.. _sqlite3-dbconfig-constants:
+
+.. data:: SQLITE_DBCONFIG_DEFENSIVE
+          SQLITE_DBCONFIG_DQS_DDL
+          SQLITE_DBCONFIG_DQS_DML
+          SQLITE_DBCONFIG_ENABLE_FKEY
+          SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER
+          SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION
+          SQLITE_DBCONFIG_ENABLE_QPSG
+          SQLITE_DBCONFIG_ENABLE_TRIGGER
+          SQLITE_DBCONFIG_ENABLE_VIEW
+          SQLITE_DBCONFIG_LEGACY_ALTER_TABLE
+          SQLITE_DBCONFIG_LEGACY_FILE_FORMAT
+          SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE
+          SQLITE_DBCONFIG_RESET_DATABASE
+          SQLITE_DBCONFIG_TRIGGER_EQP
+          SQLITE_DBCONFIG_TRUSTED_SCHEMA
+          SQLITE_DBCONFIG_WRITABLE_SCHEMA
+
+   These constants are used for the :meth:`Connection.setconfig`
+   and :meth:`~Connection.getconfig` methods.
+
+   The availability of these constants varies depending on the version of SQLite
+   Python was compiled with.
+
+   .. versionadded:: 3.12
+
+   .. seealso::
+
+     https://www.sqlite.org/c3ref/c_dbconfig_defensive.html
+        SQLite docs: Database Connection Configuration Options
+
 
 .. _sqlite3-connection-objects:
 
@@ -1041,12 +1073,25 @@ Connection objects
          (2, 'broccoli pie', 'broccoli cheese onions flour')
          (3, 'pumpkin pie', 'pumpkin sugar flour butter')
 
-   .. method:: load_extension(path, /)
+   .. method:: load_extension(path, /, *, entrypoint=None)
 
-      Load an SQLite extension from a shared library located at *path*.
+      Load an SQLite extension from a shared library.
       Enable extension loading with :meth:`enable_load_extension` before
       calling this method.
 
+      :param str path:
+
+         The path to the SQLite extension.
+
+      :param entrypoint:
+
+         Entry point name.
+         If ``None`` (the default),
+         SQLite will come up with an entry point name of its own;
+         see the SQLite docs `Loading an Extension`_ for details.
+
+      :type entrypoint: str | None
+
       .. audit-event:: sqlite3.load_extension connection,path sqlite3.Connection.load_extension
 
       .. versionadded:: 3.2
@@ -1054,6 +1099,11 @@ Connection objects
       .. versionchanged:: 3.10
          Added the ``sqlite3.load_extension`` auditing event.
 
+      .. versionadded:: 3.12
+         The *entrypoint* parameter.
+
+   .. _Loading an Extension: https://www.sqlite.org/loadext.html#loading_an_extension_
+
    .. method:: iterdump
 
       Return an :term:`iterator` to dump the database as SQL source code.
@@ -1079,7 +1129,7 @@ Connection objects
       Works even if the database is being accessed by other clients
       or concurrently by the same connection.
 
-      :param Connection target:
+      :param ~sqlite3.Connection target:
           The database connection to save the backup to.
 
       :param int pages:
@@ -1201,6 +1251,30 @@ Connection objects
    .. _SQLite limit category: https://www.sqlite.org/c3ref/c_limit_attached.html
 
 
+   .. method:: getconfig(op, /)
+
+      Query a boolean connection configuration option.
+
+      :param int op:
+         A :ref:`SQLITE_DBCONFIG code <sqlite3-dbconfig-constants>`.
+
+      :rtype: bool
+
+      .. versionadded:: 3.12
+
+   .. method:: setconfig(op, enable=True, /)
+
+      Set a boolean connection configuration option.
+
+      :param int op:
+         A :ref:`SQLITE_DBCONFIG code <sqlite3-dbconfig-constants>`.
+
+      :param bool enable:
+         ``True`` if the configuration option should be enabled (default);
+         ``False`` if it should be disabled.
+
+      .. versionadded:: 3.12
+
    .. method:: serialize(*, name="main")
 
       Serialize a database into a :class:`bytes` object.  For an
@@ -1456,12 +1530,12 @@ Cursor objects
 
       For every item in *parameters*,
       repeatedly execute the :ref:`parameterized <sqlite3-placeholders>`
-      SQL statement *sql*.
+      :abbr:`DML (Data Manipulation Language)` SQL statement *sql*.
 
       Uses the same implicit transaction handling as :meth:`~Cursor.execute`.
 
       :param str sql:
-         A single SQL :abbr:`DML (Data Manipulation Language)` statement.
+         A single SQL DML statement.
 
       :param parameters:
          An :term:`!iterable` of parameters to bind with
@@ -1484,6 +1558,13 @@ Cursor objects
          # cur is an sqlite3.Cursor object
          cur.executemany("INSERT INTO data VALUES(?)", rows)
 
+      .. note::
+
+         Any resulting rows are discarded,
+         including DML statements with `RETURNING clauses`_.
+
+      .. _RETURNING clauses: https://www.sqlite.org/lang_returning.html
+
       .. deprecated-removed:: 3.12 3.14
 
          :exc:`DeprecationWarning` is emitted if
@@ -1613,7 +1694,10 @@ Cursor objects
       ``INSERT``, ``UPDATE``, ``DELETE``, and ``REPLACE`` statements;
       is ``-1`` for other statements,
       including :abbr:`CTE (Common Table Expression)` queries.
-      It is only updated by the :meth:`execute` and :meth:`executemany` methods.
+      It is only updated by the :meth:`execute` and :meth:`executemany` methods,
+      after the statement has run to completion.
+      This means that any resulting rows must be fetched in order for
+      :attr:`!rowcount` to be updated.
 
    .. attribute:: row_factory
 
diff -pruN 3.12.0~a7-1/Doc/library/ssl.rst 3.12.0~b1-1/Doc/library/ssl.rst
--- 3.12.0~a7-1/Doc/library/ssl.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/ssl.rst	2023-05-22 12:07:36.000000000 +0000
@@ -1719,7 +1719,7 @@ to speed up repeated connections from th
    .. versionadded:: 3.3
 
    .. seealso::
-      `SSL/TLS & Perfect Forward Secrecy <https://vincent.bernat.im/en/blog/2011-ssl-perfect-forward-secrecy>`_
+      `SSL/TLS & Perfect Forward Secrecy <https://vincent.bernat.ch/en/blog/2011-ssl-perfect-forward-secrecy>`_
          Vincent Bernat.
 
 .. method:: SSLContext.wrap_socket(sock, server_side=False, \
diff -pruN 3.12.0~a7-1/Doc/library/statistics.rst 3.12.0~b1-1/Doc/library/statistics.rst
--- 3.12.0~a7-1/Doc/library/statistics.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/statistics.rst	2023-05-22 12:07:36.000000000 +0000
@@ -22,7 +22,7 @@ This module provides functions for calcu
 numeric (:class:`~numbers.Real`-valued) data.
 
 The module is not intended to be a competitor to third-party libraries such
-as `NumPy <https://numpy.org>`_, `SciPy <https://www.scipy.org/>`_, or
+as `NumPy <https://numpy.org>`_, `SciPy <https://scipy.org/>`_, or
 proprietary full-featured statistics packages aimed at professional
 statisticians such as Minitab, SAS and Matlab. It is aimed at the level of
 graphing and scientific calculators.
diff -pruN 3.12.0~a7-1/Doc/library/stdtypes.rst 3.12.0~b1-1/Doc/library/stdtypes.rst
--- 3.12.0~a7-1/Doc/library/stdtypes.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/stdtypes.rst	2023-05-22 12:07:36.000000000 +0000
@@ -32,8 +32,8 @@ Truth Value Testing
 ===================
 
 .. index::
-   statement: if
-   statement: while
+   pair: statement; if
+   pair: statement; while
    pair: truth; value
    pair: Boolean; operations
    single: false
@@ -61,8 +61,8 @@ objects considered false:
   ``range(0)``
 
 .. index::
-   operator: or
-   operator: and
+   pair: operator; or
+   pair: operator; and
    single: False
    single: True
 
@@ -95,9 +95,9 @@ These are the Boolean operations, ordere
 +-------------+---------------------------------+-------+
 
 .. index::
-   operator: and
-   operator: or
-   operator: not
+   pair: operator; and
+   pair: operator; or
+   pair: operator; not
 
 Notes:
 
@@ -122,14 +122,14 @@ Comparisons
 .. index::
    pair: chaining; comparisons
    pair: operator; comparison
-   operator: ==
-   operator: < (less)
-   operator: <=
-   operator: > (greater)
-   operator: >=
-   operator: !=
-   operator: is
-   operator: is not
+   pair: operator; ==
+   pair: operator; < (less)
+   pair: operator; <=
+   pair: operator; > (greater)
+   pair: operator; >=
+   pair: operator; !=
+   pair: operator; is
+   pair: operator; is not
 
 There are eight comparison operations in Python.  They all have the same
 priority (which is higher than that of the Boolean operations).  Comparisons can
@@ -192,8 +192,8 @@ customized; also they can be applied to
 exception.
 
 .. index::
-   operator: in
-   operator: not in
+   pair: operator; in
+   pair: operator; not in
 
 Two more operations with the same syntactic priority, :keyword:`in` and
 :keyword:`not in`, are supported by types that are :term:`iterable` or
@@ -205,11 +205,11 @@ Numeric Types --- :class:`int`, :class:`
 ================================================================
 
 .. index::
-   object: numeric
-   object: Boolean
-   object: integer
-   object: floating point
-   object: complex number
+   pair: object; numeric
+   pair: object; Boolean
+   pair: object; integer
+   pair: object; floating point
+   pair: object; complex number
    pair: C; language
 
 There are three distinct numeric types: :dfn:`integers`, :dfn:`floating
@@ -244,20 +244,20 @@ and imaginary parts.
 
 .. index::
    single: arithmetic
-   builtin: int
-   builtin: float
-   builtin: complex
+   pair: built-in function; int
+   pair: built-in function; float
+   pair: built-in function; complex
    single: operator; + (plus)
    single: + (plus); unary operator
    single: + (plus); binary operator
    single: operator; - (minus)
    single: - (minus); unary operator
    single: - (minus); binary operator
-   operator: * (asterisk)
-   operator: / (slash)
-   operator: //
-   operator: % (percent)
-   operator: **
+   pair: operator; * (asterisk)
+   pair: operator; / (slash)
+   pair: operator; //
+   pair: operator; % (percent)
+   pair: operator; **
 
 Python fully supports mixed arithmetic: when a binary arithmetic operator has
 operands of different numeric types, the operand with the "narrower" type is
@@ -330,7 +330,7 @@ Notes:
 
 (3)
    .. index::
-      module: math
+      pair: module; math
       single: floor() (in module math)
       single: ceil() (in module math)
       single: trunc() (in module math)
@@ -392,12 +392,12 @@ Bitwise Operations on Integer Types
    pair: bitwise; operations
    pair: shifting; operations
    pair: masking; operations
-   operator: | (vertical bar)
-   operator: ^ (caret)
-   operator: & (ampersand)
-   operator: <<
-   operator: >>
-   operator: ~ (tilde)
+   pair: operator; | (vertical bar)
+   pair: operator; ^ (caret)
+   pair: operator; & (ampersand)
+   pair: operator; <<
+   pair: operator; >>
+   pair: operator; ~ (tilde)
 
 Bitwise operations only make sense for integers. The result of bitwise
 operations is calculated as though carried out in two's complement with an
@@ -802,6 +802,39 @@ number, :class:`float`, or :class:`compl
            hash_value = -2
        return hash_value
 
+.. _typebool:
+
+Boolean Type - :class:`bool`
+============================
+
+Booleans represent truth values. The :class:`bool` type has exactly two
+constant instances: ``True`` and ``False``.
+
+.. index::
+   single: False
+   single: True
+   pair: Boolean; values
+
+The built-in function :func:`bool`  converts any value to a boolean, if the
+value can be interpreted as a truth value (see section :ref:`truth` above).
+
+For logical operations, use the :ref:`boolean operators <boolean>` ``and``,
+``or`` and ``not``.
+When applying the bitwise operators ``&``, ``|``, ``^`` to two booleans, they
+return a bool equivalent to the logical operations "and", "or", "xor". However,
+the logical operators ``and``, ``or`` and ``!=`` should be preferred
+over ``&``, ``|`` and ``^``.
+
+.. deprecated:: 3.12
+
+   The use of the bitwise inversion operator ``~`` is deprecated and will
+   raise an error in Python 3.14.
+
+:class:`bool` is a subclass of :class:`int` (see :ref:`typesnumeric`). In
+many numeric contexts, ``False`` and ``True`` behave like the integers 0 and 1, respectively.
+However, relying on this is discouraged; explicitly convert using :func:`int`
+instead.
+
 .. _typeiter:
 
 Iterator Types
@@ -894,7 +927,7 @@ described in dedicated sections.
 Common Sequence Operations
 --------------------------
 
-.. index:: object: sequence
+.. index:: pair: object; sequence
 
 The operations in the following table are supported by most sequence types,
 both mutable and immutable. The :class:`collections.abc.Sequence` ABC is
@@ -912,15 +945,15 @@ operations have the same priority as the
 
 .. index::
    triple: operations on; sequence; types
-   builtin: len
-   builtin: min
-   builtin: max
+   pair: built-in function; len
+   pair: built-in function; min
+   pair: built-in function; max
    pair: concatenation; operation
    pair: repetition; operation
    pair: subscript; operation
    pair: slice; operation
-   operator: in
-   operator: not in
+   pair: operator; in
+   pair: operator; not in
    single: count() (sequence method)
    single: index() (sequence method)
 
@@ -1079,8 +1112,8 @@ Immutable Sequence Types
 
 .. index::
    triple: immutable; sequence; types
-   object: tuple
-   builtin: hash
+   pair: object; tuple
+   pair: built-in function; hash
 
 The only operation that immutable sequence types generally implement that is
 not also implemented by mutable sequence types is support for the :func:`hash`
@@ -1101,8 +1134,8 @@ Mutable Sequence Types
 
 .. index::
    triple: mutable; sequence; types
-   object: list
-   object: bytearray
+   pair: object; list
+   pair: object; bytearray
 
 The operations in the following table are defined on mutable sequence types.
 The :class:`collections.abc.MutableSequence` ABC is provided to make it
@@ -1119,7 +1152,7 @@ accepts integers that meet the value res
    triple: operations on; list; type
    pair: subscript; assignment
    pair: slice; assignment
-   statement: del
+   pair: statement; del
    single: append() (sequence method)
    single: clear() (sequence method)
    single: copy() (sequence method)
@@ -1219,7 +1252,7 @@ Notes:
 Lists
 -----
 
-.. index:: object: list
+.. index:: pair: object; list
 
 Lists are mutable sequences, typically used to store collections of
 homogeneous items (where the precise degree of similarity will vary by
@@ -1298,7 +1331,7 @@ application).
 Tuples
 ------
 
-.. index:: object: tuple
+.. index:: pair: object; tuple
 
 Tuples are immutable sequences, typically used to store collections of
 heterogeneous data (such as the 2-tuples produced by the :func:`enumerate`
@@ -1342,7 +1375,7 @@ choice than a simple tuple object.
 Ranges
 ------
 
-.. index:: object: range
+.. index:: pair: object; range
 
 The :class:`range` type represents an immutable sequence of numbers and is
 commonly used for looping a specific number of times in :keyword:`for`
@@ -1467,7 +1500,7 @@ objects that compare equal might have di
 .. index::
    single: string; text sequence type
    single: str (built-in class); (see also string)
-   object: string
+   pair: object; string
 
 .. _textseq:
 
@@ -1501,7 +1534,7 @@ Since there is no separate "character" t
 strings of length 1. That is, for a non-empty string *s*, ``s[0] == s[0:1]``.
 
 .. index::
-   object: io.StringIO
+   pair: object; io.StringIO
 
 There is also no mutable string type, but :meth:`str.join` or
 :class:`io.StringIO` can be used to efficiently construct strings from
@@ -1567,7 +1600,7 @@ String Methods
 --------------
 
 .. index::
-   module: re
+   pair: module; re
 
 Strings implement all of the :ref:`common <typesseq-common>` sequence
 operations, along with the additional methods described below.
@@ -1605,8 +1638,8 @@ expression support in the :mod:`re` modu
    converts it to ``"ss"``.
 
    The casefolding algorithm is
-   `described in section 3.13 of the Unicode Standard
-   <http://www.unicode.org/versions/Unicode15.0.0/ch03.pdf#G53253>`__.
+   `described in section 3.13 'Default Case Folding' of the Unicode Standard
+   <https://www.unicode.org/versions/Unicode15.0.0/ch03.pdf>`__.
 
    .. versionadded:: 3.3
 
@@ -1768,8 +1801,9 @@ expression support in the :mod:`re` modu
    one character, ``False`` otherwise.  Alphabetic characters are those characters defined
    in the Unicode character database as "Letter", i.e., those with general category
    property being one of "Lm", "Lt", "Lu", "Ll", or "Lo".  Note that this is different
-   from the `Alphabetic property defined in the Unicode Standard
-   <https://www.unicode.org/versions/Unicode15.0.0/ch04.pdf#G91002>`_.
+   from the `Alphabetic property defined in the section 4.10 'Letters, Alphabetic, and
+   Ideographic' of the Unicode Standard
+   <https://www.unicode.org/versions/Unicode15.0.0/ch04.pdf>`_.
 
 
 .. method:: str.isascii()
@@ -1904,8 +1938,8 @@ expression support in the :mod:`re` modu
    lowercase.
 
    The lowercasing algorithm used is
-   `described in section 3.13 of the Unicode Standard
-   <https://www.unicode.org/versions/Unicode15.0.0/ch03.pdf#G34078>`__.
+   `described in section 3.13 'Default Case Folding' of the Unicode Standard
+   <https://www.unicode.org/versions/Unicode15.0.0/ch03.pdf>`__.
 
 
 .. method:: str.lstrip([chars])
@@ -2250,8 +2284,8 @@ expression support in the :mod:`re` modu
    titlecase).
 
    The uppercasing algorithm used is
-   `described in section 3.13 of the Unicode Standard
-   <https://www.unicode.org/versions/Unicode15.0.0/ch03.pdf#G34078>`__.
+   `described in section 3.13 'Default Case Folding' of the Unicode Standard
+   <https://www.unicode.org/versions/Unicode15.0.0/ch03.pdf>`__.
 
 
 .. method:: str.zfill(width)
@@ -2474,10 +2508,10 @@ Binary Sequence Types --- :class:`bytes`
 =================================================================================
 
 .. index::
-   object: bytes
-   object: bytearray
-   object: memoryview
-   module: array
+   pair: object; bytes
+   pair: object; bytearray
+   pair: object; memoryview
+   pair: module; array
 
 The core built-in types for manipulating binary data are :class:`bytes` and
 :class:`bytearray`. They are supported by :class:`memoryview` which uses
@@ -2492,7 +2526,7 @@ The :mod:`array` module supports efficie
 Bytes Objects
 -------------
 
-.. index:: object: bytes
+.. index:: pair: object; bytes
 
 Bytes objects are immutable sequences of single bytes. Since many major
 binary protocols are based on the ASCII text encoding, bytes objects offer
@@ -2599,7 +2633,7 @@ always convert a bytes object into a lis
 Bytearray Objects
 -----------------
 
-.. index:: object: bytearray
+.. index:: pair: object; bytearray
 
 :class:`bytearray` objects are a mutable counterpart to :class:`bytes`
 objects.
@@ -3714,12 +3748,15 @@ copying.
    types such as :class:`bytes` and :class:`bytearray`, an element is a single
    byte, but other types such as :class:`array.array` may have bigger elements.
 
-   ``len(view)`` is equal to the length of :class:`~memoryview.tolist`.
-   If ``view.ndim = 0``, the length is 1. If ``view.ndim = 1``, the length
-   is equal to the number of elements in the view. For higher dimensions,
-   the length is equal to the length of the nested list representation of
-   the view. The :class:`~memoryview.itemsize` attribute will give you the
-   number of bytes in a single element.
+   ``len(view)`` is equal to the length of :class:`~memoryview.tolist`, which
+   is the nested list representation of the view. If ``view.ndim = 1``,
+   this is equal to the number of elements in the view.
+
+   .. versionchanged:: 3.12
+      If ``view.ndim == 0``, ``len(view)`` now raises :exc:`TypeError` instead of returning 1.
+
+   The :class:`~memoryview.itemsize` attribute will give you the number of
+   bytes in a single element.
 
    A :class:`memoryview` supports slicing and indexing to expose its data.
    One-dimensional slicing will result in a subview::
@@ -4175,7 +4212,7 @@ copying.
 Set Types --- :class:`set`, :class:`frozenset`
 ==============================================
 
-.. index:: object: set
+.. index:: pair: object; set
 
 A :dfn:`set` object is an unordered collection of distinct :term:`hashable` objects.
 Common uses include membership testing, removing duplicates from a sequence, and
@@ -4377,12 +4414,12 @@ Mapping Types --- :class:`dict`
 ===============================
 
 .. index::
-   object: mapping
-   object: dictionary
+   pair: object; mapping
+   pair: object; dictionary
    triple: operations on; mapping; types
    triple: operations on; dictionary; type
-   statement: del
-   builtin: len
+   pair: statement; del
+   pair: built-in function; len
 
 A :term:`mapping` object maps :term:`hashable` values to arbitrary objects.
 Mappings are mutable objects.  There is currently only one standard mapping
@@ -4852,7 +4889,7 @@ Generic Alias Type
 ------------------
 
 .. index::
-   object: GenericAlias
+   pair: object; GenericAlias
    pair: Generic; Alias
 
 ``GenericAlias`` objects are generally created by
@@ -5107,7 +5144,7 @@ Union Type
 ----------
 
 .. index::
-   object: Union
+   pair: object; Union
    pair: union; type
 
 A union object holds the value of the ``|`` (bitwise or) operation on
@@ -5264,7 +5301,7 @@ See :ref:`function` for more information
 Methods
 -------
 
-.. index:: object: method
+.. index:: pair: object; method
 
 Methods are functions that are called using the attribute notation. There are
 two flavors: built-in methods (such as :meth:`append` on lists) and class
@@ -5311,7 +5348,7 @@ Code Objects
 ------------
 
 .. index::
-   builtin: compile
+   pair: built-in function; compile
    single: __code__ (function object attribute)
 
 Code objects are used by the implementation to represent "pseudo-compiled"
@@ -5325,8 +5362,8 @@ Accessing ``__code__`` raises an :ref:`a
 ``object.__getattr__`` with arguments ``obj`` and ``"__code__"``.
 
 .. index::
-   builtin: exec
-   builtin: eval
+   pair: built-in function; exec
+   pair: built-in function; eval
 
 A code object can be executed or evaluated by passing it (instead of a source
 string) to the :func:`exec` or :func:`eval`  built-in functions.
@@ -5340,8 +5377,8 @@ Type Objects
 ------------
 
 .. index::
-   builtin: type
-   module: types
+   pair: built-in function; type
+   pair: module; types
 
 Type objects represent the various object types.  An object's type is accessed
 by the built-in function :func:`type`.  There are no special operations on
@@ -5390,27 +5427,6 @@ information.  There is exactly one ``Not
 It is written as ``NotImplemented``.
 
 
-.. _bltin-boolean-values:
-
-Boolean Values
---------------
-
-Boolean values are the two constant objects ``False`` and ``True``.  They are
-used to represent truth values (although other values can also be considered
-false or true).  In numeric contexts (for example when used as the argument to
-an arithmetic operator), they behave like the integers 0 and 1, respectively.
-The built-in function :func:`bool` can be used to convert any value to a
-Boolean, if the value can be interpreted as a truth value (see section
-:ref:`truth` above).
-
-.. index::
-   single: False
-   single: True
-   pair: Boolean; values
-
-They are written as ``False`` and ``True``, respectively.
-
-
 .. _typesinternal:
 
 Internal Objects
diff -pruN 3.12.0~a7-1/Doc/library/string.rst 3.12.0~b1-1/Doc/library/string.rst
--- 3.12.0~a7-1/Doc/library/string.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/string.rst	2023-05-22 12:07:36.000000000 +0000
@@ -235,7 +235,7 @@ dictionary keys (e.g., the strings ``'10
 The *arg_name* can be followed by any number of index or
 attribute expressions. An expression of the form ``'.name'`` selects the named
 attribute using :func:`getattr`, while an expression of the form ``'[index]'``
-does an index lookup using :func:`__getitem__`.
+does an index lookup using :meth:`~object.__getitem__`.
 
 .. versionchanged:: 3.1
    The positional argument specifiers can be omitted for :meth:`str.format`,
@@ -254,10 +254,10 @@ Some simple format string examples::
    "Units destroyed: {players[0]}"   # First element of keyword argument 'players'.
 
 The *conversion* field causes a type coercion before formatting.  Normally, the
-job of formatting a value is done by the :meth:`__format__` method of the value
+job of formatting a value is done by the :meth:`~object.__format__` method of the value
 itself.  However, in some cases it is desirable to force a type to be formatted
 as a string, overriding its own definition of formatting.  By converting the
-value to a string before calling :meth:`__format__`, the normal formatting logic
+value to a string before calling :meth:`~object.__format__`, the normal formatting logic
 is bypassed.
 
 Three conversion flags are currently supported: ``'!s'`` which calls :func:`str`
diff -pruN 3.12.0~a7-1/Doc/library/struct.rst 3.12.0~b1-1/Doc/library/struct.rst
--- 3.12.0~a7-1/Doc/library/struct.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/struct.rst	2023-05-22 12:07:36.000000000 +0000
@@ -602,4 +602,4 @@ The :mod:`struct` module also defines th
 
 .. _ieee 754 standard: https://en.wikipedia.org/wiki/IEEE_754-2008_revision
 
-.. _IETF RFC 1700: https://tools.ietf.org/html/rfc1700
+.. _IETF RFC 1700: https://datatracker.ietf.org/doc/html/rfc1700
diff -pruN 3.12.0~a7-1/Doc/library/subprocess.rst 3.12.0~b1-1/Doc/library/subprocess.rst
--- 3.12.0~a7-1/Doc/library/subprocess.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/subprocess.rst	2023-05-22 12:07:36.000000000 +0000
@@ -919,9 +919,12 @@ Reassigning them to new values is unsupp
 
 .. attribute:: Popen.returncode
 
-   The child return code, set by :meth:`poll` and :meth:`wait` (and indirectly
-   by :meth:`communicate`).  A ``None`` value indicates that the process
-   hasn't terminated yet.
+   The child return code. Initially ``None``, :attr:`returncode` is set by
+   a call to the :meth:`poll`, :meth:`wait`, or :meth:`communicate` methods
+   if they detect that the process has terminated.
+
+   A ``None`` value indicates that the process hadn't yet terminated at the
+   time of the last method call.
 
    A negative value ``-N`` indicates that the child was terminated by signal
    ``N`` (POSIX only).
diff -pruN 3.12.0~a7-1/Doc/library/superseded.rst 3.12.0~b1-1/Doc/library/superseded.rst
--- 3.12.0~a7-1/Doc/library/superseded.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/superseded.rst	2023-05-22 12:07:36.000000000 +0000
@@ -17,7 +17,6 @@ backwards compatibility. They have been
    chunk.rst
    crypt.rst
    imghdr.rst
-   imp.rst
    mailcap.rst
    msilib.rst
    nis.rst
diff -pruN 3.12.0~a7-1/Doc/library/sys.rst 3.12.0~b1-1/Doc/library/sys.rst
--- 3.12.0~a7-1/Doc/library/sys.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/sys.rst	2023-05-22 12:07:36.000000000 +0000
@@ -220,6 +220,10 @@ always available.
 
    .. audit-event:: sys._current_exceptions "" sys._current_exceptions
 
+   .. versionchanged:: 3.12
+      Each value in the dictionary is now a single exception instance, rather
+      than a 3-tuple as returned from ``sys.exc_info()``.
+
 .. function:: breakpointhook()
 
    This hook function is called by built-in :func:`breakpoint`.  By default,
@@ -440,7 +444,7 @@ always available.
    object <traceback-objects>` which typically encapsulates the call
    stack at the point where the exception last occurred.
 
-   .. index:: object: traceback
+   .. index:: pair: object; traceback
 
    If no exception is being handled anywhere on the stack, this function
    return a tuple containing three ``None`` values.
@@ -666,6 +670,13 @@ always available.
    .. versionadded:: 3.4
 
 
+.. function:: getunicodeinternedsize()
+
+   Return the number of unicode objects that have been interned.
+
+   .. versionadded:: 3.12
+
+
 .. function:: getandroidapilevel()
 
    Return the build time API version of Android as an integer.
@@ -697,7 +708,7 @@ always available.
    the encoding used with the :term:`filesystem error handler <filesystem
    encoding and error handler>` to convert between Unicode filenames and bytes
    filenames. The filesystem error handler is returned from
-   :func:`getfilesystemencoding`.
+   :func:`getfilesystemencodeerrors`.
 
    For best compatibility, str should be used for filenames in all cases,
    although representing filenames as bytes is also supported. Functions
@@ -781,7 +792,7 @@ always available.
    additional garbage collector overhead if the object is managed by the garbage
    collector.
 
-   See `recursive sizeof recipe <https://code.activestate.com/recipes/577504>`_
+   See `recursive sizeof recipe <https://code.activestate.com/recipes/577504/>`_
    for an example of using :func:`getsizeof` recursively to find the size of
    containers and all their contents.
 
@@ -1166,7 +1177,7 @@ always available.
 
         :term:`Module specs <module spec>` were introduced in Python 3.4, by
         :pep:`451`. Earlier versions of Python looked for a method called
-        :meth:`~importlib.abc.MetaPathFinder.find_module`.
+        :meth:`!find_module`.
         This is still called as a fallback if a :data:`meta_path` entry doesn't
         have a :meth:`~importlib.abc.MetaPathFinder.find_spec` method.
 
@@ -1242,10 +1253,6 @@ always available.
 
     Originally specified in :pep:`302`.
 
-    .. versionchanged:: 3.3
-       ``None`` is stored instead of :class:`imp.NullImporter` when no finder
-       is found.
-
 
 .. data:: platform
 
diff -pruN 3.12.0~a7-1/Doc/library/tarfile.rst 3.12.0~b1-1/Doc/library/tarfile.rst
--- 3.12.0~a7-1/Doc/library/tarfile.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/tarfile.rst	2023-05-22 12:07:36.000000000 +0000
@@ -36,6 +36,13 @@ Some facts and figures:
 .. versionchanged:: 3.3
    Added support for :mod:`lzma` compression.
 
+.. versionchanged:: 3.12
+   Archives are extracted using a :ref:`filter <tarfile-extraction-filter>`,
+   which makes it possible to either limit surprising/dangerous features,
+   or to acknowledge that they are expected and the archive is fully trusted.
+   By default, archives are fully trusted, but this default is deprecated
+   and slated to change in Python 3.14.
+
 
 .. function:: open(name=None, mode='r', fileobj=None, bufsize=10240, **kwargs)
 
@@ -209,6 +216,38 @@ The :mod:`tarfile` module defines the fo
    Is raised by :meth:`TarInfo.frombuf` if the buffer it gets is invalid.
 
 
+.. exception:: FilterError
+
+   Base class for members :ref:`refused <tarfile-extraction-refuse>` by
+   filters.
+
+   .. attribute:: tarinfo
+
+      Information about the member that the filter refused to extract,
+      as :ref:`TarInfo <tarinfo-objects>`.
+
+.. exception:: AbsolutePathError
+
+   Raised to refuse extracting a member with an absolute path.
+
+.. exception:: OutsideDestinationError
+
+   Raised to refuse extracting a member outside the destination directory.
+
+.. exception:: SpecialFileError
+
+   Raised to refuse extracting a special file (e.g. a device or pipe).
+
+.. exception:: AbsoluteLinkError
+
+   Raised to refuse extracting a symbolic link with an absolute path.
+
+.. exception:: LinkOutsideDestinationError
+
+   Raised to refuse extracting a symbolic link pointing outside the destination
+   directory.
+
+
 The following constants are available at the module level:
 
 .. data:: ENCODING
@@ -319,11 +358,8 @@ be finalized; only the internally used f
    *debug* can be set from ``0`` (no debug messages) up to ``3`` (all debug
    messages). The messages are written to ``sys.stderr``.
 
-   If *errorlevel* is ``0``, all errors are ignored when using :meth:`TarFile.extract`.
-   Nevertheless, they appear as error messages in the debug output, when debugging
-   is enabled.  If ``1``, all *fatal* errors are raised as :exc:`OSError`
-   exceptions. If ``2``, all *non-fatal* errors are raised as :exc:`TarError`
-   exceptions as well.
+   *errorlevel* controls how extraction errors are handled,
+   see :attr:`the corresponding attribute <~TarFile.errorlevel>`.
 
    The *encoding* and *errors* arguments define the character encoding to be
    used for reading or writing the archive and how conversion errors are going
@@ -390,7 +426,7 @@ be finalized; only the internally used f
    available.
 
 
-.. method:: TarFile.extractall(path=".", members=None, *, numeric_owner=False)
+.. method:: TarFile.extractall(path=".", members=None, *, numeric_owner=False, filter=None)
 
    Extract all members from the archive to the current working directory or
    directory *path*. If optional *members* is given, it must be a subset of the
@@ -404,6 +440,12 @@ be finalized; only the internally used f
    are used to set the owner/group for the extracted files. Otherwise, the named
    values from the tarfile are used.
 
+   The *filter* argument specifies how ``members`` are modified or rejected
+   before extraction.
+   See :ref:`tarfile-extraction-filter` for details.
+   It is recommended to set this explicitly depending on which *tar* features
+   you need to support.
+
    .. warning::
 
       Never extract archives from untrusted sources without prior inspection.
@@ -411,14 +453,20 @@ be finalized; only the internally used f
       that have absolute filenames starting with ``"/"`` or filenames with two
       dots ``".."``.
 
+      Set ``filter='data'`` to prevent the most dangerous security issues,
+      and read the :ref:`tarfile-extraction-filter` section for details.
+
    .. versionchanged:: 3.5
       Added the *numeric_owner* parameter.
 
    .. versionchanged:: 3.6
       The *path* parameter accepts a :term:`path-like object`.
 
+   .. versionchanged:: 3.12
+      Added the *filter* parameter.
+
 
-.. method:: TarFile.extract(member, path="", set_attrs=True, *, numeric_owner=False)
+.. method:: TarFile.extract(member, path="", set_attrs=True, *, numeric_owner=False, filter=None)
 
    Extract a member from the archive to the current working directory, using its
    full name. Its file information is extracted as accurately as possible. *member*
@@ -426,9 +474,8 @@ be finalized; only the internally used f
    directory using *path*. *path* may be a :term:`path-like object`.
    File attributes (owner, mtime, mode) are set unless *set_attrs* is false.
 
-   If *numeric_owner* is :const:`True`, the uid and gid numbers from the tarfile
-   are used to set the owner/group for the extracted files. Otherwise, the named
-   values from the tarfile are used.
+   The *numeric_owner* and *filter* arguments are the same as
+   for :meth:`extractall`.
 
    .. note::
 
@@ -439,6 +486,9 @@ be finalized; only the internally used f
 
       See the warning for :meth:`extractall`.
 
+      Set ``filter='data'`` to prevent the most dangerous security issues,
+      and read the :ref:`tarfile-extraction-filter` section for details.
+
    .. versionchanged:: 3.2
       Added the *set_attrs* parameter.
 
@@ -448,6 +498,9 @@ be finalized; only the internally used f
    .. versionchanged:: 3.6
       The *path* parameter accepts a :term:`path-like object`.
 
+   .. versionchanged:: 3.12
+      Added the *filter* parameter.
+
 
 .. method:: TarFile.extractfile(member)
 
@@ -460,6 +513,55 @@ be finalized; only the internally used f
    .. versionchanged:: 3.3
       Return an :class:`io.BufferedReader` object.
 
+.. attribute:: TarFile.errorlevel
+   :type: int
+
+   If *errorlevel* is ``0``, errors are ignored when using :meth:`TarFile.extract`
+   and :meth:`TarFile.extractall`.
+   Nevertheless, they appear as error messages in the debug output when
+   *debug* is greater than 0.
+   If ``1`` (the default), all *fatal* errors are raised as :exc:`OSError` or
+   :exc:`FilterError` exceptions. If ``2``, all *non-fatal* errors are raised
+   as :exc:`TarError` exceptions as well.
+
+   Some exceptions, e.g. ones caused by wrong argument types or data
+   corruption, are always raised.
+
+   Custom :ref:`extraction filters <tarfile-extraction-filter>`
+   should raise :exc:`FilterError` for *fatal* errors
+   and :exc:`ExtractError` for *non-fatal* ones.
+
+   Note that when an exception is raised, the archive may be partially
+   extracted. It is the user’s responsibility to clean up.
+
+.. attribute:: TarFile.extraction_filter
+
+   .. versionadded:: 3.12
+
+   The :ref:`extraction filter <tarfile-extraction-filter>` used
+   as a default for the *filter* argument of :meth:`~TarFile.extract`
+   and :meth:`~TarFile.extractall`.
+
+   The attribute may be ``None`` or a callable.
+   String names are not allowed for this attribute, unlike the *filter*
+   argument to :meth:`~TarFile.extract`.
+
+   If ``extraction_filter`` is ``None`` (the default),
+   calling an extraction method without a *filter* argument will raise a
+   ``DeprecationWarning``,
+   and fall back to the :func:`fully_trusted <fully_trusted_filter>` filter,
+   whose dangerous behavior matches previous versions of Python.
+
+   In Python 3.14+, leaving ``extraction_filter=None`` will cause
+   extraction methods to use the :func:`data <data_filter>` filter by default.
+
+   The attribute may be set on instances or overridden in subclasses.
+   It also is possible to set it on the ``TarFile`` class itself to set a
+   global default, although, since it affects all uses of *tarfile*,
+   it is best practice to only do so in top-level applications or
+   :mod:`site configuration <site>`.
+   To set a global default this way, a filter function needs to be wrapped in
+   :func:`staticmethod()` to prevent injection of a ``self`` argument.
 
 .. method:: TarFile.add(name, arcname=None, recursive=True, *, filter=None)
 
@@ -535,8 +637,23 @@ permissions, owner etc.), it provides so
 It does *not* contain the file's data itself.
 
 :class:`TarInfo` objects are returned by :class:`TarFile`'s methods
-:meth:`getmember`, :meth:`getmembers` and :meth:`gettarinfo`.
+:meth:`~TarFile.getmember`, :meth:`~TarFile.getmembers` and
+:meth:`~TarFile.gettarinfo`.
 
+Modifying the objects returned by :meth:`~!TarFile.getmember` or
+:meth:`~!TarFile.getmembers` will affect all subsequent
+operations on the archive.
+For cases where this is unwanted, you can use :mod:`copy.copy() <copy>` or
+call the :meth:`~TarInfo.replace` method to create a modified copy in one step.
+
+Several attributes can be set to ``None`` to indicate that a piece of metadata
+is unused or unknown.
+Different :class:`TarInfo` methods handle ``None`` differently:
+
+- The :meth:`~TarFile.extract` or :meth:`~TarFile.extractall` methods will
+  ignore the corresponding metadata, leaving it set to a default.
+- :meth:`~TarFile.addfile` will fail.
+- :meth:`~TarFile.list` will print a placeholder string.
 
 .. class:: TarInfo(name="")
 
@@ -569,24 +686,39 @@ A ``TarInfo`` object has the following p
 
 
 .. attribute:: TarInfo.name
+   :type: str
 
    Name of the archive member.
 
 
 .. attribute:: TarInfo.size
+   :type: int
 
    Size in bytes.
 
 
 .. attribute:: TarInfo.mtime
+   :type: int | float
+
+   Time of last modification in seconds since the :ref:`epoch <epoch>`,
+   as in :attr:`os.stat_result.st_mtime`.
 
-   Time of last modification.
+   .. versionchanged:: 3.12
 
+      Can be set to ``None`` for :meth:`~TarFile.extract` and
+      :meth:`~TarFile.extractall`, causing extraction to skip applying this
+      attribute.
 
 .. attribute:: TarInfo.mode
+   :type: int
+
+   Permission bits, as for :func:`os.chmod`.
 
-   Permission bits.
+   .. versionchanged:: 3.12
 
+      Can be set to ``None`` for :meth:`~TarFile.extract` and
+      :meth:`~TarFile.extractall`, causing extraction to skip applying this
+      attribute.
 
 .. attribute:: TarInfo.type
 
@@ -598,35 +730,76 @@ A ``TarInfo`` object has the following p
 
 
 .. attribute:: TarInfo.linkname
+   :type: str
 
    Name of the target file name, which is only present in :class:`TarInfo` objects
    of type :const:`LNKTYPE` and :const:`SYMTYPE`.
 
 
 .. attribute:: TarInfo.uid
+   :type: int
 
    User ID of the user who originally stored this member.
 
+   .. versionchanged:: 3.12
+
+      Can be set to ``None`` for :meth:`~TarFile.extract` and
+      :meth:`~TarFile.extractall`, causing extraction to skip applying this
+      attribute.
 
 .. attribute:: TarInfo.gid
+   :type: int
 
    Group ID of the user who originally stored this member.
 
+   .. versionchanged:: 3.12
+
+      Can be set to ``None`` for :meth:`~TarFile.extract` and
+      :meth:`~TarFile.extractall`, causing extraction to skip applying this
+      attribute.
 
 .. attribute:: TarInfo.uname
+   :type: str
 
    User name.
 
+   .. versionchanged:: 3.12
+
+      Can be set to ``None`` for :meth:`~TarFile.extract` and
+      :meth:`~TarFile.extractall`, causing extraction to skip applying this
+      attribute.
 
 .. attribute:: TarInfo.gname
+   :type: str
 
    Group name.
 
+   .. versionchanged:: 3.12
+
+      Can be set to ``None`` for :meth:`~TarFile.extract` and
+      :meth:`~TarFile.extractall`, causing extraction to skip applying this
+      attribute.
 
 .. attribute:: TarInfo.pax_headers
+   :type: dict
 
    A dictionary containing key-value pairs of an associated pax extended header.
 
+.. method:: TarInfo.replace(name=..., mtime=..., mode=..., linkname=...,
+                            uid=..., gid=..., uname=..., gname=...,
+                            deep=True)
+
+   .. versionadded:: 3.12
+
+   Return a *new* copy of the :class:`!TarInfo` object with the given attributes
+   changed. For example, to return a ``TarInfo`` with the group name set to
+   ``'staff'``, use::
+
+       new_tarinfo = old_tarinfo.replace(gname='staff')
+
+   By default, a deep copy is made.
+   If *deep* is false, the copy is shallow, i.e. ``pax_headers``
+   and any custom attributes are shared with the original ``TarInfo`` object.
 
 A :class:`TarInfo` object also provides some convenient query methods:
 
@@ -676,9 +849,258 @@ A :class:`TarInfo` object also provides
    Return :const:`True` if it is one of character device, block device or FIFO.
 
 
+.. _tarfile-extraction-filter:
+
+Extraction filters
+------------------
+
+.. versionadded:: 3.12
+
+The *tar* format is designed to capture all details of a UNIX-like filesystem,
+which makes it very powerful.
+Unfortunately, the features make it easy to create tar files that have
+unintended -- and possibly malicious -- effects when extracted.
+For example, extracting a tar file can overwrite arbitrary files in various
+ways (e.g.  by using absolute paths, ``..`` path components, or symlinks that
+affect later members).
+
+In most cases, the full functionality is not needed.
+Therefore, *tarfile* supports extraction filters: a mechanism to limit
+functionality, and thus mitigate some of the security issues.
+
+.. seealso::
+
+   :pep:`706`
+      Contains further motivation and rationale behind the design.
+
+The *filter* argument to :meth:`TarFile.extract` or :meth:`~TarFile.extractall`
+can be:
+
+* the string ``'fully_trusted'``: Honor all metadata as specified in the
+  archive.
+  Should be used if the user trusts the archive completely, or implements
+  their own complex verification.
+
+* the string ``'tar'``: Honor most *tar*-specific features (i.e. features of
+  UNIX-like filesystems), but block features that are very likely to be
+  surprising or malicious. See :func:`tar_filter` for details.
+
+* the string ``'data'``: Ignore or block most features specific to UNIX-like
+  filesystems. Intended for extracting cross-platform data archives.
+  See :func:`data_filter` for details.
+
+* ``None`` (default): Use :attr:`TarFile.extraction_filter`.
+
+  If that is also ``None`` (the default), raise a ``DeprecationWarning``,
+  and fall back to the ``'fully_trusted'`` filter, whose dangerous behavior
+  matches previous versions of Python.
+
+  In Python 3.14, the ``'data'`` filter will become the default instead.
+  It's possible to switch earlier; see :attr:`TarFile.extraction_filter`.
+
+* A callable which will be called for each extracted member with a
+  :ref:`TarInfo <tarinfo-objects>` describing the member and the destination
+  path to where the archive is extracted (i.e. the same path is used for all
+  members)::
+
+      filter(/, member: TarInfo, path: str) -> TarInfo | None
+
+  The callable is called just before each member is extracted, so it can
+  take the current state of the disk into account.
+  It can:
+
+  - return a :class:`TarInfo` object which will be used instead of the metadata
+    in the archive, or
+  - return ``None``, in which case the member will be skipped, or
+  - raise an exception to abort the operation or skip the member,
+    depending on :attr:`~TarFile.errorlevel`.
+    Note that when extraction is aborted, :meth:`~TarFile.extractall` may leave
+    the archive partially extracted. It does not attempt to clean up.
+
+Default named filters
+~~~~~~~~~~~~~~~~~~~~~
+
+The pre-defined, named filters are available as functions, so they can be
+reused in custom filters:
+
+.. function:: fully_trusted_filter(/, member, path)
+
+   Return *member* unchanged.
+
+   This implements the ``'fully_trusted'`` filter.
+
+.. function:: tar_filter(/, member, path)
+
+  Implements the ``'tar'`` filter.
+
+  - Strip leading slashes (``/`` and :attr:`os.sep`) from filenames.
+  - :ref:`Refuse <tarfile-extraction-refuse>` to extract files with absolute
+    paths (in case the name is absolute
+    even after stripping slashes, e.g. ``C:/foo`` on Windows).
+    This raises :class:`~tarfile.AbsolutePathError`.
+  - :ref:`Refuse <tarfile-extraction-refuse>` to extract files whose absolute
+    path (after following symlinks) would end up outside the destination.
+    This raises :class:`~tarfile.OutsideDestinationError`.
+  - Clear high mode bits (setuid, setgid, sticky) and group/other write bits
+    (:attr:`~stat.S_IWGRP`|:attr:`~stat.S_IWOTH`).
+
+  Return the modified ``TarInfo`` member.
+
+.. function:: data_filter(/, member, path)
+
+  Implements the ``'data'`` filter.
+  In addition to what ``tar_filter`` does:
+
+  - :ref:`Refuse <tarfile-extraction-refuse>` to extract links (hard or soft)
+    that link to absolute paths, or ones that link outside the destination.
+
+    This raises :class:`~tarfile.AbsoluteLinkError` or
+    :class:`~tarfile.LinkOutsideDestinationError`.
+
+    Note that such files are refused even on platforms that do not support
+    symbolic links.
+
+  - :ref:`Refuse <tarfile-extraction-refuse>` to extract device files
+    (including pipes).
+    This raises :class:`~tarfile.SpecialFileError`.
+
+  - For regular files, including hard links:
+
+    - Set the owner read and write permissions
+      (:attr:`~stat.S_IRUSR`|:attr:`~stat.S_IWUSR`).
+    - Remove the group & other executable permission
+      (:attr:`~stat.S_IXGRP`|:attr:`~stat.S_IXOTH`)
+      if the owner doesn’t have it (:attr:`~stat.S_IXUSR`).
+
+  - For other files (directories), set ``mode`` to ``None``, so
+    that extraction methods skip applying permission bits.
+  - Set user and group info (``uid``, ``gid``, ``uname``, ``gname``)
+    to ``None``, so that extraction methods skip setting it.
+
+  Return the modified ``TarInfo`` member.
+
+
+.. _tarfile-extraction-refuse:
+
+Filter errors
+~~~~~~~~~~~~~
+
+When a filter refuses to extract a file, it will raise an appropriate exception,
+a subclass of :class:`~tarfile.FilterError`.
+This will abort the extraction if :attr:`TarFile.errorlevel` is 1 or more.
+With ``errorlevel=0`` the error will be logged and the member will be skipped,
+but extraction will continue.
+
+
+Hints for further verification
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Even with ``filter='data'``, *tarfile* is not suited for extracting untrusted
+files without prior inspection.
+Among other issues, the pre-defined filters do not prevent denial-of-service
+attacks. Users should do additional checks.
+
+Here is an incomplete list of things to consider:
+
+* Extract to a :func:`new temporary directory <tempfile.mkdtemp>`
+  to prevent e.g. exploiting pre-existing links, and to make it easier to
+  clean up after a failed extraction.
+* When working with untrusted data, use external (e.g. OS-level) limits on
+  disk, memory and CPU usage.
+* Check filenames against an allow-list of characters
+  (to filter out control characters, confusables, foreign path separators,
+  etc.).
+* Check that filenames have expected extensions (discouraging files that
+  execute when you “click on them”, or extension-less files like Windows special device names).
+* Limit the number of extracted files, total size of extracted data,
+  filename length (including symlink length), and size of individual files.
+* Check for files that would be shadowed on case-insensitive filesystems.
+
+Also note that:
+
+* Tar files may contain multiple versions of the same file.
+  Later ones are expected to overwrite any earlier ones.
+  This feature is crucial to allow updating tape archives, but can be abused
+  maliciously.
+* *tarfile* does not protect against issues with “live” data,
+  e.g. an attacker tinkering with the destination (or source) directory while
+  extraction (or archiving) is in progress.
+
+
+Supporting older Python versions
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Extraction filters were added to Python 3.12, but may be backported to older
+versions as security updates.
+To check whether the feature is available, use e.g.
+``hasattr(tarfile, 'data_filter')`` rather than checking the Python version.
+
+The following examples show how to support Python versions with and without
+the feature.
+Note that setting ``extraction_filter`` will affect any subsequent operations.
+
+* Fully trusted archive::
+
+    my_tarfile.extraction_filter = (lambda member, path: member)
+    my_tarfile.extractall()
+
+* Use the ``'data'`` filter if available, but revert to Python 3.11 behavior
+  (``'fully_trusted'``) if this feature is not available::
+
+    my_tarfile.extraction_filter = getattr(tarfile, 'data_filter',
+                                           (lambda member, path: member))
+    my_tarfile.extractall()
+
+* Use the ``'data'`` filter; *fail* if it is not available::
+
+    my_tarfile.extractall(filter=tarfile.data_filter)
+
+  or::
+
+    my_tarfile.extraction_filter = tarfile.data_filter
+    my_tarfile.extractall()
+
+* Use the ``'data'`` filter; *warn* if it is not available::
+
+   if hasattr(tarfile, 'data_filter'):
+       my_tarfile.extractall(filter='data')
+   else:
+       # remove this when no longer needed
+       warn_the_user('Extracting may be unsafe; consider updating Python')
+       my_tarfile.extractall()
+
+
+Stateful extraction filter example
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+While *tarfile*'s extraction methods take a simple *filter* callable,
+custom filters may be more complex objects with an internal state.
+It may be useful to write these as context managers, to be used like this::
+
+    with StatefulFilter() as filter_func:
+        tar.extractall(path, filter=filter_func)
+
+Such a filter can be written as, for example::
+
+    class StatefulFilter:
+        def __init__(self):
+            self.file_count = 0
+
+        def __enter__(self):
+            return self
+
+        def __call__(self, member, path):
+            self.file_count += 1
+            return member
+
+        def __exit__(self, *exc_info):
+            print(f'{self.file_count} files extracted')
+
+
 .. _tarfile-commandline:
 .. program:: tarfile
 
+
 Command-Line Interface
 ----------------------
 
@@ -748,6 +1170,13 @@ Command-line options
 
    Verbose output.
 
+.. cmdoption:: --filter <filtername>
+
+   Specifies the *filter* for ``--extract``.
+   See :ref:`tarfile-extraction-filter` for details.
+   Only string names are accepted (that is, ``fully_trusted``, ``tar``,
+   and ``data``).
+
 .. _tar-examples:
 
 Examples
@@ -757,7 +1186,7 @@ How to extract an entire tar archive to
 
    import tarfile
    tar = tarfile.open("sample.tar.gz")
-   tar.extractall()
+   tar.extractall(filter='data')
    tar.close()
 
 How to extract a subset of a tar archive with :meth:`TarFile.extractall` using
diff -pruN 3.12.0~a7-1/Doc/library/tempfile.rst 3.12.0~b1-1/Doc/library/tempfile.rst
--- 3.12.0~a7-1/Doc/library/tempfile.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/tempfile.rst	2023-05-22 12:07:36.000000000 +0000
@@ -292,6 +292,9 @@ The module defines the following user-ca
    .. versionchanged:: 3.6
       The *dir* parameter now accepts a :term:`path-like object`.
 
+   .. versionchanged:: 3.12
+      :func:`mkdtemp` now always returns an absolute path, even if *dir* is relative.
+
 
 .. function:: gettempdir()
 
diff -pruN 3.12.0~a7-1/Doc/library/token-list.inc 3.12.0~b1-1/Doc/library/token-list.inc
--- 3.12.0~a7-1/Doc/library/token-list.inc	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/token-list.inc	2023-05-22 12:07:36.000000000 +0000
@@ -201,6 +201,10 @@
 
    Token value for ``":="``.
 
+.. data:: EXCLAMATION
+
+   Token value for ``"!"``.
+
 .. data:: OP
 
 .. data:: AWAIT
@@ -213,6 +217,16 @@
 
 .. data:: SOFT_KEYWORD
 
+.. data:: FSTRING_START
+
+.. data:: FSTRING_MIDDLE
+
+.. data:: FSTRING_END
+
+.. data:: COMMENT
+
+.. data:: NL
+
 .. data:: ERRORTOKEN
 
 .. data:: N_TOKENS
diff -pruN 3.12.0~a7-1/Doc/library/token.rst 3.12.0~b1-1/Doc/library/token.rst
--- 3.12.0~a7-1/Doc/library/token.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/token.rst	2023-05-22 12:07:36.000000000 +0000
@@ -50,11 +50,13 @@ The following token type values aren't u
 the :mod:`tokenize` module.
 
 .. data:: COMMENT
+   :noindex:
 
    Token value used to indicate a comment.
 
 
 .. data:: NL
+   :noindex:
 
    Token value used to indicate a non-terminating newline.  The
    :data:`NEWLINE` token indicates the end of a logical line of Python code;
diff -pruN 3.12.0~a7-1/Doc/library/traceback.rst 3.12.0~b1-1/Doc/library/traceback.rst
--- 3.12.0~a7-1/Doc/library/traceback.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/traceback.rst	2023-05-22 12:07:36.000000000 +0000
@@ -14,7 +14,7 @@ interpreter when it prints a stack trace
 stack traces under program control, such as in a "wrapper" around the
 interpreter.
 
-.. index:: object: traceback
+.. index:: pair: object; traceback
 
 The module uses traceback objects --- these are objects of type :class:`types.TracebackType`,
 which are assigned to the ``__traceback__`` field of :class:`BaseException` instances.
diff -pruN 3.12.0~a7-1/Doc/library/tty.rst 3.12.0~b1-1/Doc/library/tty.rst
--- 3.12.0~a7-1/Doc/library/tty.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/tty.rst	2023-05-22 12:07:36.000000000 +0000
@@ -20,18 +20,36 @@ Because it requires the :mod:`termios` m
 The :mod:`tty` module defines the following functions:
 
 
+.. function:: cfmakeraw(mode)
+
+   Convert the tty attribute list *mode*, which is a list like the one returned
+   by :func:`termios.tcgetattr`, to that of a tty in raw mode.
+
+   .. versionadded:: 3.12
+
+
+.. function:: cfmakecbreak(mode)
+
+   Convert the tty attribute list *mode*, which is a list like the one returned
+   by :func:`termios.tcgetattr`, to that of a tty in cbreak mode.
+
+   .. versionadded:: 3.12
+
+
 .. function:: setraw(fd, when=termios.TCSAFLUSH)
 
    Change the mode of the file descriptor *fd* to raw. If *when* is omitted, it
    defaults to :const:`termios.TCSAFLUSH`, and is passed to
-   :func:`termios.tcsetattr`.
+   :func:`termios.tcsetattr`. The return value of :func:`termios.tcgetattr`
+   is saved before setting *fd* to raw mode; this value is returned.
 
 
 .. function:: setcbreak(fd, when=termios.TCSAFLUSH)
 
    Change the mode of file descriptor *fd* to cbreak. If *when* is omitted, it
    defaults to :const:`termios.TCSAFLUSH`, and is passed to
-   :func:`termios.tcsetattr`.
+   :func:`termios.tcsetattr`. The return value of :func:`termios.tcgetattr`
+   is saved before setting *fd* to cbreak mode; this value is returned.
 
 
 .. seealso::
diff -pruN 3.12.0~a7-1/Doc/library/turtle.rst 3.12.0~b1-1/Doc/library/turtle.rst
--- 3.12.0~a7-1/Doc/library/turtle.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/turtle.rst	2023-05-22 12:07:36.000000000 +0000
@@ -107,6 +107,7 @@ Turtle motion
       | :func:`right` | :func:`rt`
       | :func:`left` | :func:`lt`
       | :func:`goto` | :func:`setpos` | :func:`setposition`
+      | :func:`teleport`
       | :func:`setx`
       | :func:`sety`
       | :func:`setheading` | :func:`seth`
@@ -358,18 +359,56 @@ Turtle motion
    .. doctest::
       :skipif: _tkinter is None
 
-       >>> tp = turtle.pos()
-       >>> tp
-       (0.00,0.00)
-       >>> turtle.setpos(60,30)
-       >>> turtle.pos()
-       (60.00,30.00)
-       >>> turtle.setpos((20,80))
-       >>> turtle.pos()
-       (20.00,80.00)
-       >>> turtle.setpos(tp)
-       >>> turtle.pos()
-       (0.00,0.00)
+      >>> tp = turtle.pos()
+      >>> tp
+      (0.00,0.00)
+      >>> turtle.setpos(60,30)
+      >>> turtle.pos()
+      (60.00,30.00)
+      >>> turtle.setpos((20,80))
+      >>> turtle.pos()
+      (20.00,80.00)
+      >>> turtle.setpos(tp)
+      >>> turtle.pos()
+      (0.00,0.00)
+
+
+.. function:: teleport(x, y=None, *, fill_gap=False)
+
+   :param x: a number or ``None``
+   :param y: a number or ``None``
+   :param fill_gap: a boolean
+
+   Move turtle to an absolute position. Unlike goto(x, y), a line will not
+   be drawn. The turtle's orientation does not change. If currently
+   filling, the polygon(s) teleported from will be filled after leaving,
+   and filling will begin again after teleporting. This can be disabled
+   with fill_gap=True, which makes the imaginary line traveled during
+   teleporting act as a fill barrier like in goto(x, y).
+
+   .. doctest::
+      :skipif: _tkinter is None
+      :hide:
+
+      >>> turtle.goto(0, 0)
+
+   .. doctest::
+      :skipif: _tkinter is None
+
+      >>> tp = turtle.pos()
+      >>> tp
+      (0.00,0.00)
+      >>> turtle.teleport(60)
+      >>> turtle.pos()
+      (60.00,0.00)
+      >>> turtle.teleport(y=10)
+      >>> turtle.pos()
+      (60.00,10.00)
+      >>> turtle.teleport(20, 30)
+      >>> turtle.pos()
+      (20.00,30.00)
+
+   .. versionadded: 3.12
 
 
 .. function:: setx(x)
@@ -537,8 +576,7 @@ Turtle motion
       :skipif: _tkinter is None
 
       >>> turtle.color("blue")
-      >>> turtle.stamp()
-      11
+      >>> stamp_id = turtle.stamp()
       >>> turtle.fd(50)
 
 
@@ -575,15 +613,8 @@ Turtle motion
    .. doctest::
 
       >>> for i in range(8):
-      ...     turtle.stamp(); turtle.fd(30)
-      13
-      14
-      15
-      16
-      17
-      18
-      19
-      20
+      ...     unused_stamp_id = turtle.stamp()
+      ...     turtle.fd(30)
       >>> turtle.clearstamps(2)
       >>> turtle.clearstamps(-2)
       >>> turtle.clearstamps()
@@ -919,23 +950,23 @@ Color control
    .. doctest::
       :skipif: _tkinter is None
 
-       >>> colormode()
-       1.0
-       >>> turtle.pencolor()
-       'red'
-       >>> turtle.pencolor("brown")
-       >>> turtle.pencolor()
-       'brown'
-       >>> tup = (0.2, 0.8, 0.55)
-       >>> turtle.pencolor(tup)
-       >>> turtle.pencolor()
-       (0.2, 0.8, 0.5490196078431373)
-       >>> colormode(255)
-       >>> turtle.pencolor()
-       (51.0, 204.0, 140.0)
-       >>> turtle.pencolor('#32c18f')
-       >>> turtle.pencolor()
-       (50.0, 193.0, 143.0)
+      >>> colormode()
+      1.0
+      >>> turtle.pencolor()
+      'red'
+      >>> turtle.pencolor("brown")
+      >>> turtle.pencolor()
+      'brown'
+      >>> tup = (0.2, 0.8, 0.55)
+      >>> turtle.pencolor(tup)
+      >>> turtle.pencolor()
+      (0.2, 0.8, 0.5490196078431373)
+      >>> colormode(255)
+      >>> turtle.pencolor()
+      (51.0, 204.0, 140.0)
+      >>> turtle.pencolor('#32c18f')
+      >>> turtle.pencolor()
+      (50.0, 193.0, 143.0)
 
 
 .. function:: fillcolor(*args)
@@ -968,17 +999,17 @@ Color control
    .. doctest::
       :skipif: _tkinter is None
 
-       >>> turtle.fillcolor("violet")
-       >>> turtle.fillcolor()
-       'violet'
-       >>> turtle.pencolor()
-       (50.0, 193.0, 143.0)
-       >>> turtle.fillcolor((50, 193, 143))  # Integers, not floats
-       >>> turtle.fillcolor()
-       (50.0, 193.0, 143.0)
-       >>> turtle.fillcolor('#ffffff')
-       >>> turtle.fillcolor()
-       (255.0, 255.0, 255.0)
+      >>> turtle.fillcolor("violet")
+      >>> turtle.fillcolor()
+      'violet'
+      >>> turtle.pencolor()
+      (50.0, 193.0, 143.0)
+      >>> turtle.fillcolor((50, 193, 143))  # Integers, not floats
+      >>> turtle.fillcolor()
+      (50.0, 193.0, 143.0)
+      >>> turtle.fillcolor('#ffffff')
+      >>> turtle.fillcolor()
+      (255.0, 255.0, 255.0)
 
 
 .. function:: color(*args)
@@ -1007,12 +1038,12 @@ Color control
    .. doctest::
       :skipif: _tkinter is None
 
-       >>> turtle.color("red", "green")
-       >>> turtle.color()
-       ('red', 'green')
-       >>> color("#285078", "#a0c8f0")
-       >>> color()
-       ((40.0, 80.0, 120.0), (160.0, 200.0, 240.0))
+      >>> turtle.color("red", "green")
+      >>> turtle.color()
+      ('red', 'green')
+      >>> color("#285078", "#a0c8f0")
+      >>> color()
+      ((40.0, 80.0, 120.0), (160.0, 200.0, 240.0))
 
 
 See also: Screen method :func:`colormode`.
@@ -1034,11 +1065,11 @@ Filling
    .. doctest::
       :skipif: _tkinter is None
 
-       >>> turtle.begin_fill()
-       >>> if turtle.filling():
-       ...    turtle.pensize(5)
-       ... else:
-       ...    turtle.pensize(3)
+      >>> turtle.begin_fill()
+      >>> if turtle.filling():
+      ...    turtle.pensize(5)
+      ... else:
+      ...    turtle.pensize(3)
 
 
 
@@ -1244,11 +1275,11 @@ Appearance
    .. doctest::
       :skipif: _tkinter is None
 
-       >>> turtle.shape("circle")
-       >>> turtle.shapesize(5,2)
-       >>> turtle.shearfactor(0.5)
-       >>> turtle.shearfactor()
-       0.5
+      >>> turtle.shape("circle")
+      >>> turtle.shapesize(5,2)
+      >>> turtle.shearfactor(0.5)
+      >>> turtle.shearfactor()
+      0.5
 
 
 .. function:: tilt(angle)
@@ -1617,11 +1648,11 @@ Window control
    ``"nopic"``, delete background image, if present.  If *picname* is ``None``,
    return the filename of the current backgroundimage. ::
 
-       >>> screen.bgpic()
-       'nopic'
-       >>> screen.bgpic("landscape.gif")
-       >>> screen.bgpic()
-       "landscape.gif"
+      >>> screen.bgpic()
+      'nopic'
+      >>> screen.bgpic("landscape.gif")
+      >>> screen.bgpic()
+      "landscape.gif"
 
 
 .. function:: clear()
@@ -2028,16 +2059,16 @@ Settings and special methods
 
    Return the height of the turtle window. ::
 
-       >>> screen.window_height()
-       480
+      >>> screen.window_height()
+      480
 
 
 .. function:: window_width()
 
    Return the width of the turtle window. ::
 
-       >>> screen.window_width()
-       640
+      >>> screen.window_width()
+      640
 
 
 .. _screenspecific:
@@ -2218,12 +2249,12 @@ facilities:
          in the range 0..colormode or a 3-tuple of such numbers.
 
 
-           >>> screen.bgcolor("orange")
-           >>> screen.bgcolor()
-           "orange"
-           >>> screen.bgcolor(0.5,0,0.5)
-           >>> screen.bgcolor()
-           "#800080"
+         >>> screen.bgcolor("orange")
+         >>> screen.bgcolor()
+         "orange"
+         >>> screen.bgcolor(0.5,0,0.5)
+         >>> screen.bgcolor()
+         "#800080"
 
      >>> help(Turtle.penup)
      Help on method penup in module turtle:
diff -pruN 3.12.0~a7-1/Doc/library/types.rst 3.12.0~b1-1/Doc/library/types.rst
--- 3.12.0~a7-1/Doc/library/types.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/types.rst	2023-05-22 12:07:36.000000000 +0000
@@ -75,13 +75,53 @@ Dynamic Type Creation
 
    This function looks for items in *bases* that are not instances of
    :class:`type`, and returns a tuple where each such object that has
-   an ``__mro_entries__`` method is replaced with an unpacked result of
+   an :meth:`~object.__mro_entries__` method is replaced with an unpacked result of
    calling this method.  If a *bases* item is an instance of :class:`type`,
-   or it doesn't have an ``__mro_entries__`` method, then it is included in
+   or it doesn't have an :meth:`!__mro_entries__` method, then it is included in
    the return tuple unchanged.
 
    .. versionadded:: 3.7
 
+.. function:: get_original_bases(cls, /)
+
+    Return the tuple of objects originally given as the bases of *cls* before
+    the :meth:`~object.__mro_entries__` method has been called on any bases
+    (following the mechanisms laid out in :pep:`560`). This is useful for
+    introspecting :ref:`Generics <user-defined-generics>`.
+
+    For classes that have an ``__orig_bases__`` attribute, this
+    function returns the value of ``cls.__orig_bases__``.
+    For classes without the ``__orig_bases__`` attribute, ``cls.__bases__`` is
+    returned.
+
+    Examples::
+
+        from typing import TypeVar, Generic, NamedTuple, TypedDict
+
+        T = TypeVar("T")
+        class Foo(Generic[T]): ...
+        class Bar(Foo[int], float): ...
+        class Baz(list[str]): ...
+        Eggs = NamedTuple("Eggs", [("a", int), ("b", str)])
+        Spam = TypedDict("Spam", {"a": int, "b": str})
+
+        assert Bar.__bases__ == (Foo, float)
+        assert get_original_bases(Bar) == (Foo[int], float)
+
+        assert Baz.__bases__ == (list,)
+        assert get_original_bases(Baz) == (list[str],)
+
+        assert Eggs.__bases__ == (tuple,)
+        assert get_original_bases(Eggs) == (NamedTuple,)
+
+        assert Spam.__bases__ == (dict,)
+        assert get_original_bases(Spam) == (TypedDict,)
+
+        assert int.__bases__ == (object,)
+        assert get_original_bases(int) == (object,)
+
+    .. versionadded:: 3.12
+
 .. seealso::
 
    :pep:`560` - Core support for typing module and generic types
@@ -146,7 +186,7 @@ Standard names are defined for the follo
 
 .. class:: CodeType(**kwargs)
 
-   .. index:: builtin: compile
+   .. index:: pair: built-in function; compile
 
    The type for code objects such as returned by :func:`compile`.
 
@@ -311,6 +351,13 @@ Standard names are defined for the follo
    .. versionchanged:: 3.9.2
       This type can now be subclassed.
 
+   .. seealso::
+
+      :ref:`Generic Alias Types<types-genericalias>`
+         In-depth documentation on instances of :class:`!types.GenericAlias`
+
+      :pep:`585` - Type Hinting Generics In Standard Collections
+         Introducing the :class:`!types.GenericAlias` class
 
 .. class:: UnionType
 
diff -pruN 3.12.0~a7-1/Doc/library/typing.rst 3.12.0~b1-1/Doc/library/typing.rst
--- 3.12.0~a7-1/Doc/library/typing.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/typing.rst	2023-05-22 12:07:36.000000000 +0000
@@ -19,7 +19,7 @@
 
 This module provides runtime support for type hints. The most fundamental
 support consists of the types :data:`Any`, :data:`Union`, :data:`Callable`,
-:class:`TypeVar`, and :class:`Generic`. For a full specification, please see
+:class:`TypeVar`, and :class:`Generic`. For a specification, please see
 :pep:`484`. For a simplified introduction to type hints, see :pep:`483`.
 
 
@@ -98,6 +98,9 @@ annotations. These include:
     *Introducing* :data:`LiteralString`
 * :pep:`681`: Data Class Transforms
     *Introducing* the :func:`@dataclass_transform<dataclass_transform>` decorator
+* :pep:`692`: Using ``TypedDict`` for more precise ``**kwargs`` typing
+    *Introducing* a new way of typing ``**kwargs`` with :data:`Unpack` and
+    :data:`TypedDict`
 * :pep:`698`: Adding an override decorator to typing
     *Introducing* the :func:`@override<override>` decorator
 
@@ -423,7 +426,7 @@ to this is that a list of types can be u
    >>> class Z(Generic[T, P]): ...
    ...
    >>> Z[int, [dict, float]]
-   __main__.Z[int, (<class 'dict'>, <class 'float'>)]
+   __main__.Z[int, [dict, float]]
 
 
 Furthermore, a generic with only one parameter specification variable will accept
@@ -434,9 +437,9 @@ to the former, so the following are equi
    >>> class X(Generic[P]): ...
    ...
    >>> X[int, str]
-   __main__.X[(<class 'int'>, <class 'str'>)]
+   __main__.X[[int, str]]
    >>> X[[int, str]]
-   __main__.X[(<class 'int'>, <class 'str'>)]
+   __main__.X[[int, str]]
 
 Do note that generics with :class:`ParamSpec` may not have correct
 ``__parameters__`` after substitution in some cases because they
@@ -589,7 +592,7 @@ The module defines the following classes
    when the checked program targets Python 3.9 or newer.
 
    The deprecated types will be removed from the :mod:`typing` module
-   in the first Python version released 5 years after the release of Python 3.9.0.
+   no sooner than the first Python version released 5 years after the release of Python 3.9.0.
    See details in :pep:`585`—*Type Hinting Generics In Standard Collections*.
 
 
@@ -613,6 +616,21 @@ These can be used as types in annotation
       avoiding type checker errors with classes that can duck type anywhere or
       are highly dynamic.
 
+.. data:: AnyStr
+
+   ``AnyStr`` is a :ref:`constrained type variable <typing-constrained-typevar>` defined as
+   ``AnyStr = TypeVar('AnyStr', str, bytes)``.
+
+   It is meant to be used for functions that may accept any kind of string
+   without allowing different kinds of strings to mix. For example::
+
+      def concat(a: AnyStr, b: AnyStr) -> AnyStr:
+          return a + b
+
+      concat(u"foo", u"bar")  # Ok, output has type 'unicode'
+      concat(b"foo", b"bar")  # Ok, output has type 'bytes'
+      concat(u"foo", b"bar")  # Error, cannot mix unicode and bytes
+
 .. data:: LiteralString
 
    Special type that includes only literal strings. A string
@@ -914,13 +932,13 @@ These can be used as types in annotation
       # We don't need to pass in the lock ourselves thanks to the decorator.
       sum_threadsafe([1.1, 2.2, 3.3])
 
-.. versionadded:: 3.10
+   .. versionadded:: 3.10
 
-.. seealso::
+   .. seealso::
 
-   * :pep:`612` -- Parameter Specification Variables (the PEP which introduced
-     ``ParamSpec`` and ``Concatenate``).
-   * :class:`ParamSpec` and :class:`Callable`.
+      * :pep:`612` -- Parameter Specification Variables (the PEP which introduced
+        ``ParamSpec`` and ``Concatenate``).
+      * :class:`ParamSpec` and :class:`Callable`.
 
 
 .. class:: Type(Generic[CT_co])
@@ -1205,6 +1223,49 @@ These can be used as types in annotation
    .. versionadded:: 3.10
 
 
+.. data:: Unpack
+
+   A typing operator that conceptually marks an object as having been
+   unpacked. For example, using the unpack operator ``*`` on a
+   :class:`type variable tuple <TypeVarTuple>` is equivalent to using ``Unpack``
+   to mark the type variable tuple as having been unpacked::
+
+      Ts = TypeVarTuple('Ts')
+      tup: tuple[*Ts]
+      # Effectively does:
+      tup: tuple[Unpack[Ts]]
+
+   In fact, ``Unpack`` can be used interchangeably with ``*`` in the context
+   of :class:`typing.TypeVarTuple <TypeVarTuple>` and
+   :class:`builtins.tuple <tuple>` types. You might see ``Unpack`` being used
+   explicitly in older versions of Python, where ``*`` couldn't be used in
+   certain places::
+
+      # In older versions of Python, TypeVarTuple and Unpack
+      # are located in the `typing_extensions` backports package.
+      from typing_extensions import TypeVarTuple, Unpack
+
+      Ts = TypeVarTuple('Ts')
+      tup: tuple[*Ts]         # Syntax error on Python <= 3.10!
+      tup: tuple[Unpack[Ts]]  # Semantically equivalent, and backwards-compatible
+
+   ``Unpack`` can also be used along with :class:`typing.TypedDict` for typing
+   ``**kwargs`` in a function signature::
+
+      from typing import TypedDict, Unpack
+
+      class Movie(TypedDict):
+         name: str
+         year: int
+
+      # This function expects two keyword arguments - `name` of type `str`
+      # and `year` of type `int`.
+      def foo(**kwargs: Unpack[Movie]): ...
+
+   See :pep:`692` for more details on using ``Unpack`` for ``**kwargs`` typing.
+
+   .. versionadded:: 3.11
+
 Building generic types
 """"""""""""""""""""""
 
@@ -1288,6 +1349,8 @@ These are not used in annotations. They
        U = TypeVar('U', bound=str|bytes)  # Can be any subtype of the union str|bytes
        V = TypeVar('V', bound=SupportsAbs)  # Can be anything with an __abs__ method
 
+.. _typing-constrained-typevar:
+
     Using a *constrained* type variable, however, means that the ``TypeVar``
     can only ever be solved as being exactly one of the constraints given::
 
@@ -1404,32 +1467,6 @@ These are not used in annotations. They
 
     .. versionadded:: 3.11
 
-.. data:: Unpack
-
-   A typing operator that conceptually marks an object as having been
-   unpacked. For example, using the unpack operator ``*`` on a
-   :class:`type variable tuple <TypeVarTuple>` is equivalent to using ``Unpack``
-   to mark the type variable tuple as having been unpacked::
-
-      Ts = TypeVarTuple('Ts')
-      tup: tuple[*Ts]
-      # Effectively does:
-      tup: tuple[Unpack[Ts]]
-
-   In fact, ``Unpack`` can be used interchangeably with ``*`` in the context
-   of types. You might see ``Unpack`` being used explicitly in older versions
-   of Python, where ``*`` couldn't be used in certain places::
-
-      # In older versions of Python, TypeVarTuple and Unpack
-      # are located in the `typing_extensions` backports package.
-      from typing_extensions import TypeVarTuple, Unpack
-
-      Ts = TypeVarTuple('Ts')
-      tup: tuple[*Ts]         # Syntax error on Python <= 3.10!
-      tup: tuple[Unpack[Ts]]  # Semantically equivalent, and backwards-compatible
-
-   .. versionadded:: 3.11
-
 .. class:: ParamSpec(name, *, bound=None, covariant=False, contravariant=False)
 
    Parameter specification variable.  A specialized version of
@@ -1528,106 +1565,6 @@ These are not used in annotations. They
    .. versionadded:: 3.10
 
 
-.. data:: AnyStr
-
-   ``AnyStr`` is a :class:`constrained type variable <TypeVar>` defined as
-   ``AnyStr = TypeVar('AnyStr', str, bytes)``.
-
-   It is meant to be used for functions that may accept any kind of string
-   without allowing different kinds of strings to mix. For example::
-
-      def concat(a: AnyStr, b: AnyStr) -> AnyStr:
-          return a + b
-
-      concat(u"foo", u"bar")  # Ok, output has type 'unicode'
-      concat(b"foo", b"bar")  # Ok, output has type 'bytes'
-      concat(u"foo", b"bar")  # Error, cannot mix unicode and bytes
-
-.. class:: Protocol(Generic)
-
-   Base class for protocol classes. Protocol classes are defined like this::
-
-      class Proto(Protocol):
-          def meth(self) -> int:
-              ...
-
-   Such classes are primarily used with static type checkers that recognize
-   structural subtyping (static duck-typing), for example::
-
-      class C:
-          def meth(self) -> int:
-              return 0
-
-      def func(x: Proto) -> int:
-          return x.meth()
-
-      func(C())  # Passes static type check
-
-   See :pep:`544` for more details. Protocol classes decorated with
-   :func:`runtime_checkable` (described later) act as simple-minded runtime
-   protocols that check only the presence of given attributes, ignoring their
-   type signatures.
-
-   Protocol classes can be generic, for example::
-
-      class GenProto(Protocol[T]):
-          def meth(self) -> T:
-              ...
-
-   .. versionadded:: 3.8
-
-.. decorator:: runtime_checkable
-
-   Mark a protocol class as a runtime protocol.
-
-   Such a protocol can be used with :func:`isinstance` and :func:`issubclass`.
-   This raises :exc:`TypeError` when applied to a non-protocol class.  This
-   allows a simple-minded structural check, very similar to "one trick ponies"
-   in :mod:`collections.abc` such as :class:`~collections.abc.Iterable`.  For example::
-
-      @runtime_checkable
-      class Closable(Protocol):
-          def close(self): ...
-
-      assert isinstance(open('/some/file'), Closable)
-
-      @runtime_checkable
-      class Named(Protocol):
-          name: str
-
-      import threading
-      assert isinstance(threading.Thread(name='Bob'), Named)
-
-   .. versionchanged:: 3.12
-      The internal implementation of :func:`isinstance` checks against
-      runtime-checkable protocols now uses :func:`inspect.getattr_static`
-      to look up attributes (previously, :func:`hasattr` was used).
-      As a result, some objects which used to be considered instances
-      of a runtime-checkable protocol may no longer be considered instances
-      of that protocol on Python 3.12+, and vice versa.
-      Most users are unlikely to be affected by this change.
-
-   .. note::
-
-        :func:`!runtime_checkable` will check only the presence of the required
-        methods or attributes, not their type signatures or types.
-        For example, :class:`ssl.SSLObject`
-        is a class, therefore it passes an :func:`issubclass`
-        check against :data:`Callable`.  However, the
-        ``ssl.SSLObject.__init__`` method exists only to raise a
-        :exc:`TypeError` with a more informative message, therefore making
-        it impossible to call (instantiate) :class:`ssl.SSLObject`.
-
-   .. note::
-
-        An :func:`isinstance` check against a runtime-checkable protocol can be
-        surprisingly slow compared to an ``isinstance()`` check against
-        a non-protocol class. Consider using alternative idioms such as
-        :func:`hasattr` calls for structural checks in performance-sensitive
-        code.
-
-   .. versionadded:: 3.8
-
 Other special directives
 """"""""""""""""""""""""
 
@@ -1716,6 +1653,100 @@ These are not used in annotations. They
    .. versionchanged:: 3.10
       ``NewType`` is now a class rather than a function.
 
+.. class:: Protocol(Generic)
+
+   Base class for protocol classes. Protocol classes are defined like this::
+
+      class Proto(Protocol):
+          def meth(self) -> int:
+              ...
+
+   Such classes are primarily used with static type checkers that recognize
+   structural subtyping (static duck-typing), for example::
+
+      class C:
+          def meth(self) -> int:
+              return 0
+
+      def func(x: Proto) -> int:
+          return x.meth()
+
+      func(C())  # Passes static type check
+
+   See :pep:`544` for more details. Protocol classes decorated with
+   :func:`runtime_checkable` (described later) act as simple-minded runtime
+   protocols that check only the presence of given attributes, ignoring their
+   type signatures.
+
+   Protocol classes can be generic, for example::
+
+      class GenProto(Protocol[T]):
+          def meth(self) -> T:
+              ...
+
+   .. versionadded:: 3.8
+
+.. decorator:: runtime_checkable
+
+   Mark a protocol class as a runtime protocol.
+
+   Such a protocol can be used with :func:`isinstance` and :func:`issubclass`.
+   This raises :exc:`TypeError` when applied to a non-protocol class.  This
+   allows a simple-minded structural check, very similar to "one trick ponies"
+   in :mod:`collections.abc` such as :class:`~collections.abc.Iterable`.  For example::
+
+      @runtime_checkable
+      class Closable(Protocol):
+          def close(self): ...
+
+      assert isinstance(open('/some/file'), Closable)
+
+      @runtime_checkable
+      class Named(Protocol):
+          name: str
+
+      import threading
+      assert isinstance(threading.Thread(name='Bob'), Named)
+
+   .. note::
+
+        :func:`!runtime_checkable` will check only the presence of the required
+        methods or attributes, not their type signatures or types.
+        For example, :class:`ssl.SSLObject`
+        is a class, therefore it passes an :func:`issubclass`
+        check against :data:`Callable`.  However, the
+        ``ssl.SSLObject.__init__`` method exists only to raise a
+        :exc:`TypeError` with a more informative message, therefore making
+        it impossible to call (instantiate) :class:`ssl.SSLObject`.
+
+   .. note::
+
+        An :func:`isinstance` check against a runtime-checkable protocol can be
+        surprisingly slow compared to an ``isinstance()`` check against
+        a non-protocol class. Consider using alternative idioms such as
+        :func:`hasattr` calls for structural checks in performance-sensitive
+        code.
+
+   .. versionadded:: 3.8
+
+   .. versionchanged:: 3.12
+      The internal implementation of :func:`isinstance` checks against
+      runtime-checkable protocols now uses :func:`inspect.getattr_static`
+      to look up attributes (previously, :func:`hasattr` was used).
+      As a result, some objects which used to be considered instances
+      of a runtime-checkable protocol may no longer be considered instances
+      of that protocol on Python 3.12+, and vice versa.
+      Most users are unlikely to be affected by this change.
+
+   .. versionchanged:: 3.12
+      The members of a runtime-checkable protocol are now considered "frozen"
+      at runtime as soon as the class has been created. Monkey-patching
+      attributes onto a runtime-checkable protocol will still work, but will
+      have no impact on :func:`isinstance` checks comparing objects to the
+      protocol. See :ref:`"What's new in Python 3.12" <whatsnew-typing-py312>`
+      for more details.
+
+
 .. class:: TypedDict(dict)
 
    Special construct to add type hints to a dictionary.
@@ -2083,7 +2114,7 @@ Other concrete types
       Python 2 is no longer supported, and most type checkers also no longer
       support type checking Python 2 code. Removal of the alias is not
       currently planned, but users are encouraged to use
-      :class:`str` instead of ``Text`` wherever possible.
+      :class:`str` instead of ``Text``.
 
 Abstract Base Classes
 ---------------------
@@ -2101,17 +2132,11 @@ Corresponding to collections in :mod:`co
 
 .. class:: ByteString(Sequence[int])
 
-   A generic version of :class:`collections.abc.ByteString`.
-
    This type represents the types :class:`bytes`, :class:`bytearray`,
    and :class:`memoryview` of byte sequences.
 
-   As a shorthand for this type, :class:`bytes` can be used to
-   annotate arguments of any of the types mentioned above.
-
-   .. deprecated:: 3.9
-      :class:`collections.abc.ByteString` now supports subscripting (``[]``).
-      See :pep:`585` and :ref:`types-genericalias`.
+   .. deprecated-removed:: 3.9 3.14
+      Prefer :class:`collections.abc.Buffer`, or a union like ``bytes | bytearray | memoryview``.
 
 .. class:: Collection(Sized, Iterable[T_co], Container[T_co])
 
@@ -2455,15 +2480,16 @@ Functions and decorators
 
    Ask a static type checker to confirm that *val* has an inferred type of *typ*.
 
-   When the type checker encounters a call to ``assert_type()``, it
+   At runtime this does nothing: it returns the first argument unchanged with no
+   checks or side effects, no matter the actual type of the argument.
+
+   When a static type checker encounters a call to ``assert_type()``, it
    emits an error if the value is not of the specified type::
 
        def greet(name: str) -> None:
            assert_type(name, str)  # OK, inferred type of `name` is `str`
            assert_type(name, int)  # type checker error
 
-   At runtime this returns the first argument unchanged with no side effects.
-
    This function is useful for ensuring the type checker's understanding of a
    script is in line with the developer's intentions::
 
@@ -2852,24 +2878,37 @@ Introspection helpers
       if a default value equal to ``None`` was set.
       Now the annotation is returned unchanged.
 
-.. function:: get_args(tp)
 .. function:: get_origin(tp)
 
-   Provide basic introspection for generic types and special typing forms.
-
-   For a typing object of the form ``X[Y, Z, ...]`` these functions return
-   ``X`` and ``(Y, Z, ...)``. If ``X`` is a generic alias for a builtin or
+   Get the unsubscripted version of a type: for a typing object of the form
+   ``X[Y, Z, ...]`` return ``X``. If ``X`` is a generic alias for a builtin or
    :mod:`collections` class, it gets normalized to the original class.
+   If ``X`` is an instance of :class:`ParamSpecArgs` or :class:`ParamSpecKwargs`,
+   return the underlying :class:`ParamSpec`.
+   Return ``None`` for unsupported objects.
+   Examples::
+
+      assert get_origin(str) is None
+      assert get_origin(Dict[str, int]) is dict
+      assert get_origin(Union[int, str]) is Union
+      P = ParamSpec('P')
+      assert get_origin(P.args) is P
+      assert get_origin(P.kwargs) is P
+
+   .. versionadded:: 3.8
+
+.. function:: get_args(tp)
+
+   Get type arguments with all substitutions performed: for a typing object
+   of the form ``X[Y, Z, ...]`` return ``(Y, Z, ...)``.
    If ``X`` is a union or :class:`Literal` contained in another
    generic type, the order of ``(Y, Z, ...)`` may be different from the order
    of the original arguments ``[Y, Z, ...]`` due to type caching.
-   For unsupported objects return ``None`` and ``()`` correspondingly.
+   Return ``()`` for unsupported objects.
    Examples::
 
-      assert get_origin(Dict[str, int]) is dict
+      assert get_args(int) == ()
       assert get_args(Dict[int, str]) == (int, str)
-
-      assert get_origin(Union[int, str]) is Union
       assert get_args(Union[int, str]) == (int, str)
 
    .. versionadded:: 3.8
@@ -2948,6 +2987,8 @@ convenience. This is subject to change,
 |  ``typing`` versions of standard | 3.9           | Undecided         | :pep:`585`     |
 |  collections                     |               |                   |                |
 +----------------------------------+---------------+-------------------+----------------+
+|  ``typing.ByteString``           | 3.9           | 3.14              | :gh:`91896`    |
++----------------------------------+---------------+-------------------+----------------+
 |  ``typing.Text``                 | 3.11          | Undecided         | :gh:`92332`    |
 +----------------------------------+---------------+-------------------+----------------+
 |  ``typing.Hashable`` and         | 3.12          | Undecided         | :gh:`94309`    |
diff -pruN 3.12.0~a7-1/Doc/library/unittest.mock-examples.rst 3.12.0~b1-1/Doc/library/unittest.mock-examples.rst
--- 3.12.0~a7-1/Doc/library/unittest.mock-examples.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/unittest.mock-examples.rst	2023-05-22 12:07:36.000000000 +0000
@@ -1074,7 +1074,7 @@ subclass.
 Sometimes this is inconvenient. For example, `one user
 <https://code.google.com/archive/p/mock/issues/105>`_ is subclassing mock to
 created a `Twisted adaptor
-<https://twistedmatrix.com/documents/11.0.0/api/twisted.python.components.html>`_.
+<https://twisted.org/documents/11.0.0/api/twisted.python.components.html>`_.
 Having this applied to attributes too actually causes errors.
 
 ``Mock`` (in all its flavours) uses a method called ``_get_child_mock`` to create
diff -pruN 3.12.0~a7-1/Doc/library/unittest.rst 3.12.0~b1-1/Doc/library/unittest.rst
--- 3.12.0~a7-1/Doc/library/unittest.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/unittest.rst	2023-05-22 12:07:36.000000000 +0000
@@ -72,7 +72,7 @@ test runner
    a GUI tool for test discovery and execution.  This is intended largely for ease of use
    for those new to unit testing.  For production environments it is
    recommended that tests be driven by a continuous integration system such as
-   `Buildbot <https://buildbot.net/>`_, `Jenkins <https://jenkins.io/>`_,
+   `Buildbot <https://buildbot.net/>`_, `Jenkins <https://www.jenkins.io/>`_,
    `GitHub Actions <https://github.com/features/actions>`_, or
    `AppVeyor <https://www.appveyor.com/>`_.
 
@@ -2191,10 +2191,6 @@ Loading and running tests
    .. versionadded:: 3.12
       Added *durations* keyword argument.
 
-   .. versionchanged:: 3.12
-      Subclasses should accept ``**kwargs`` to ensure compatibility as the
-      interface changes.
-
 .. data:: defaultTestLoader
 
    Instance of the :class:`TestLoader` class intended to be shared.  If no
@@ -2285,7 +2281,8 @@ Loading and running tests
 
    The *testRunner* argument can either be a test runner class or an already
    created instance of it. By default ``main`` calls :func:`sys.exit` with
-   an exit code indicating success or failure of the tests run.
+   an exit code indicating success (0) or failure (1) of the tests run.
+   An exit code of 5 indicates that no tests were run.
 
    The *testLoader* argument has to be a :class:`TestLoader` instance,
    and defaults to :data:`defaultTestLoader`.
diff -pruN 3.12.0~a7-1/Doc/library/urllib.parse.rst 3.12.0~b1-1/Doc/library/urllib.parse.rst
--- 3.12.0~a7-1/Doc/library/urllib.parse.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/urllib.parse.rst	2023-05-22 12:07:36.000000000 +0000
@@ -159,6 +159,10 @@ or on combining URL components into a UR
       ParseResult(scheme='http', netloc='www.cwi.nl:80', path='/%7Eguido/Python.html',
                   params='', query='', fragment='')
 
+   .. warning::
+
+      :func:`urlparse` does not perform validation.  See :ref:`URL parsing
+      security <url-parsing-security>` for details.
 
    .. versionchanged:: 3.2
       Added IPv6 URL parsing capabilities.
@@ -324,8 +328,14 @@ or on combining URL components into a UR
    ``#``, ``@``, or ``:`` will raise a :exc:`ValueError`. If the URL is
    decomposed before parsing, no error will be raised.
 
-   Following the `WHATWG spec`_ that updates RFC 3986, ASCII newline
-   ``\n``, ``\r`` and tab ``\t`` characters are stripped from the URL.
+   Following some of the `WHATWG spec`_ that updates RFC 3986, leading C0
+   control and space characters are stripped from the URL. ``\n``,
+   ``\r`` and tab ``\t`` characters are removed from the URL at any position.
+
+   .. warning::
+
+      :func:`urlsplit` does not perform validation.  See :ref:`URL parsing
+      security <url-parsing-security>` for details.
 
    .. versionchanged:: 3.6
       Out-of-range port numbers now raise :exc:`ValueError`, instead of
@@ -338,6 +348,9 @@ or on combining URL components into a UR
    .. versionchanged:: 3.10
       ASCII newline and tab characters are stripped from the URL.
 
+   .. versionchanged:: 3.12
+      Leading WHATWG C0 control and space characters are stripped from the URL.
+
 .. _WHATWG spec: https://url.spec.whatwg.org/#concept-basic-url-parser
 
 .. function:: urlunsplit(parts)
@@ -414,6 +427,35 @@ or on combining URL components into a UR
    or ``scheme://host/path``). If *url* is not a wrapped URL, it is returned
    without changes.
 
+.. _url-parsing-security:
+
+URL parsing security
+--------------------
+
+The :func:`urlsplit` and :func:`urlparse` APIs do not perform **validation** of
+inputs.  They may not raise errors on inputs that other applications consider
+invalid.  They may also succeed on some inputs that might not be considered
+URLs elsewhere.  Their purpose is for practical functionality rather than
+purity.
+
+Instead of raising an exception on unusual input, they may instead return some
+component parts as empty strings. Or components may contain more than perhaps
+they should.
+
+We recommend that users of these APIs where the values may be used anywhere
+with security implications code defensively. Do some verification within your
+code before trusting a returned component part.  Does that ``scheme`` make
+sense?  Is that a sensible ``path``?  Is there anything strange about that
+``hostname``?  etc.
+
+What constitutes a URL is not universally well defined.  Different applications
+have different needs and desired constraints.  For instance the living `WHATWG
+spec`_ describes what user facing web clients such as a web browser require.
+While :rfc:`3986` is more general.  These functions incorporate some aspects of
+both, but cannot be claimed compliant with either.  The APIs and existing user
+code with expectations on specific behaviors predate both standards leading us
+to be very cautious about making API behavior changes.
+
 .. _parsing-ascii-encoded-bytes:
 
 Parsing ASCII Encoded Bytes
diff -pruN 3.12.0~a7-1/Doc/library/urllib.request.rst 3.12.0~b1-1/Doc/library/urllib.request.rst
--- 3.12.0~a7-1/Doc/library/urllib.request.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/urllib.request.rst	2023-05-22 12:07:36.000000000 +0000
@@ -28,8 +28,8 @@ The :mod:`urllib.request` module defines
 
 .. function:: urlopen(url, data=None[, timeout], *, cafile=None, capath=None, cadefault=False, context=None)
 
-   Open the URL *url*, which can be either a string or a
-   :class:`Request` object.
+   Open *url*, which can be either a string containing a valid, properly
+   encoded URL, or a :class:`Request` object.
 
    *data* must be an object specifying additional data to be sent to the
    server, or ``None`` if no such data is needed.  See :class:`Request`
@@ -192,7 +192,7 @@ The following classes are provided:
 
    This class is an abstraction of a URL request.
 
-   *url* should be a string containing a valid URL.
+   *url* should be a string containing a valid, properly encoded URL.
 
    *data* must be an object specifying additional data to send to the
    server, or ``None`` if no such data is needed.  Currently HTTP
diff -pruN 3.12.0~a7-1/Doc/library/venv.rst 3.12.0~b1-1/Doc/library/venv.rst
--- 3.12.0~a7-1/Doc/library/venv.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/venv.rst	2023-05-22 12:07:36.000000000 +0000
@@ -55,7 +55,7 @@ point to the directories of the virtual
 whereas :data:`sys.base_prefix` and :data:`sys.base_exec_prefix`
 point to those of the base Python used to create the environment.
 It is sufficient to check
-``sys.prefix == sys.base_prefix`` to determine if the current interpreter is
+``sys.prefix != sys.base_prefix`` to determine if the current interpreter is
 running from a virtual environment.
 
 A virtual environment may be "activated" using a script in its binary directory
@@ -284,11 +284,14 @@ creation according to their needs, the :
 
     .. method:: upgrade_dependencies(context)
 
-       Upgrades the core venv dependency packages (currently ``pip`` and
-       ``setuptools``) in the environment. This is done by shelling out to the
+       Upgrades the core venv dependency packages (currently ``pip``)
+       in the environment. This is done by shelling out to the
        ``pip`` executable in the environment.
 
        .. versionadded:: 3.9
+       .. versionchanged:: 3.12
+
+          ``setuptools`` is no longer a core venv dependency.
 
     .. method:: post_setup(context)
 
diff -pruN 3.12.0~a7-1/Doc/library/xmlrpc.client.rst 3.12.0~b1-1/Doc/library/xmlrpc.client.rst
--- 3.12.0~a7-1/Doc/library/xmlrpc.client.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/xmlrpc.client.rst	2023-05-22 12:07:36.000000000 +0000
@@ -161,7 +161,7 @@ between conformable Python objects and X
 
 .. seealso::
 
-   `XML-RPC HOWTO <https://www.tldp.org/HOWTO/XML-RPC-HOWTO/index.html>`_
+   `XML-RPC HOWTO <https://tldp.org/HOWTO/XML-RPC-HOWTO/index.html>`_
       A good description of XML-RPC operation and client software in several languages.
       Contains pretty much everything an XML-RPC client developer needs to know.
 
diff -pruN 3.12.0~a7-1/Doc/library/zipfile.rst 3.12.0~b1-1/Doc/library/zipfile.rst
--- 3.12.0~a7-1/Doc/library/zipfile.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/zipfile.rst	2023-05-22 12:07:36.000000000 +0000
@@ -7,7 +7,7 @@
 .. moduleauthor:: James C. Ahlstrom <jim@interet.com>
 .. sectionauthor:: James C. Ahlstrom <jim@interet.com>
 
-**Source code:** :source:`Lib/zipfile.py`
+**Source code:** :source:`Lib/zipfile/`
 
 --------------
 
@@ -128,7 +128,7 @@ The module defines the following items:
       Documentation on the ZIP file format by Phil Katz, the creator of the format and
       algorithms used.
 
-   `Info-ZIP Home Page <http://www.info-zip.org/>`_
+   `Info-ZIP Home Page <https://infozip.sourceforge.net/>`_
       Information about the Info-ZIP project's ZIP archive programs and development
       libraries.
 
diff -pruN 3.12.0~a7-1/Doc/library/zipimport.rst 3.12.0~b1-1/Doc/library/zipimport.rst
--- 3.12.0~a7-1/Doc/library/zipimport.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/library/zipimport.rst	2023-05-22 12:07:36.000000000 +0000
@@ -74,6 +74,11 @@ zipimporter Objects
    :exc:`ZipImportError` is raised if *archivepath* doesn't point to a valid ZIP
    archive.
 
+   .. versionchanged:: 3.12
+
+      Methods ``find_loader()`` and ``find_module()``, deprecated in 3.10 are
+      now removed.  Use :meth:`find_spec` instead.
+
    .. method:: create_module(spec)
 
       Implementation of :meth:`importlib.abc.Loader.create_module` that returns
@@ -89,28 +94,6 @@ zipimporter Objects
       .. versionadded:: 3.10
 
 
-   .. method:: find_loader(fullname, path=None)
-
-      An implementation of :meth:`importlib.abc.PathEntryFinder.find_loader`.
-
-      .. deprecated:: 3.10
-
-         Use :meth:`find_spec` instead.
-
-
-   .. method:: find_module(fullname, path=None)
-
-      Search for a module specified by *fullname*. *fullname* must be the fully
-      qualified (dotted) module name. It returns the zipimporter instance itself
-      if the module was found, or :const:`None` if it wasn't. The optional
-      *path* argument is ignored---it's there for compatibility with the
-      importer protocol.
-
-      .. deprecated:: 3.10
-
-         Use :meth:`find_spec` instead.
-
-
    .. method:: find_spec(fullname, target=None)
 
       An implementation of :meth:`importlib.abc.PathEntryFinder.find_spec`.
diff -pruN 3.12.0~a7-1/Doc/reference/compound_stmts.rst 3.12.0~b1-1/Doc/reference/compound_stmts.rst
--- 3.12.0~a7-1/Doc/reference/compound_stmts.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/reference/compound_stmts.rst	2023-05-22 12:07:36.000000000 +0000
@@ -84,9 +84,9 @@ The :keyword:`!if` statement
 ============================
 
 .. index::
-   ! statement: if
-   keyword: elif
-   keyword: else
+   ! pair: statement; if
+   pair: keyword; elif
+   pair: keyword; else
    single: : (colon); compound statement
 
 The :keyword:`if` statement is used for conditional execution:
@@ -109,8 +109,8 @@ The :keyword:`!while` statement
 ===============================
 
 .. index::
-   ! statement: while
-   keyword: else
+   ! pair: statement; while
+   pair: keyword; else
    pair: loop; statement
    single: : (colon); compound statement
 
@@ -127,8 +127,8 @@ suite of the :keyword:`!else` clause, if
 terminates.
 
 .. index::
-   statement: break
-   statement: continue
+   pair: statement; break
+   pair: statement; continue
 
 A :keyword:`break` statement executed in the first suite terminates the loop
 without executing the :keyword:`!else` clause's suite.  A :keyword:`continue`
@@ -142,12 +142,12 @@ The :keyword:`!for` statement
 =============================
 
 .. index::
-   ! statement: for
-   keyword: in
-   keyword: else
+   ! pair: statement; for
+   pair: keyword; in
+   pair: keyword; else
    pair: target; list
    pair: loop; statement
-   object: sequence
+   pair: object; sequence
    single: : (colon); compound statement
 
 The :keyword:`for` statement is used to iterate over the elements of a sequence
@@ -167,8 +167,8 @@ the suite in the :keyword:`!else` clause
 if present, is executed, and the loop terminates.
 
 .. index::
-   statement: break
-   statement: continue
+   pair: statement; break
+   pair: statement; continue
 
 A :keyword:`break` statement executed in the first suite terminates the loop
 without executing the :keyword:`!else` clause's suite.  A :keyword:`continue`
@@ -188,7 +188,7 @@ those made in the suite of the for-loop:
 
 
 .. index::
-   builtin: range
+   pair: built-in function; range
 
 Names in the target list are not deleted when the loop is finished, but if the
 sequence is empty, they will not have been assigned to at all by the loop.  Hint:
@@ -205,11 +205,11 @@ The :keyword:`!try` statement
 =============================
 
 .. index::
-   ! statement: try
-   keyword: except
-   keyword: finally
-   keyword: else
-   keyword: as
+   ! pair: statement; try
+   pair: keyword; except
+   pair: keyword; finally
+   pair: keyword; else
+   pair: keyword; as
    single: : (colon); compound statement
 
 The :keyword:`!try` statement specifies exception handlers and/or cleanup code
@@ -297,8 +297,8 @@ traceback attached to them, they form a
 keeping all locals in that frame alive until the next garbage collection occurs.
 
 .. index::
-   module: sys
-   object: traceback
+   pair: module; sys
+   pair: object; traceback
 
 Before an :keyword:`!except` clause's suite is executed,
 the exception is stored in the :mod:`sys` module, where it can be accessed
@@ -326,7 +326,7 @@ stored in the :mod:`sys` module is reset
 
 
 .. index::
-   keyword: except_star
+   pair: keyword; except_star
 
 .. _except_star:
 
@@ -362,8 +362,10 @@ one :keyword:`!except*` clause, the firs
 
 
 Any remaining exceptions that were not handled by any :keyword:`!except*`
-clause are re-raised at the end, combined into an exception group along with
-all exceptions that were raised from within :keyword:`!except*` clauses.
+clause are re-raised at the end, along with all exceptions that were
+raised from within the :keyword:`!except*` clauses. If this list contains
+more than one exception to reraise, they are combined into an exception
+group.
 
 If the raised exception is not an exception group and its type matches
 one of the :keyword:`!except*` clauses, it is caught and wrapped by an
@@ -385,10 +387,10 @@ cannot appear in an :keyword:`!except*`
 
 
 .. index::
-   keyword: else
-   statement: return
-   statement: break
-   statement: continue
+   pair: keyword; else
+   pair: statement; return
+   pair: statement; break
+   pair: statement; continue
 
 .. _except_else:
 
@@ -402,7 +404,7 @@ the :keyword:`!else` clause are not hand
 clauses.
 
 
-.. index:: keyword: finally
+.. index:: pair: keyword; finally
 
 .. _finally:
 
@@ -432,9 +434,9 @@ The exception information is not availab
 the :keyword:`!finally` clause.
 
 .. index::
-   statement: return
-   statement: break
-   statement: continue
+   pair: statement; return
+   pair: statement; break
+   pair: statement; continue
 
 When a :keyword:`return`, :keyword:`break` or :keyword:`continue` statement is
 executed in the :keyword:`try` suite of a :keyword:`!try`...\ :keyword:`!finally`
@@ -466,8 +468,8 @@ The :keyword:`!with` statement
 ==============================
 
 .. index::
-   ! statement: with
-   keyword: as
+   ! pair: statement; with
+   pair: keyword; as
    single: as; with statement
    single: , (comma); with statement
    single: : (colon); compound statement
@@ -583,11 +585,11 @@ The :keyword:`!match` statement
 ===============================
 
 .. index::
-   ! statement: match
-   ! keyword: case
+   ! pair: statement; match
+   ! pair: keyword; case
    ! single: pattern matching
-   keyword: if
-   keyword: as
+   pair: keyword; if
+   pair: keyword; as
    pair: match; case
    single: as; match statement
    single: : (colon); compound statement
@@ -1188,12 +1190,12 @@ Function definitions
 ====================
 
 .. index::
-   statement: def
+   pair: statement; def
    pair: function; definition
    pair: function; name
    pair: name; binding
-   object: user-defined function
-   object: function
+   pair: object; user-defined function
+   pair: object; function
    pair: function; name
    pair: name; binding
    single: () (parentheses); function definition
@@ -1361,8 +1363,8 @@ Class definitions
 =================
 
 .. index::
-   object: class
-   statement: class
+   pair: object; class
+   pair: statement; class
    pair: class; definition
    pair: class; name
    pair: name; binding
@@ -1461,7 +1463,7 @@ Coroutines
 
 .. versionadded:: 3.5
 
-.. index:: statement: async def
+.. index:: pair: statement; async def
 .. _`async def`:
 
 Coroutine function definition
@@ -1472,8 +1474,8 @@ Coroutine function definition
                 : ["->" `expression`] ":" `suite`
 
 .. index::
-   keyword: async
-   keyword: await
+   pair: keyword; async
+   pair: keyword; await
 
 Execution of Python coroutines can be suspended and resumed at many points
 (see :term:`coroutine`). :keyword:`await` expressions, :keyword:`async for` and
@@ -1495,7 +1497,7 @@ An example of a coroutine function::
    ``await`` and ``async`` are now keywords; previously they were only
    treated as such inside the body of a coroutine function.
 
-.. index:: statement: async for
+.. index:: pair: statement; async for
 .. _`async for`:
 
 The :keyword:`!async for` statement
@@ -1540,7 +1542,7 @@ It is a :exc:`SyntaxError` to use an ``a
 body of a coroutine function.
 
 
-.. index:: statement: async with
+.. index:: pair: statement; async with
 .. _`async with`:
 
 The :keyword:`!async with` statement
diff -pruN 3.12.0~a7-1/Doc/reference/datamodel.rst 3.12.0~b1-1/Doc/reference/datamodel.rst
--- 3.12.0~a7-1/Doc/reference/datamodel.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/reference/datamodel.rst	2023-05-22 12:07:36.000000000 +0000
@@ -21,8 +21,8 @@ conformance to Von Neumann's model of a
 represented by objects.)
 
 .. index::
-   builtin: id
-   builtin: type
+   pair: built-in function; id
+   pair: built-in function; type
    single: identity of an object
    single: value of an object
    single: type of an object
@@ -142,7 +142,7 @@ attributes.'  These are attributes that
 are not intended for general use.  Their definition may change in the future.
 
 None
-   .. index:: object: None
+   .. index:: pair: object; None
 
    This type has a single value.  There is a single object with this value. This
    object is accessed through the built-in name ``None``. It is used to signify the
@@ -150,7 +150,7 @@ None
    don't explicitly return anything. Its truth value is false.
 
 NotImplemented
-   .. index:: object: NotImplemented
+   .. index:: pair: object; NotImplemented
 
    This type has a single value.  There is a single object with this value. This
    object is accessed through the built-in name ``NotImplemented``. Numeric methods
@@ -171,7 +171,7 @@ NotImplemented
 
 Ellipsis
    .. index::
-      object: Ellipsis
+      pair: object; Ellipsis
       single: ...; ellipsis literal
 
    This type has a single value.  There is a single object with this value. This
@@ -179,7 +179,7 @@ Ellipsis
    ``Ellipsis``.  Its truth value is true.
 
 :class:`numbers.Number`
-   .. index:: object: numeric
+   .. index:: pair: object; numeric
 
    These are created by numeric literals and returned as results by arithmetic
    operators and arithmetic built-in functions.  Numeric objects are immutable;
@@ -209,7 +209,7 @@ Ellipsis
    numbers:
 
    :class:`numbers.Integral`
-      .. index:: object: integer
+      .. index:: pair: object; integer
 
       These represent elements from the mathematical set of integers (positive and
       negative).
@@ -225,7 +225,7 @@ Ellipsis
 
       Booleans (:class:`bool`)
          .. index::
-            object: Boolean
+            pair: object; Boolean
             single: False
             single: True
 
@@ -242,7 +242,7 @@ Ellipsis
 
    :class:`numbers.Real` (:class:`float`)
       .. index::
-         object: floating point
+         pair: object; floating point
          pair: floating point; number
          pair: C; language
          pair: Java; language
@@ -257,7 +257,7 @@ Ellipsis
 
    :class:`numbers.Complex` (:class:`complex`)
       .. index::
-         object: complex
+         pair: object; complex
          pair: complex; number
 
       These represent complex numbers as a pair of machine-level double precision
@@ -267,8 +267,8 @@ Ellipsis
 
 Sequences
    .. index::
-      builtin: len
-      object: sequence
+      pair: built-in function; len
+      pair: object; sequence
       single: index operation
       single: item selection
       single: subscription
@@ -293,8 +293,8 @@ Sequences
 
    Immutable sequences
       .. index::
-         object: immutable sequence
-         object: immutable
+         pair: object; immutable sequence
+         pair: object; immutable
 
       An object of an immutable sequence type cannot change once it is created.  (If
       the object contains references to other objects, these other objects may be
@@ -308,8 +308,8 @@ Sequences
 
       Strings
          .. index::
-            builtin: chr
-            builtin: ord
+            pair: built-in function; chr
+            pair: built-in function; ord
             single: character
             single: integer
             single: Unicode
@@ -328,7 +328,7 @@ Sequences
 
       Tuples
          .. index::
-            object: tuple
+            pair: object; tuple
             pair: singleton; tuple
             pair: empty; tuple
 
@@ -350,8 +350,8 @@ Sequences
 
    Mutable sequences
       .. index::
-         object: mutable sequence
-         object: mutable
+         pair: object; mutable sequence
+         pair: object; mutable
          pair: assignment; statement
          single: subscription
          single: slicing
@@ -363,7 +363,7 @@ Sequences
       There are currently two intrinsic mutable sequence types:
 
       Lists
-         .. index:: object: list
+         .. index:: pair: object; list
 
          The items of a list are arbitrary Python objects.  Lists are formed by
          placing a comma-separated list of expressions in square brackets. (Note
@@ -377,15 +377,15 @@ Sequences
          (and hence unhashable), byte arrays otherwise provide the same interface
          and functionality as immutable :class:`bytes` objects.
 
-      .. index:: module: array
+      .. index:: pair: module; array
 
       The extension module :mod:`array` provides an additional example of a
       mutable sequence type, as does the :mod:`collections` module.
 
 Set types
    .. index::
-      builtin: len
-      object: set type
+      pair: built-in function; len
+      pair: object; set type
 
    These represent unordered, finite sets of unique, immutable objects. As such,
    they cannot be indexed by any subscript. However, they can be iterated over, and
@@ -402,14 +402,14 @@ Set types
    There are currently two intrinsic set types:
 
    Sets
-      .. index:: object: set
+      .. index:: pair: object; set
 
       These represent a mutable set. They are created by the built-in :func:`set`
       constructor and can be modified afterwards by several methods, such as
       :meth:`~set.add`.
 
    Frozen sets
-      .. index:: object: frozenset
+      .. index:: pair: object; frozenset
 
       These represent an immutable set.  They are created by the built-in
       :func:`frozenset` constructor.  As a frozenset is immutable and
@@ -418,9 +418,9 @@ Set types
 
 Mappings
    .. index::
-      builtin: len
+      pair: built-in function; len
       single: subscription
-      object: mapping
+      pair: object; mapping
 
    These represent finite sets of objects indexed by arbitrary index sets. The
    subscript notation ``a[k]`` selects the item indexed by ``k`` from the mapping
@@ -431,7 +431,7 @@ Mappings
    There is currently a single intrinsic mapping type:
 
    Dictionaries
-      .. index:: object: dictionary
+      .. index:: pair: object; dictionary
 
       These represent finite sets of objects indexed by nearly arbitrary values.  The
       only types of values not acceptable as keys are values containing lists or
@@ -451,8 +451,8 @@ Mappings
       section :ref:`dict`).
 
       .. index::
-         module: dbm.ndbm
-         module: dbm.gnu
+         pair: module; dbm.ndbm
+         pair: module; dbm.gnu
 
       The extension modules :mod:`dbm.ndbm` and :mod:`dbm.gnu` provide
       additional examples of mapping types, as does the :mod:`collections`
@@ -465,7 +465,7 @@ Mappings
 
 Callable types
    .. index::
-      object: callable
+      pair: object; callable
       pair: function; call
       single: invocation
       pair: function; argument
@@ -476,8 +476,8 @@ Callable types
    User-defined functions
       .. index::
          pair: user-defined; function
-         object: function
-         object: user-defined function
+         pair: object; function
+         pair: object; user-defined function
 
       A user-defined function object is created by a function definition (see
       section :ref:`function`).  It should be called with an argument list
@@ -580,8 +580,8 @@ Callable types
 
    Instance methods
       .. index::
-         object: method
-         object: user-defined method
+         pair: object; method
+         pair: object; user-defined method
          pair: user-defined; method
 
       An instance method object combines a class, a class instance and any
@@ -688,8 +688,8 @@ Callable types
 
    Built-in functions
       .. index::
-         object: built-in function
-         object: function
+         pair: object; built-in function
+         pair: object; function
          pair: C; language
 
       A built-in function object is a wrapper around a C function.  Examples of
@@ -703,8 +703,8 @@ Callable types
 
    Built-in methods
       .. index::
-         object: built-in method
-         object: method
+         pair: object; built-in method
+         pair: object; method
          pair: built-in; method
 
       This is really a different disguise of a built-in function, this time containing
@@ -727,8 +727,8 @@ Callable types
 
 Modules
    .. index::
-      statement: import
-      object: module
+      pair: statement; import
+      pair: object; module
 
    Modules are a basic organizational unit of Python code, and are created by
    the :ref:`import system <importsystem>` as invoked either by the
@@ -805,12 +805,12 @@ Custom classes
    .. XXX: Could we add that MRO doc as an appendix to the language ref?
 
    .. index::
-      object: class
-      object: class instance
-      object: instance
+      pair: object; class
+      pair: object; class instance
+      pair: object; instance
       pair: class object; call
       single: container
-      object: dictionary
+      pair: object; dictionary
       pair: class; attribute
 
    When a class attribute reference (for class :class:`C`, say) would yield a
@@ -865,8 +865,8 @@ Custom classes
 
 Class instances
    .. index::
-      object: class instance
-      object: instance
+      pair: object; class instance
+      pair: object; instance
       pair: class; instance
       pair: class instance; attribute
 
@@ -892,9 +892,9 @@ Class instances
    dictionary directly.
 
    .. index::
-      object: numeric
-      object: sequence
-      object: mapping
+      pair: object; numeric
+      pair: object; sequence
+      pair: object; mapping
 
    Class instances can pretend to be numbers, sequences, or mappings if they have
    methods with certain special names.  See section :ref:`specialnames`.
@@ -908,8 +908,8 @@ Class instances
 
 I/O objects (also known as file objects)
    .. index::
-      builtin: open
-      module: io
+      pair: built-in function; open
+      pair: module; io
       single: popen() (in module os)
       single: makefile() (socket method)
       single: sys.stdin
@@ -996,7 +996,7 @@ Internal types
       required stack size; :attr:`co_flags` is an integer encoding a number
       of flags for the interpreter.
 
-      .. index:: object: generator
+      .. index:: pair: object; generator
 
       The following flag bits are defined for :attr:`co_flags`: bit ``0x04`` is set if
       the function uses the ``*arguments`` syntax to accept an arbitrary number of
@@ -1053,7 +1053,7 @@ Internal types
    .. _frame-objects:
 
    Frame objects
-      .. index:: object: frame
+      .. index:: pair: object; frame
 
       Frame objects represent execution frames.  They may occur in traceback objects
       (see below), and are also passed to registered trace functions.
@@ -1116,7 +1116,7 @@ Internal types
 
    Traceback objects
       .. index::
-         object: traceback
+         pair: object; traceback
          pair: stack; trace
          pair: exception; handler
          pair: execution; stack
@@ -1151,7 +1151,7 @@ Internal types
          single: tb_frame (traceback attribute)
          single: tb_lineno (traceback attribute)
          single: tb_lasti (traceback attribute)
-         statement: try
+         pair: statement; try
 
       Special read-only attributes:
       :attr:`tb_frame` points to the execution frame of the current level;
@@ -1177,7 +1177,7 @@ Internal types
          and the ``tb_next`` attribute of existing instances can be updated.
 
    Slice objects
-      .. index:: builtin: slice
+      .. index:: pair: built-in function; slice
 
       Slice objects are used to represent slices for
       :meth:`~object.__getitem__`
@@ -1310,7 +1310,7 @@ Basic customization
    .. index::
       single: destructor
       single: finalizer
-      statement: del
+      pair: statement; del
 
    Called when the instance is about to be destroyed.  This is also called a
    finalizer or (improperly) a destructor.  If a base class has a
@@ -1411,7 +1411,7 @@ Basic customization
 
 .. method:: object.__bytes__(self)
 
-   .. index:: builtin: bytes
+   .. index:: pair: built-in function; bytes
 
    Called by :ref:`bytes <func-bytes>` to compute a byte-string representation
    of an object. This should return a :class:`bytes` object.
@@ -1419,7 +1419,7 @@ Basic customization
    .. index::
       single: string; __format__() (object method)
       pair: string; conversion
-      builtin: print
+      pair: built-in function; print
 
 
 .. method:: object.__format__(self, format_spec)
@@ -1498,8 +1498,8 @@ Basic customization
 .. method:: object.__hash__(self)
 
    .. index::
-      object: dictionary
-      builtin: hash
+      pair: object; dictionary
+      pair: built-in function; hash
 
    Called by built-in function :func:`hash` and for operations on members of
    hashed collections including :class:`set`, :class:`frozenset`, and
@@ -1564,7 +1564,7 @@ Basic customization
       This is intended to provide protection against a denial-of-service caused
       by carefully chosen inputs that exploit the worst case performance of a
       dict insertion, O(n\ :sup:`2`) complexity.  See
-      http://www.ocert.org/advisories/ocert-2011-003.html for details.
+      http://ocert.org/advisories/ocert-2011-003.html for details.
 
       Changing hash values affects the iteration order of sets.
       Python has never made guarantees about this ordering
@@ -2050,7 +2050,7 @@ Metaclasses
 
 .. index::
    single: metaclass
-   builtin: type
+   pair: built-in function; type
    single: = (equals); class definition
 
 By default, classes are constructed using :func:`type`. The class body is
@@ -2086,15 +2086,28 @@ When a class definition is executed, the
 Resolving MRO entries
 ^^^^^^^^^^^^^^^^^^^^^
 
-If a base that appears in class definition is not an instance of :class:`type`,
-then an ``__mro_entries__`` method is searched on it. If found, it is called
-with the original bases tuple. This method must return a tuple of classes that
-will be used instead of this base. The tuple may be empty, in such case
-the original base is ignored.
+.. method:: object.__mro_entries__(self, bases)
+
+   If a base that appears in a class definition is not an instance of
+   :class:`type`, then an :meth:`!__mro_entries__` method is searched on the base.
+   If an :meth:`!__mro_entries__` method is found, the base is substituted with the
+   result of a call to :meth:`!__mro_entries__` when creating the class.
+   The method is called with the original bases tuple
+   passed to the *bases* parameter, and must return a tuple
+   of classes that will be used instead of the base. The returned tuple may be
+   empty: in these cases, the original base is ignored.
 
 .. seealso::
 
-   :pep:`560` - Core support for typing module and generic types
+   :func:`types.resolve_bases`
+      Dynamically resolve bases that are not instances of :class:`type`.
+
+   :func:`types.get_original_bases`
+      Retrieve a class's "original bases" prior to modifications by
+      :meth:`~object.__mro_entries__`.
+
+   :pep:`560`
+      Core support for typing module and generic types.
 
 
 Determining the appropriate metaclass
@@ -2464,7 +2477,7 @@ through the object's keys; for sequences
 .. method:: object.__len__(self)
 
    .. index::
-      builtin: len
+      pair: built-in function; len
       single: __bool__() (object method)
 
    Called to implement the built-in function :func:`len`.  Should return the length
@@ -2493,7 +2506,7 @@ through the object's keys; for sequences
    .. versionadded:: 3.4
 
 
-.. index:: object: slice
+.. index:: pair: object; slice
 
 .. note::
 
@@ -2622,9 +2635,9 @@ left undefined.
             object.__or__(self, other)
 
    .. index::
-      builtin: divmod
-      builtin: pow
-      builtin: pow
+      pair: built-in function; divmod
+      pair: built-in function; pow
+      pair: built-in function; pow
 
    These methods are called to implement the binary arithmetic operations
    (``+``, ``-``, ``*``, ``@``, ``/``, ``//``, ``%``, :func:`divmod`,
@@ -2657,8 +2670,8 @@ left undefined.
             object.__ror__(self, other)
 
    .. index::
-      builtin: divmod
-      builtin: pow
+      pair: built-in function; divmod
+      pair: built-in function; pow
 
    These methods are called to implement the binary arithmetic operations
    (``+``, ``-``, ``*``, ``@``, ``/``, ``//``, ``%``, :func:`divmod`,
@@ -2670,7 +2683,7 @@ left undefined.
    ``type(y).__rsub__(y, x)`` is called if ``type(x).__sub__(x, y)`` returns
    *NotImplemented*.
 
-   .. index:: builtin: pow
+   .. index:: pair: built-in function; pow
 
    Note that ternary :func:`pow` will not try calling :meth:`__rpow__` (the
    coercion rules would become too complicated).
@@ -2717,7 +2730,7 @@ left undefined.
             object.__abs__(self)
             object.__invert__(self)
 
-   .. index:: builtin: abs
+   .. index:: pair: built-in function; abs
 
    Called to implement the unary arithmetic operations (``-``, ``+``, :func:`abs`
    and ``~``).
@@ -2728,9 +2741,9 @@ left undefined.
             object.__float__(self)
 
    .. index::
-      builtin: complex
-      builtin: int
-      builtin: float
+      pair: built-in function; complex
+      pair: built-in function; int
+      pair: built-in function; float
 
    Called to implement the built-in functions :func:`complex`,
    :func:`int` and :func:`float`.  Should return a value
@@ -2755,7 +2768,7 @@ left undefined.
             object.__floor__(self)
             object.__ceil__(self)
 
-   .. index:: builtin: round
+   .. index:: pair: built-in function; round
 
    Called to implement the built-in function :func:`round` and :mod:`math`
    functions :func:`~math.trunc`, :func:`~math.floor` and :func:`~math.ceil`.
@@ -2783,7 +2796,7 @@ execution of the block of code.  Context
 used by directly invoking their methods.
 
 .. index::
-   statement: with
+   pair: statement; with
    single: context manager
 
 Typical uses of context managers include saving and restoring various kinds of
@@ -2852,6 +2865,47 @@ a :exc:`TypeError`.
       The specification for the Python ``match`` statement.
 
 
+.. _python-buffer-protocol:
+
+Emulating buffer types
+----------------------
+
+The :ref:`buffer protocol <bufferobjects>` provides a way for Python
+objects to expose efficient access to a low-level memory array. This protocol
+is implemented by builtin types such as :class:`bytes` and :class:`memoryview`,
+and third-party libraries may define additional buffer types.
+
+While buffer types are usually implemented in C, it is also possible to
+implement the protocol in Python.
+
+.. method:: object.__buffer__(self, flags)
+
+   Called when a buffer is requested from *self* (for example, by the
+   :class:`memoryview` constructor). The *flags* argument is an integer
+   representing the kind of buffer requested, affecting for example whether
+   the returned buffer is read-only or writable. :class:`inspect.BufferFlags`
+   provides a convenient way to interpret the flags. The method must return
+   a :class:`memoryview` object.
+
+.. method:: object.__release_buffer__(self, buffer)
+
+   Called when a buffer is no longer needed. The *buffer* argument is a
+   :class:`memoryview` object that was previously returned by
+   :meth:`~object.__buffer__`. The method must release any resources associated
+   with the buffer. This method should return ``None``.
+   Buffer objects that do not need to perform any cleanup are not required
+   to implement this method.
+
+.. versionadded:: 3.12
+
+.. seealso::
+
+   :pep:`688` - Making the buffer protocol accessible in Python
+      Introduces the Python ``__buffer__`` and ``__release_buffer__`` methods.
+
+   :class:`collections.abc.Buffer`
+      ABC for buffer types.
+
 .. _special-lookup:
 
 Special method lookup
diff -pruN 3.12.0~a7-1/Doc/reference/executionmodel.rst 3.12.0~b1-1/Doc/reference/executionmodel.rst
--- 3.12.0~a7-1/Doc/reference/executionmodel.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/reference/executionmodel.rst	2023-05-22 12:07:36.000000000 +0000
@@ -151,7 +151,7 @@ to previously bound variables in the nea
 :exc:`SyntaxError` is raised at compile time if the given name does not
 exist in any enclosing function scope.
 
-.. index:: module: __main__
+.. index:: pair: module; __main__
 
 The namespace for a module is automatically created the first time a module is
 imported.  The main module for a script is always called :mod:`__main__`.
diff -pruN 3.12.0~a7-1/Doc/reference/expressions.rst 3.12.0~b1-1/Doc/reference/expressions.rst
--- 3.12.0~a7-1/Doc/reference/expressions.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/reference/expressions.rst	2023-05-22 12:07:36.000000000 +0000
@@ -71,7 +71,7 @@ An identifier occurring as an atom is a
 for lexical definition and section :ref:`naming` for documentation of naming and
 binding.
 
-.. index:: exception: NameError
+.. index:: pair: exception; NameError
 
 When the name is bound to an object, evaluation of the atom yields that object.
 When a name is not bound, an attempt to evaluate it raises a :exc:`NameError`
@@ -245,7 +245,7 @@ List displays
    pair: list; display
    pair: list; comprehensions
    pair: empty; list
-   object: list
+   pair: object; list
    single: [] (square brackets); list expression
    single: , (comma); expression list
 
@@ -270,7 +270,7 @@ Set displays
 .. index::
    pair: set; display
    pair: set; comprehensions
-   object: set
+   pair: object; set
    single: {} (curly brackets); set expression
    single: , (comma); expression list
 
@@ -299,7 +299,7 @@ Dictionary displays
    pair: dictionary; display
    pair: dictionary; comprehensions
    key, datum, key/datum pair
-   object: dictionary
+   pair: object; dictionary
    single: {} (curly brackets); dictionary expression
    single: : (colon); in dictionary expressions
    single: , (comma); in dictionary displays
@@ -361,7 +361,7 @@ Generator expressions
 
 .. index::
    pair: generator; expression
-   object: generator
+   pair: object; generator
    single: () (parentheses); generator expression
 
 A generator expression is a compact generator notation in parentheses:
@@ -415,8 +415,8 @@ Yield expressions
 -----------------
 
 .. index::
-   keyword: yield
-   keyword: from
+   pair: keyword; yield
+   pair: keyword; from
    pair: yield; expression
    pair: generator; function
 
@@ -522,7 +522,7 @@ on the right hand side of an assignment
       The proposal that expanded on :pep:`492` by adding generator capabilities to
       coroutine functions.
 
-.. index:: object: generator
+.. index:: pair: object; generator
 .. _generator-methods:
 
 Generator-iterator methods
@@ -534,7 +534,7 @@ be used to control the execution of a ge
 Note that calling any of the generator methods below when the generator
 is already executing raises a :exc:`ValueError` exception.
 
-.. index:: exception: StopIteration
+.. index:: pair: exception; StopIteration
 
 
 .. method:: generator.__next__()
@@ -589,7 +589,7 @@ is already executing raises a :exc:`Valu
       The second signature \(type\[, value\[, traceback\]\]\) is deprecated and
       may be removed in a future version of Python.
 
-.. index:: exception: GeneratorExit
+.. index:: pair: exception; GeneratorExit
 
 
 .. method:: generator.close()
@@ -701,7 +701,7 @@ of a *finalizer* method see the implemen
 The expression ``yield from <expr>`` is a syntax error when used in an
 asynchronous generator function.
 
-.. index:: object: asynchronous-generator
+.. index:: pair: object; asynchronous-generator
 .. _asynchronous-generator-methods:
 
 Asynchronous generator-iterator methods
@@ -711,7 +711,7 @@ This subsection describes the methods of
 which are used to control the execution of a generator function.
 
 
-.. index:: exception: StopAsyncIteration
+.. index:: pair: exception; StopAsyncIteration
 
 .. coroutinemethod:: agen.__anext__()
 
@@ -763,7 +763,7 @@ which are used to control the execution
       The second signature \(type\[, value\[, traceback\]\]\) is deprecated and
       may be removed in a future version of Python.
 
-.. index:: exception: GeneratorExit
+.. index:: pair: exception; GeneratorExit
 
 
 .. coroutinemethod:: agen.aclose()
@@ -810,9 +810,9 @@ An attribute reference is a primary foll
    attributeref: `primary` "." `identifier`
 
 .. index::
-   exception: AttributeError
-   object: module
-   object: list
+   pair: exception; AttributeError
+   pair: object; module
+   pair: object; list
 
 The primary must evaluate to an object of a type that supports attribute
 references, which most objects do.  This object is then asked to produce the
@@ -833,12 +833,12 @@ Subscriptions
    single: [] (square brackets); subscription
 
 .. index::
-   object: sequence
-   object: mapping
-   object: string
-   object: tuple
-   object: list
-   object: dictionary
+   pair: object; sequence
+   pair: object; mapping
+   pair: object; string
+   pair: object; tuple
+   pair: object; list
+   pair: object; dictionary
    pair: sequence; item
 
 The subscription of an instance of a :ref:`container class <sequence-types>`
@@ -906,10 +906,10 @@ Slicings
    single: , (comma); slicing
 
 .. index::
-   object: sequence
-   object: string
-   object: tuple
-   object: list
+   pair: object; sequence
+   pair: object; string
+   pair: object; tuple
+   pair: object; list
 
 A slicing selects a range of items in a sequence object (e.g., a string, tuple
 or list).  Slicings may be used as expressions or as targets in assignment or
@@ -950,7 +950,7 @@ substituting ``None`` for missing expres
 
 
 .. index::
-   object: callable
+   pair: object; callable
    single: call
    single: argument; call semantics
    single: () (parentheses); call
@@ -1100,8 +1100,8 @@ a user-defined function:
    .. index::
       pair: function; call
       triple: user-defined; function; call
-      object: user-defined function
-      object: function
+      pair: object; user-defined function
+      pair: object; function
 
    The code block for the function is executed, passing it the argument list.  The
    first thing the code block will do is bind the formal parameters to the
@@ -1115,25 +1115,25 @@ a built-in function or method:
       pair: built-in function; call
       pair: method; call
       pair: built-in method; call
-      object: built-in method
-      object: built-in function
-      object: method
-      object: function
+      pair: object; built-in method
+      pair: object; built-in function
+      pair: object; method
+      pair: object; function
 
    The result is up to the interpreter; see :ref:`built-in-funcs` for the
    descriptions of built-in functions and methods.
 
 a class object:
    .. index::
-      object: class
+      pair: object; class
       pair: class object; call
 
    A new instance of that class is returned.
 
 a class instance method:
    .. index::
-      object: class instance
-      object: instance
+      pair: object; class instance
+      pair: object; instance
       pair: class instance; call
 
    The corresponding user-defined function is called, with an argument list that is
@@ -1149,7 +1149,7 @@ a class instance:
    if that method was called.
 
 
-.. index:: keyword: await
+.. index:: pair: keyword; await
 .. _await:
 
 Await expression
@@ -1171,7 +1171,7 @@ The power operator
 
 .. index::
    pair: power; operation
-   operator: **
+   pair: operator; **
 
 The power operator binds more tightly than unary operators on its left; it binds
 less tightly than unary operators on its right.  The syntax is:
@@ -1232,7 +1232,7 @@ operation can be overridden with the :me
 
 .. index::
    single: inversion
-   operator: ~ (tilde)
+   pair: operator; ~ (tilde)
 
 The unary ``~`` (invert) operator yields the bitwise inversion of its integer
 argument.  The bitwise inversion of ``x`` is defined as ``-(x+1)``.  It only
@@ -1241,7 +1241,7 @@ applies to integral numbers or to custom
 
 
 
-.. index:: exception: TypeError
+.. index:: pair: exception; TypeError
 
 In all three cases, if the argument does not have the proper type, a
 :exc:`TypeError` exception is raised.
@@ -1267,7 +1267,7 @@ operators and one for additive operators
 
 .. index::
    single: multiplication
-   operator: * (asterisk)
+   pair: operator; * (asterisk)
 
 The ``*`` (multiplication) operator yields the product of its arguments.  The
 arguments must either both be numbers, or one argument must be an integer and
@@ -1280,7 +1280,7 @@ This operation can be customized using t
 
 .. index::
    single: matrix multiplication
-   operator: @ (at)
+   pair: operator; @ (at)
 
 The ``@`` (at) operator is intended to be used for matrix multiplication.  No
 builtin Python types implement this operator.
@@ -1288,10 +1288,10 @@ builtin Python types implement this oper
 .. versionadded:: 3.5
 
 .. index::
-   exception: ZeroDivisionError
+   pair: exception; ZeroDivisionError
    single: division
-   operator: / (slash)
-   operator: //
+   pair: operator; / (slash)
+   pair: operator; //
 
 The ``/`` (division) and ``//`` (floor division) operators yield the quotient of
 their arguments.  The numeric arguments are first converted to a common type.
@@ -1305,7 +1305,7 @@ This operation can be customized using t
 
 .. index::
    single: modulo
-   operator: % (percent)
+   pair: operator; % (percent)
 
 The ``%`` (modulo) operator yields the remainder from the division of the first
 argument by the second.  The numeric arguments are first converted to a common
@@ -1363,8 +1363,8 @@ Shifting operations
 
 .. index::
    pair: shifting; operation
-   operator: <<
-   operator: >>
+   pair: operator; <<
+   pair: operator; >>
 
 The shifting operations have lower priority than the arithmetic operations:
 
@@ -1377,7 +1377,7 @@ the left or right by the number of bits
 This operation can be customized using the special :meth:`__lshift__` and
 :meth:`__rshift__` methods.
 
-.. index:: exception: ValueError
+.. index:: pair: exception; ValueError
 
 A right shift by *n* bits is defined as floor division by ``pow(2,n)``.  A left
 shift by *n* bits is defined as multiplication with ``pow(2,n)``.
@@ -1399,7 +1399,7 @@ Each of the three bitwise operations has
 
 .. index::
    pair: bitwise; and
-   operator: & (ampersand)
+   pair: operator; & (ampersand)
 
 The ``&`` operator yields the bitwise AND of its arguments, which must be
 integers or one of them must be a custom object overriding :meth:`__and__` or
@@ -1408,7 +1408,7 @@ integers or one of them must be a custom
 .. index::
    pair: bitwise; xor
    pair: exclusive; or
-   operator: ^ (caret)
+   pair: operator; ^ (caret)
 
 The ``^`` operator yields the bitwise XOR (exclusive OR) of its arguments, which
 must be integers or one of them must be a custom object overriding :meth:`__xor__` or
@@ -1417,7 +1417,7 @@ must be integers or one of them must be
 .. index::
    pair: bitwise; or
    pair: inclusive; or
-   operator: | (vertical bar)
+   pair: operator; | (vertical bar)
 
 The ``|`` operator yields the bitwise (inclusive) OR of its arguments, which
 must be integers or one of them must be a custom object overriding :meth:`__or__` or
@@ -1432,12 +1432,12 @@ Comparisons
 .. index::
    single: comparison
    pair: C; language
-   operator: < (less)
-   operator: > (greater)
-   operator: <=
-   operator: >=
-   operator: ==
-   operator: !=
+   pair: operator; < (less)
+   pair: operator; > (greater)
+   pair: operator; <=
+   pair: operator; >=
+   pair: operator; ==
+   pair: operator; !=
 
 Unlike C, all comparison operations in Python have the same priority, which is
 lower than that of any arithmetic, shifting or bitwise operation.  Also unlike
@@ -1669,17 +1669,17 @@ raises the :exc:`IndexError` exception.
 if :keyword:`in` raised that exception).
 
 .. index::
-   operator: in
-   operator: not in
+   pair: operator; in
+   pair: operator; not in
    pair: membership; test
-   object: sequence
+   pair: object; sequence
 
 The operator :keyword:`not in` is defined to have the inverse truth value of
 :keyword:`in`.
 
 .. index::
-   operator: is
-   operator: is not
+   pair: operator; is
+   pair: operator; is not
    pair: identity; test
 
 
@@ -1719,17 +1719,17 @@ control flow statements, the following v
 other values are interpreted as true.  User-defined objects can customize their
 truth value by providing a :meth:`__bool__` method.
 
-.. index:: operator: not
+.. index:: pair: operator; not
 
 The operator :keyword:`not` yields ``True`` if its argument is false, ``False``
 otherwise.
 
-.. index:: operator: and
+.. index:: pair: operator; and
 
 The expression ``x and y`` first evaluates *x*; if *x* is false, its value is
 returned; otherwise, *y* is evaluated and the resulting value is returned.
 
-.. index:: operator: or
+.. index:: pair: operator; or
 
 The expression ``x or y`` first evaluates *x*; if *x* is true, its value is
 returned; otherwise, *y* is evaluated and the resulting value is returned.
@@ -1854,7 +1854,7 @@ Expression lists
    starred_expression: `expression` | (`starred_item` ",")* [`starred_item`]
    starred_item: `assignment_expression` | "*" `or_expr`
 
-.. index:: object: tuple
+.. index:: pair: object; tuple
 
 Except when part of a list or set display, an expression list
 containing at least one comma yields a tuple.  The length of
diff -pruN 3.12.0~a7-1/Doc/reference/import.rst 3.12.0~b1-1/Doc/reference/import.rst
--- 3.12.0~a7-1/Doc/reference/import.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/reference/import.rst	2023-05-22 12:07:36.000000000 +0000
@@ -324,15 +324,18 @@ modules, and one that knows how to impor
 
 .. versionchanged:: 3.4
    The :meth:`~importlib.abc.MetaPathFinder.find_spec` method of meta path
-   finders replaced :meth:`~importlib.abc.MetaPathFinder.find_module`, which
+   finders replaced :meth:`!find_module`, which
    is now deprecated.  While it will continue to work without change, the
    import machinery will try it only if the finder does not implement
    ``find_spec()``.
 
 .. versionchanged:: 3.10
-   Use of :meth:`~importlib.abc.MetaPathFinder.find_module` by the import system
+   Use of :meth:`!find_module` by the import system
    now raises :exc:`ImportWarning`.
 
+.. versionchanged:: 3.12
+   ``find_module()`` has been removed.  Use :meth:`find_spec` instead.
+
 
 Loading
 =======
@@ -703,7 +706,7 @@ Here are the exact rules used:
  * Otherwise, just use the module's ``__name__`` in the repr.
 
 .. versionchanged:: 3.12
-   Use of :meth:`module_repr`, having been deprecated since Python 3.4, was
+   Use of :meth:`!module_repr`, having been deprecated since Python 3.4, was
    removed in Python 3.12 and is no longer called during the resolution of a
    module's repr.
 
@@ -837,7 +840,7 @@ stores finder objects rather than being
 In this way, the expensive search for a particular :term:`path entry`
 location's :term:`path entry finder` need only be done once.  User code is
 free to remove cache entries from :data:`sys.path_importer_cache` forcing
-the path based finder to perform the path entry search again [#fnpic]_.
+the path based finder to perform the path entry search again.
 
 If the path entry is not present in the cache, the path based finder iterates
 over every callable in :data:`sys.path_hooks`.  Each of the :term:`path entry
@@ -887,13 +890,13 @@ module.  ``find_spec()`` returns a fully
 This spec will always have "loader" set (with one exception).
 
 To indicate to the import machinery that the spec represents a namespace
-:term:`portion`, the path entry finder sets "submodule_search_locations" to
+:term:`portion`, the path entry finder sets ``submodule_search_locations`` to
 a list containing the portion.
 
 .. versionchanged:: 3.4
    :meth:`~importlib.abc.PathEntryFinder.find_spec` replaced
-   :meth:`~importlib.abc.PathEntryFinder.find_loader` and
-   :meth:`~importlib.abc.PathEntryFinder.find_module`, both of which
+   :meth:`!find_loader` and
+   :meth:`!find_module`, both of which
    are now deprecated, but will be used if ``find_spec()`` is not defined.
 
    Older path entry finders may implement one of these two deprecated methods
@@ -901,7 +904,7 @@ a list containing the portion.
    sake of backward compatibility.  However, if ``find_spec()`` is
    implemented on the path entry finder, the legacy methods are ignored.
 
-   :meth:`~importlib.abc.PathEntryFinder.find_loader` takes one argument, the
+   :meth:`!find_loader` takes one argument, the
    fully qualified name of the module being imported.  ``find_loader()``
    returns a 2-tuple where the first item is the loader and the second item
    is a namespace :term:`portion`.
@@ -920,10 +923,13 @@ a list containing the portion.
    ``find_loader()`` in preference to ``find_module()``.
 
 .. versionchanged:: 3.10
-    Calls to :meth:`~importlib.abc.PathEntryFinder.find_module` and
-    :meth:`~importlib.abc.PathEntryFinder.find_loader` by the import
+    Calls to :meth:`!find_module` and
+    :meth:`!find_loader` by the import
     system will raise :exc:`ImportWarning`.
 
+.. versionchanged:: 3.12
+    ``find_module()`` and ``find_loader()`` have been removed.
+
 
 Replacing the standard import system
 ====================================
@@ -1045,8 +1051,8 @@ The original specification for :data:`sy
 subsequent extension in :pep:`420`.
 
 :pep:`420` introduced :term:`namespace packages <namespace package>` for
-Python 3.3.  :pep:`420` also introduced the :meth:`find_loader` protocol as an
-alternative to :meth:`find_module`.
+Python 3.3.  :pep:`420` also introduced the :meth:`!find_loader` protocol as an
+alternative to :meth:`!find_module`.
 
 :pep:`366` describes the addition of the ``__package__`` attribute for
 explicit relative imports in main modules.
@@ -1073,8 +1079,3 @@ methods to finders and loaders.
    module may replace itself in :data:`sys.modules`.  This is
    implementation-specific behavior that is not guaranteed to work in other
    Python implementations.
-
-.. [#fnpic] In legacy code, it is possible to find instances of
-   :class:`imp.NullImporter` in the :data:`sys.path_importer_cache`.  It
-   is recommended that code be changed to use ``None`` instead.  See
-   :ref:`portingpythoncode` for more details.
diff -pruN 3.12.0~a7-1/Doc/reference/introduction.rst 3.12.0~b1-1/Doc/reference/introduction.rst
--- 3.12.0~a7-1/Doc/reference/introduction.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/reference/introduction.rst	2023-05-22 12:07:36.000000000 +0000
@@ -74,7 +74,7 @@ PyPy
    and a Just in Time compiler. One of the goals of the project is to encourage
    experimentation with the language itself by making it easier to modify the
    interpreter (since it is written in Python).  Additional information is
-   available on `the PyPy project's home page <https://pypy.org/>`_.
+   available on `the PyPy project's home page <https://www.pypy.org/>`_.
 
 Each of these implementations varies in some way from the language as documented
 in this manual, or introduces specific information beyond what's covered in the
diff -pruN 3.12.0~a7-1/Doc/reference/simple_stmts.rst 3.12.0~b1-1/Doc/reference/simple_stmts.rst
--- 3.12.0~a7-1/Doc/reference/simple_stmts.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/reference/simple_stmts.rst	2023-05-22 12:07:36.000000000 +0000
@@ -53,8 +53,8 @@ An expression statement evaluates the ex
 expression).
 
 .. index::
-   builtin: repr
-   object: None
+   pair: built-in function; repr
+   pair: object; None
    pair: string; conversion
    single: output
    pair: standard; output
@@ -76,7 +76,7 @@ Assignment statements
    pair: assignment; statement
    pair: binding; name
    pair: rebinding; name
-   object: mutable
+   pair: object; mutable
    pair: attribute; assignment
 
 Assignment statements are used to (re)bind names to values and to modify
@@ -185,7 +185,7 @@ Assignment of an object to a single targ
 
   .. index::
      pair: subscription; assignment
-     object: mutable
+     pair: object; mutable
 
 * If the target is a subscription: The primary expression in the reference is
   evaluated.  It should yield either a mutable sequence object (such as a list)
@@ -193,8 +193,8 @@ Assignment of an object to a single targ
   evaluated.
 
   .. index::
-     object: sequence
-     object: list
+     pair: object; sequence
+     pair: object; list
 
   If the primary is a mutable sequence object (such as a list), the subscript
   must yield an integer.  If it is negative, the sequence's length is added to
@@ -204,8 +204,8 @@ Assignment of an object to a single targ
   raised (assignment to a subscripted sequence cannot add new items to a list).
 
   .. index::
-     object: mapping
-     object: dictionary
+     pair: object; mapping
+     pair: object; dictionary
 
   If the primary is a mapping object (such as a dictionary), the subscript must
   have a type compatible with the mapping's key type, and the mapping is then
@@ -376,7 +376,7 @@ The :keyword:`!assert` statement
 ================================
 
 .. index::
-   ! statement: assert
+   ! pair: statement; assert
    pair: debugging; assertions
    single: , (comma); expression list
 
@@ -398,7 +398,7 @@ The extended form, ``assert expression1,
 
 .. index::
    single: __debug__
-   exception: AssertionError
+   pair: exception; AssertionError
 
 These equivalences assume that :const:`__debug__` and :exc:`AssertionError` refer to
 the built-in variables with those names.  In the current implementation, the
@@ -419,7 +419,7 @@ The :keyword:`!pass` statement
 ==============================
 
 .. index::
-   statement: pass
+   pair: statement; pass
    pair: null; operation
            pair: null; operation
 
@@ -441,7 +441,7 @@ The :keyword:`!del` statement
 =============================
 
 .. index::
-   ! statement: del
+   ! pair: statement; del
    pair: deletion; target
    triple: deletion; target; list
 
@@ -454,7 +454,7 @@ Rather than spelling it out in full deta
 Deletion of a target list recursively deletes each target, from left to right.
 
 .. index::
-   statement: global
+   pair: statement; global
    pair: unbinding; name
 
 Deletion of a name removes the binding of that name from the local or global
@@ -480,7 +480,7 @@ The :keyword:`!return` statement
 ================================
 
 .. index::
-   ! statement: return
+   ! pair: statement; return
    pair: function; definition
    pair: class; definition
 
@@ -495,7 +495,7 @@ If an expression list is present, it is
 :keyword:`return` leaves the current function call with the expression list (or
 ``None``) as return value.
 
-.. index:: keyword: finally
+.. index:: pair: keyword; finally
 
 When :keyword:`return` passes control out of a :keyword:`try` statement with a
 :keyword:`finally` clause, that :keyword:`!finally` clause is executed before
@@ -517,11 +517,11 @@ The :keyword:`!yield` statement
 ===============================
 
 .. index::
-   statement: yield
+   pair: statement; yield
    single: generator; function
    single: generator; iterator
    single: function; generator
-   exception: StopIteration
+   pair: exception; StopIteration
 
 .. productionlist:: python-grammar
    yield_stmt: `yield_expression`
@@ -553,7 +553,7 @@ The :keyword:`!raise` statement
 ===============================
 
 .. index::
-   ! statement: raise
+   ! pair: statement; raise
    single: exception
    pair: raising; exception
    single: __traceback__ (exception attribute)
@@ -574,7 +574,7 @@ instantiating the class with no argument
 The :dfn:`type` of the exception is the exception instance's class, the
 :dfn:`value` is the instance itself.
 
-.. index:: object: traceback
+.. index:: pair: object; traceback
 
 A traceback object is normally created automatically when an exception is raised
 and attached to it as the :attr:`__traceback__` attribute, which is writable.
@@ -667,9 +667,9 @@ The :keyword:`!break` statement
 ===============================
 
 .. index::
-   ! statement: break
-   statement: for
-   statement: while
+   ! pair: statement; break
+   pair: statement; for
+   pair: statement; while
    pair: loop; statement
 
 .. productionlist:: python-grammar
@@ -679,7 +679,7 @@ The :keyword:`!break` statement
 :keyword:`while` loop, but not nested in a function or class definition within
 that loop.
 
-.. index:: keyword: else
+.. index:: pair: keyword; else
            pair: loop control; target
 
 It terminates the nearest enclosing loop, skipping the optional :keyword:`!else`
@@ -688,7 +688,7 @@ clause if the loop has one.
 If a :keyword:`for` loop is terminated by :keyword:`break`, the loop control
 target keeps its current value.
 
-.. index:: keyword: finally
+.. index:: pair: keyword; finally
 
 When :keyword:`break` passes control out of a :keyword:`try` statement with a
 :keyword:`finally` clause, that :keyword:`!finally` clause is executed before
@@ -701,11 +701,11 @@ The :keyword:`!continue` statement
 ==================================
 
 .. index::
-   ! statement: continue
-   statement: for
-   statement: while
+   ! pair: statement; continue
+   pair: statement; for
+   pair: statement; while
    pair: loop; statement
-   keyword: finally
+   pair: keyword; finally
 
 .. productionlist:: python-grammar
    continue_stmt: "continue"
@@ -726,12 +726,12 @@ The :keyword:`!import` statement
 ================================
 
 .. index::
-   ! statement: import
+   ! pair: statement; import
    single: module; importing
    pair: name; binding
-   keyword: from
-   keyword: as
-   exception: ImportError
+   pair: keyword; from
+   pair: keyword; as
+   pair: exception; ImportError
    single: , (comma); import statement
 
 .. productionlist:: python-grammar
@@ -942,7 +942,7 @@ The :keyword:`!global` statement
 ================================
 
 .. index::
-   ! statement: global
+   ! pair: statement; global
    triple: global; name; binding
    single: , (comma); identifier list
 
@@ -970,9 +970,9 @@ annotation.
    them or silently change the meaning of the program.
 
 .. index::
-   builtin: exec
-   builtin: eval
-   builtin: compile
+   pair: built-in function; exec
+   pair: built-in function; eval
+   pair: built-in function; compile
 
 **Programmer's note:** :keyword:`global` is a directive to the parser.  It
 applies only to code parsed at the same time as the :keyword:`!global` statement.
@@ -988,7 +988,7 @@ call.  The same applies to the :func:`ev
 The :keyword:`!nonlocal` statement
 ==================================
 
-.. index:: statement: nonlocal
+.. index:: pair: statement; nonlocal
    single: , (comma); identifier list
 
 .. productionlist:: python-grammar
diff -pruN 3.12.0~a7-1/Doc/reference/toplevel_components.rst 3.12.0~b1-1/Doc/reference/toplevel_components.rst
--- 3.12.0~a7-1/Doc/reference/toplevel_components.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/reference/toplevel_components.rst	2023-05-22 12:07:36.000000000 +0000
@@ -21,9 +21,9 @@ Complete Python programs
 .. index:: single: program
 
 .. index::
-   module: sys
-   module: __main__
-   module: builtins
+   pair: module; sys
+   pair: module; __main__
+   pair: module; builtins
 
 While a language specification need not prescribe how the language interpreter
 is invoked, it is useful to have a notion of a complete Python program.  A
@@ -38,7 +38,7 @@ the next section.
 
 .. index::
    single: interactive mode
-   module: __main__
+   pair: module; __main__
 
 The interpreter may also be invoked in interactive mode; in this case, it does
 not read and execute a complete program but reads and executes one statement
@@ -98,7 +98,7 @@ Expression input
 ================
 
 .. index:: single: input
-.. index:: builtin: eval
+.. index:: pair: built-in function; eval
 
 :func:`eval` is used for expression input.  It ignores leading whitespace. The
 string argument to :func:`eval` must have the following form:
diff -pruN 3.12.0~a7-1/Doc/requirements-oldest-sphinx.txt 3.12.0~b1-1/Doc/requirements-oldest-sphinx.txt
--- 3.12.0~a7-1/Doc/requirements-oldest-sphinx.txt	1970-01-01 00:00:00.000000000 +0000
+++ 3.12.0~b1-1/Doc/requirements-oldest-sphinx.txt	2023-05-22 12:07:36.000000000 +0000
@@ -0,0 +1,38 @@
+# Requirements to build the Python documentation, for the oldest supported
+# Sphinx version.
+#
+# We pin Sphinx and all of its dependencies to ensure a consistent environment.
+
+blurb
+python-docs-theme>=2022.1
+
+# Generated from:
+#     pip install "Sphinx~=3.2.0" "docutils<0.17" "Jinja2<3" "MarkupSafe<2"
+#     pip freeze
+#
+# Sphinx 3.2 comes from ``needs_sphinx = '3.2'`` in ``Doc/conf.py``.
+# Docutils<0.17, Jinja2<3, and MarkupSafe<2 are additionally specified as
+# Sphinx 3.2 is incompatible with newer releases of these packages.
+
+Sphinx==3.2.1
+alabaster==0.7.13
+Babel==2.12.1
+certifi==2022.12.7
+charset-normalizer==3.1.0
+colorama==0.4.6
+docutils==0.16
+idna==3.4
+imagesize==1.4.1
+Jinja2==2.11.3
+MarkupSafe==1.1.1
+packaging==23.1
+Pygments==2.15.1
+requests==2.29.0
+snowballstemmer==2.2.0
+sphinxcontrib-applehelp==1.0.4
+sphinxcontrib-devhelp==1.0.2
+sphinxcontrib-htmlhelp==2.0.1
+sphinxcontrib-jsmath==1.0.1
+sphinxcontrib-qthelp==1.0.3
+sphinxcontrib-serializinghtml==1.1.5
+urllib3==1.26.15
diff -pruN 3.12.0~a7-1/Doc/requirements.txt 3.12.0~b1-1/Doc/requirements.txt
--- 3.12.0~a7-1/Doc/requirements.txt	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/requirements.txt	2023-05-22 12:07:36.000000000 +0000
@@ -1,4 +1,7 @@
 # Requirements to build the Python documentation
+#
+# Note that when updating this file, you will likely also have to update
+# the Doc/constraints.txt file.
 
 # Sphinx version is pinned so that new versions that introduce new warnings
 # won't suddenly cause build failures. Updating the version is fine as long
@@ -13,3 +16,5 @@ sphinxext-opengraph==0.7.5
 # The theme used by the documentation is stored separately, so we need
 # to install that as well.
 python-docs-theme>=2022.1
+
+-c constraints.txt
diff -pruN 3.12.0~a7-1/Doc/tools/.nitignore 3.12.0~b1-1/Doc/tools/.nitignore
--- 3.12.0~a7-1/Doc/tools/.nitignore	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/tools/.nitignore	2023-05-22 12:07:36.000000000 +0000
@@ -59,7 +59,6 @@ Doc/faq/gui.rst
 Doc/faq/library.rst
 Doc/faq/programming.rst
 Doc/glossary.rst
-Doc/howto/argparse.rst
 Doc/howto/curses.rst
 Doc/howto/descriptor.rst
 Doc/howto/enum.rst
@@ -78,7 +77,6 @@ Doc/library/__future__.rst
 Doc/library/_thread.rst
 Doc/library/abc.rst
 Doc/library/aifc.rst
-Doc/library/argparse.rst
 Doc/library/ast.rst
 Doc/library/asyncio-dev.rst
 Doc/library/asyncio-eventloop.rst
@@ -113,7 +111,6 @@ Doc/library/csv.rst
 Doc/library/ctypes.rst
 Doc/library/curses.ascii.rst
 Doc/library/curses.rst
-Doc/library/dataclasses.rst
 Doc/library/datetime.rst
 Doc/library/dbm.rst
 Doc/library/decimal.rst
@@ -152,7 +149,6 @@ Doc/library/http.cookiejar.rst
 Doc/library/http.cookies.rst
 Doc/library/http.server.rst
 Doc/library/idle.rst
-Doc/library/imp.rst
 Doc/library/importlib.resources.abc.rst
 Doc/library/importlib.resources.rst
 Doc/library/importlib.rst
@@ -180,7 +176,6 @@ Doc/library/os.rst
 Doc/library/ossaudiodev.rst
 Doc/library/pickle.rst
 Doc/library/pickletools.rst
-Doc/library/pkgutil.rst
 Doc/library/platform.rst
 Doc/library/plistlib.rst
 Doc/library/poplib.rst
diff -pruN 3.12.0~a7-1/Doc/tools/extensions/c_annotations.py 3.12.0~b1-1/Doc/tools/extensions/c_annotations.py
--- 3.12.0~a7-1/Doc/tools/extensions/c_annotations.py	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/tools/extensions/c_annotations.py	2023-05-22 12:07:36.000000000 +0000
@@ -20,6 +20,7 @@
 """
 
 from os import path
+import docutils
 from docutils import nodes
 from docutils.parsers.rst import directives
 from docutils.parsers.rst import Directive
@@ -41,6 +42,16 @@ REST_ROLE_MAP = {
 }
 
 
+# Monkeypatch nodes.Node.findall for forwards compatability
+# This patch can be dropped when the minimum Sphinx version is 4.4.0
+# or the minimum Docutils version is 0.18.1.
+if docutils.__version_info__ < (0, 18, 1):
+    def findall(self, *args, **kwargs):
+        return iter(self.traverse(*args, **kwargs))
+
+    nodes.Node.findall = findall
+
+
 class RCEntry:
     def __init__(self, name):
         self.name = name
@@ -87,7 +98,7 @@ class Annotations:
                 self.stable_abi_data[name] = record
 
     def add_annotations(self, app, doctree):
-        for node in doctree.traverse(addnodes.desc_content):
+        for node in doctree.findall(addnodes.desc_content):
             par = node.parent
             if par['domain'] != 'c':
                 continue
diff -pruN 3.12.0~a7-1/Doc/tools/extensions/pyspecific.py 3.12.0~b1-1/Doc/tools/extensions/pyspecific.py
--- 3.12.0~a7-1/Doc/tools/extensions/pyspecific.py	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/tools/extensions/pyspecific.py	2023-05-22 12:07:36.000000000 +0000
@@ -41,7 +41,7 @@ except ImportError:
 
 ISSUE_URI = 'https://bugs.python.org/issue?@action=redirect&bpo=%s'
 GH_ISSUE_URI = 'https://github.com/python/cpython/issues/%s'
-SOURCE_URI = 'https://github.com/python/cpython/tree/main/%s'
+SOURCE_URI = 'https://github.com/python/cpython/tree/3.12/%s'
 
 # monkey-patch reST parser to disable alphabetic and roman enumerated lists
 from docutils.parsers.rst.states import Body
@@ -674,6 +674,30 @@ def process_audit_events(app, doctree, f
         node.replace_self(table)
 
 
+def patch_pairindextypes(app, _env) -> None:
+    """Remove all entries from ``pairindextypes`` before writing POT files.
+
+    We want to run this just before writing output files, as the check to
+    circumvent is in ``I18nBuilder.write_doc()``.
+    As such, we link this to ``env-check-consistency``, even though it has
+    nothing to do with the environment consistency check.
+    """
+    if app.builder.name != 'gettext':
+        return
+
+    # allow translating deprecated index entries
+    try:
+        from sphinx.domains.python import pairindextypes
+    except ImportError:
+        pass
+    else:
+        # Sphinx checks if a 'pair' type entry on an index directive is one of
+        # the Sphinx-translated pairindextypes values. As we intend to move
+        # away from this, we need Sphinx to believe that these values don't
+        # exist, by deleting them when using the gettext builder.
+        pairindextypes.clear()
+
+
 def setup(app):
     app.add_role('issue', issue_role)
     app.add_role('gh', gh_issue_role)
@@ -695,6 +719,7 @@ def setup(app):
     app.add_directive_to_domain('py', 'awaitablemethod', PyAwaitableMethod)
     app.add_directive_to_domain('py', 'abstractmethod', PyAbstractMethod)
     app.add_directive('miscnews', MiscNews)
+    app.connect('env-check-consistency', patch_pairindextypes)
     app.connect('doctree-resolved', process_audit_events)
     app.connect('env-merge-info', audit_events_merge)
     app.connect('env-purge-doc', audit_events_purge)
diff -pruN 3.12.0~a7-1/Doc/tools/templates/layout.html 3.12.0~b1-1/Doc/tools/templates/layout.html
--- 3.12.0~a7-1/Doc/tools/templates/layout.html	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/tools/templates/layout.html	2023-05-22 12:07:36.000000000 +0000
@@ -11,11 +11,6 @@
 
 {%- if is_deployment_preview %}
 <div id="deployment-preview-warning" style="padding: .5em; text-align: center; background-color: #fff2ba; color: #6a580e;">
-  <div style="float: right; margin-top: -10px; margin-left: 10px;">
-    <a href="https://www.netlify.com">
-      <img src="https://www.netlify.com/img/global/badges/netlify-color-accent.svg" alt="Deploys by Netlify" />
-    </a>
-  </div>
   {% trans %}This is a deploy preview created from a <a href="{{ repository_url }}/pull/{{ pr_id }}">pull request</a>.
   For authoritative documentation, see the {% endtrans %}
   <a href="https://docs.python.org/3/{{ pagename }}{{ file_suffix }}">{% trans %} the current stable release{% endtrans %}</a>.
diff -pruN 3.12.0~a7-1/Doc/tutorial/classes.rst 3.12.0~b1-1/Doc/tutorial/classes.rst
--- 3.12.0~a7-1/Doc/tutorial/classes.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/tutorial/classes.rst	2023-05-22 12:07:36.000000000 +0000
@@ -344,7 +344,7 @@ list objects have methods called append,
 However, in the following discussion, we'll use the term method exclusively to
 mean methods of class instance objects, unless explicitly stated otherwise.)
 
-.. index:: object: method
+.. index:: pair: object; method
 
 Valid method names of an instance object depend on its class.  By definition,
 all attributes of a class that are function  objects define corresponding
diff -pruN 3.12.0~a7-1/Doc/tutorial/controlflow.rst 3.12.0~b1-1/Doc/tutorial/controlflow.rst
--- 3.12.0~a7-1/Doc/tutorial/controlflow.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/tutorial/controlflow.rst	2023-05-22 12:07:36.000000000 +0000
@@ -46,7 +46,7 @@ details see :ref:`tut-match`.
 ==========================
 
 .. index::
-   statement: for
+   pair: statement; for
 
 The :keyword:`for` statement in Python differs a bit from what you may be used
 to in C or Pascal.  Rather than always iterating over an arithmetic progression
diff -pruN 3.12.0~a7-1/Doc/tutorial/inputoutput.rst 3.12.0~b1-1/Doc/tutorial/inputoutput.rst
--- 3.12.0~a7-1/Doc/tutorial/inputoutput.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/tutorial/inputoutput.rst	2023-05-22 12:07:36.000000000 +0000
@@ -285,8 +285,8 @@ Reading and Writing Files
 =========================
 
 .. index::
-   builtin: open
-   object: file
+   pair: built-in function; open
+   pair: object; file
 
 :func:`open` returns a :term:`file object`, and is most commonly used with
 two positional arguments and one keyword argument:
@@ -466,7 +466,7 @@ Reference for a complete guide to file o
 Saving structured data with :mod:`json`
 ---------------------------------------
 
-.. index:: module: json
+.. index:: pair: module; json
 
 Strings can easily be written to and read from a file.  Numbers take a bit more
 effort, since the :meth:`read` method only returns strings, which will have to
diff -pruN 3.12.0~a7-1/Doc/tutorial/modules.rst 3.12.0~b1-1/Doc/tutorial/modules.rst
--- 3.12.0~a7-1/Doc/tutorial/modules.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/tutorial/modules.rst	2023-05-22 12:07:36.000000000 +0000
@@ -264,7 +264,7 @@ Some tips for experts:
 Standard Modules
 ================
 
-.. index:: module: sys
+.. index:: pair: module; sys
 
 Python comes with a library of standard modules, described in a separate
 document, the Python Library Reference ("Library Reference" hereafter).  Some
@@ -345,7 +345,7 @@ Without arguments, :func:`dir` lists the
 
 Note that it lists all types of names: variables, modules, functions, etc.
 
-.. index:: module: builtins
+.. index:: pair: module; builtins
 
 :func:`dir` does not list the names of built-in functions and variables.  If you
 want a list of those, they are defined in the standard module
diff -pruN 3.12.0~a7-1/Doc/tutorial/stdlib.rst 3.12.0~b1-1/Doc/tutorial/stdlib.rst
--- 3.12.0~a7-1/Doc/tutorial/stdlib.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/tutorial/stdlib.rst	2023-05-22 12:07:36.000000000 +0000
@@ -24,7 +24,7 @@ Be sure to use the ``import os`` style i
 will keep :func:`os.open` from shadowing the built-in :func:`open` function which
 operates much differently.
 
-.. index:: builtin: help
+.. index:: pair: built-in function; help
 
 The built-in :func:`dir` and :func:`help` functions are useful as interactive
 aids for working with large modules like :mod:`os`::
diff -pruN 3.12.0~a7-1/Doc/using/cmdline.rst 3.12.0~b1-1/Doc/using/cmdline.rst
--- 3.12.0~a7-1/Doc/using/cmdline.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/using/cmdline.rst	2023-05-22 12:07:36.000000000 +0000
@@ -370,7 +370,7 @@ Miscellaneous options
    Hash randomization is intended to provide protection against a
    denial-of-service caused by carefully chosen inputs that exploit the worst
    case performance of a dict construction, O(n\ :sup:`2`) complexity.  See
-   http://www.ocert.org/advisories/ocert-2011-003.html for details.
+   http://ocert.org/advisories/ocert-2011-003.html for details.
 
    :envvar:`PYTHONHASHSEED` allows you to set a fixed value for the hash
    seed secret.
@@ -495,7 +495,8 @@ Miscellaneous options
    Reserved for various implementation-specific options.  CPython currently
    defines the following possible values:
 
-   * ``-X faulthandler`` to enable :mod:`faulthandler`;
+   * ``-X faulthandler`` to enable :mod:`faulthandler`.
+     See also :envvar:`PYTHONFAULTHANDLER`.
    * ``-X showrefcount`` to output the total reference count and number of used
      memory blocks when the program finishes or after each statement in the
      interactive interpreter. This only works on :ref:`debug builds
@@ -503,8 +504,9 @@ Miscellaneous options
    * ``-X tracemalloc`` to start tracing Python memory allocations using the
      :mod:`tracemalloc` module. By default, only the most recent frame is
      stored in a traceback of a trace. Use ``-X tracemalloc=NFRAME`` to start
-     tracing with a traceback limit of *NFRAME* frames. See the
-     :func:`tracemalloc.start` for more information.
+     tracing with a traceback limit of *NFRAME* frames.
+     See :func:`tracemalloc.start` and :envvar:`PYTHONTRACEMALLOC`
+     for more information.
    * ``-X int_max_str_digits`` configures the :ref:`integer string conversion
      length limitation <int_max_str_digits>`.  See also
      :envvar:`PYTHONINTMAXSTRDIGITS`.
@@ -519,6 +521,7 @@ Miscellaneous options
    * ``-X utf8`` enables the :ref:`Python UTF-8 Mode <utf8-mode>`.
      ``-X utf8=0`` explicitly disables :ref:`Python UTF-8 Mode <utf8-mode>`
      (even when it would otherwise activate automatically).
+     See also :envvar:`PYTHONUTF8`.
    * ``-X pycache_prefix=PATH`` enables writing ``.pyc`` files to a parallel
      tree rooted at the given directory instead of to the code tree. See also
      :envvar:`PYTHONPYCACHEPREFIX`.
@@ -861,7 +864,9 @@ conflict.
    Python memory allocations using the :mod:`tracemalloc` module. The value of
    the variable is the maximum number of frames stored in a traceback of a
    trace. For example, ``PYTHONTRACEMALLOC=1`` stores only the most recent
-   frame. See the :func:`tracemalloc.start` for more information.
+   frame.
+   See the :func:`tracemalloc.start` function for more information.
+   This is equivalent to setting the :option:`-X` ``tracemalloc`` option.
 
    .. versionadded:: 3.4
 
@@ -869,8 +874,8 @@ conflict.
 .. envvar:: PYTHONPROFILEIMPORTTIME
 
    If this environment variable is set to a non-empty string, Python will
-   show how long each import takes.  This is exactly equivalent to setting
-   ``-X importtime`` on the command line.
+   show how long each import takes.
+   This is equivalent to setting the :option:`-X` ``importtime`` option.
 
    .. versionadded:: 3.7
 
@@ -1012,6 +1017,7 @@ conflict.
    If this environment variable is set to a non-empty string, enable
    :ref:`Python Development Mode <devmode>`, introducing additional runtime
    checks that are too expensive to be enabled by default.
+   This is equivalent to setting the :option:`-X` ``dev`` option.
 
    .. versionadded:: 3.7
 
diff -pruN 3.12.0~a7-1/Doc/using/configure.rst 3.12.0~b1-1/Doc/using/configure.rst
--- 3.12.0~a7-1/Doc/using/configure.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/using/configure.rst	2023-05-22 12:07:36.000000000 +0000
@@ -314,6 +314,13 @@ also be used to improve performance.
    is dependent on a combination of the build environment + the other
    optimization configure args + the CPU architecture, and not all combinations
    are supported.
+   BOLT versions before LLVM 16 are known to crash BOLT under some scenarios.
+   Use of LLVM 16 or newer for BOLT optimization is strongly encouraged.
+
+   The :envvar:`!BOLT_INSTRUMENT_FLAGS` and :envvar:`!BOLT_APPLY_FLAGS`
+   :program:`configure` variables can be defined to override the default set of
+   arguments for :program:`llvm-bolt` to instrument and apply BOLT data to
+   binaries, respectively.
 
    .. versionadded:: 3.12
 
diff -pruN 3.12.0~a7-1/Doc/using/mac.rst 3.12.0~b1-1/Doc/using/mac.rst
--- 3.12.0~a7-1/Doc/using/mac.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/using/mac.rst	2023-05-22 12:07:36.000000000 +0000
@@ -66,7 +66,7 @@ number of standard Unix command line edi
 :program:`BBEdit` or :program:`TextWrangler` from Bare Bones Software (see
 http://www.barebones.com/products/bbedit/index.html) are good choices, as is
 :program:`TextMate` (see https://macromates.com/). Other editors include
-:program:`Gvim` (https://macvim-dev.github.io/macvim/) and :program:`Aquamacs`
+:program:`Gvim` (https://macvim.org/macvim/) and :program:`Aquamacs`
 (http://aquamacs.org/).
 
 To run your script from the Terminal window you must make sure that
@@ -144,8 +144,8 @@ the foundation of most modern Mac develo
 available from https://pypi.org/project/pyobjc/.
 
 The standard Python GUI toolkit is :mod:`tkinter`, based on the cross-platform
-Tk toolkit (https://www.tcl.tk). An Aqua-native version of Tk is bundled with OS
-X by Apple, and the latest version can be downloaded and installed from
+Tk toolkit (https://www.tcl.tk). An Aqua-native version of Tk is bundled with
+macOS by Apple, and the latest version can be downloaded and installed from
 https://www.activestate.com; it can also be built from source.
 
 *wxPython* is another popular cross-platform GUI toolkit that runs natively on
diff -pruN 3.12.0~a7-1/Doc/using/unix.rst 3.12.0~b1-1/Doc/using/unix.rst
--- 3.12.0~a7-1/Doc/using/unix.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/using/unix.rst	2023-05-22 12:07:36.000000000 +0000
@@ -54,13 +54,6 @@ On FreeBSD and OpenBSD
      pkg_add ftp://ftp.openbsd.org/pub/OpenBSD/4.2/packages/i386/python-2.5.1p2.tgz
 
 
-On OpenSolaris
---------------
-
-You can get Python from `OpenCSW <https://www.opencsw.org/>`_.  Various versions
-of Python are available and can be installed with e.g. ``pkgutil -i python27``.
-
-
 .. _building-python-on-unix:
 
 Building Python
diff -pruN 3.12.0~a7-1/Doc/using/venv-create.inc 3.12.0~b1-1/Doc/using/venv-create.inc
--- 3.12.0~a7-1/Doc/using/venv-create.inc	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/using/venv-create.inc	2023-05-22 12:07:36.000000000 +0000
@@ -61,12 +61,16 @@ The command, if run with ``-h``, will sh
                             environment (pip is bootstrapped by default)
       --prompt PROMPT       Provides an alternative prompt prefix for this
                             environment.
-      --upgrade-deps        Upgrade core dependencies: pip setuptools to the
+      --upgrade-deps        Upgrade core dependencies (pip) to the
                             latest version in PyPI
 
     Once an environment has been created, you may wish to activate it, e.g. by
     sourcing an activate script in its bin directory.
 
+.. versionchanged:: 3.12
+
+   ``setuptools`` is no longer a core venv dependency.
+
 .. versionchanged:: 3.9
    Add ``--upgrade-deps`` option to upgrade pip + setuptools to the latest on PyPI
 
@@ -104,4 +108,3 @@ invoked to bootstrap ``pip`` into the vi
 Multiple paths can be given to ``venv``, in which case an identical virtual
 environment will be created, according to the given options, at each provided
 path.
-
diff -pruN 3.12.0~a7-1/Doc/using/windows.rst 3.12.0~b1-1/Doc/using/windows.rst
--- 3.12.0~a7-1/Doc/using/windows.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/using/windows.rst	2023-05-22 12:07:36.000000000 +0000
@@ -470,7 +470,7 @@ user's system, including environment var
 installed packages. The standard library is included as pre-compiled and
 optimized ``.pyc`` files in a ZIP, and ``python3.dll``, ``python37.dll``,
 ``python.exe`` and ``pythonw.exe`` are all provided. Tcl/tk (including all
-dependants, such as Idle), pip and the Python documentation are not included.
+dependents, such as Idle), pip and the Python documentation are not included.
 
 .. note::
 
@@ -541,7 +541,7 @@ Besides the standard CPython distributio
 additional functionality.  The following is a list of popular versions and their
 key features:
 
-`ActivePython <https://www.activestate.com/activepython/>`_
+`ActivePython <https://www.activestate.com/products/python/>`_
     Installer with multi-platform compatibility, documentation, PyWin32
 
 `Anaconda <https://www.anaconda.com/download/>`_
diff -pruN 3.12.0~a7-1/Doc/whatsnew/2.0.rst 3.12.0~b1-1/Doc/whatsnew/2.0.rst
--- 3.12.0~a7-1/Doc/whatsnew/2.0.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/whatsnew/2.0.rst	2023-05-22 12:07:36.000000000 +0000
@@ -933,7 +933,7 @@ using it::
    parser.parse( 'hamlet.xml' )
 
 For more information, consult the Python documentation, or the XML HOWTO at
-http://pyxml.sourceforge.net/topics/howto/xml-howto.html.
+https://pyxml.sourceforge.net/topics/howto/xml-howto.html.
 
 
 DOM Support
diff -pruN 3.12.0~a7-1/Doc/whatsnew/2.1.rst 3.12.0~b1-1/Doc/whatsnew/2.1.rst
--- 3.12.0~a7-1/Doc/whatsnew/2.1.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/whatsnew/2.1.rst	2023-05-22 12:07:36.000000000 +0000
@@ -613,7 +613,7 @@ New and Improved Modules
   framework based on running embedded examples in docstrings and comparing the
   results against the expected output.  PyUnit, contributed by Steve Purcell, is a
   unit testing framework inspired by JUnit, which was in turn an adaptation of
-  Kent Beck's Smalltalk testing framework.  See http://pyunit.sourceforge.net/ for
+  Kent Beck's Smalltalk testing framework.  See https://pyunit.sourceforge.net/ for
   more information about PyUnit.
 
 * The :mod:`difflib` module contains a class, :class:`SequenceMatcher`, which
diff -pruN 3.12.0~a7-1/Doc/whatsnew/2.2.rst 3.12.0~b1-1/Doc/whatsnew/2.2.rst
--- 3.12.0~a7-1/Doc/whatsnew/2.2.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/whatsnew/2.2.rst	2023-05-22 12:07:36.000000000 +0000
@@ -632,10 +632,10 @@ queen threatens another) and the Knight'
 every square of an $NxN$ chessboard without visiting any square twice).
 
 The idea of generators comes from other programming languages, especially Icon
-(https://www.cs.arizona.edu/icon/), where the idea of generators is central.  In
+(https://www2.cs.arizona.edu/icon/), where the idea of generators is central.  In
 Icon, every expression and function call behaves like a generator.  One example
 from "An Overview of the Icon Programming Language" at
-https://www.cs.arizona.edu/icon/docs/ipd266.htm gives an idea of what this looks
+https://www2.cs.arizona.edu/icon/docs/ipd266.htm gives an idea of what this looks
 like::
 
    sentence := "Store it in the neighboring harbor"
diff -pruN 3.12.0~a7-1/Doc/whatsnew/2.3.rst 3.12.0~b1-1/Doc/whatsnew/2.3.rst
--- 3.12.0~a7-1/Doc/whatsnew/2.3.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/whatsnew/2.3.rst	2023-05-22 12:07:36.000000000 +0000
@@ -218,10 +218,10 @@ queen threatens another) and the Knight'
 every square of an $NxN$ chessboard without visiting any square twice).
 
 The idea of generators comes from other programming languages, especially Icon
-(https://www.cs.arizona.edu/icon/), where the idea of generators is central.  In
+(https://www2.cs.arizona.edu/icon/), where the idea of generators is central.  In
 Icon, every expression and function call behaves like a generator.  One example
 from "An Overview of the Icon Programming Language" at
-https://www.cs.arizona.edu/icon/docs/ipd266.htm gives an idea of what this looks
+https://www2.cs.arizona.edu/icon/docs/ipd266.htm gives an idea of what this looks
 like::
 
    sentence := "Store it in the neighboring harbor"
@@ -728,7 +728,7 @@ module:
 
 Importer objects must have a single method, ``find_module(fullname,
 path=None)``.  *fullname* will be a module or package name, e.g. ``string`` or
-``distutils.core``.  :meth:`find_module` must return a loader object that has a
+``distutils.core``.  :meth:`!find_module` must return a loader object that has a
 single method, ``load_module(fullname)``, that creates and returns the
 corresponding module object.
 
@@ -1332,7 +1332,7 @@ complete list of changes, or look throug
   (Contributed by Kevin O'Connor.)
 
 * The IDLE integrated development environment has been updated using the code
-  from the IDLEfork project (http://idlefork.sourceforge.net).  The most notable feature is
+  from the IDLEfork project (https://idlefork.sourceforge.net).  The most notable feature is
   that the code being developed is now executed in a subprocess, meaning that
   there's no longer any need for manual ``reload()`` operations. IDLE's core code
   has been incorporated into the standard library as the :mod:`idlelib` package.
diff -pruN 3.12.0~a7-1/Doc/whatsnew/2.4.rst 3.12.0~b1-1/Doc/whatsnew/2.4.rst
--- 3.12.0~a7-1/Doc/whatsnew/2.4.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/whatsnew/2.4.rst	2023-05-22 12:07:36.000000000 +0000
@@ -756,7 +756,7 @@ API that perform ASCII-only conversions,
   :c:expr:`double` to an ASCII string.
 
 The code for these functions came from the GLib library
-(https://developer.gnome.org/glib/stable/), whose developers kindly
+(https://developer-old.gnome.org/glib/2.26/), whose developers kindly
 relicensed the relevant functions and donated them to the Python Software
 Foundation.  The :mod:`locale` module  can now change the numeric locale,
 letting extensions such as GTK+  produce the correct results.
diff -pruN 3.12.0~a7-1/Doc/whatsnew/2.6.rst 3.12.0~b1-1/Doc/whatsnew/2.6.rst
--- 3.12.0~a7-1/Doc/whatsnew/2.6.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/whatsnew/2.6.rst	2023-05-22 12:07:36.000000000 +0000
@@ -172,7 +172,7 @@ this edition of "What's New in Python" l
 item for each change.
 
 Hosting of the Python bug tracker is kindly provided by
-`Upfront Systems <http://www.upfrontsoftware.co.za>`__
+`Upfront Systems <https://upfrontsoftware.co.za>`__
 of Stellenbosch, South Africa.  Martin von Löwis put a
 lot of effort into importing existing bugs and patches from
 SourceForge; his scripts for this import operation are at
@@ -1433,7 +1433,7 @@ one, :func:`math.trunc`, that's been bac
 
    `Scheme's numerical tower <https://www.gnu.org/software/guile/manual/html_node/Numerical-Tower.html#Numerical-Tower>`__, from the Guile manual.
 
-   `Scheme's number datatypes <https://schemers.org/Documents/Standards/R5RS/HTML/r5rs-Z-H-9.html#%_sec_6.2>`__ from the R5RS Scheme specification.
+   `Scheme's number datatypes <https://conservatory.scheme.org/schemers/Documents/Standards/R5RS/HTML/r5rs-Z-H-9.html#%_sec_6.2>`__ from the R5RS Scheme specification.
 
 
 The :mod:`fractions` Module
@@ -2363,7 +2363,7 @@ changes, or look through the Subversion
   negotiation itself.  (Patch contributed by Bill Fenner;
   :issue:`829951`.)
 
-* The :mod:`socket` module now supports TIPC (http://tipc.sourceforge.net/),
+* The :mod:`socket` module now supports TIPC (https://tipc.sourceforge.net/),
   a high-performance non-IP-based protocol designed for use in clustered
   environments.  TIPC addresses are 4- or 5-tuples.
   (Contributed by Alberto Bertogli; :issue:`1646`.)
diff -pruN 3.12.0~a7-1/Doc/whatsnew/2.7.rst 3.12.0~b1-1/Doc/whatsnew/2.7.rst
--- 3.12.0~a7-1/Doc/whatsnew/2.7.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/whatsnew/2.7.rst	2023-05-22 12:07:36.000000000 +0000
@@ -2104,7 +2104,7 @@ Changes to Python's build process and to
 
 * The latest release of the GNU Debugger, GDB 7, can be `scripted
   using Python
-  <https://sourceware.org/gdb/current/onlinedocs/gdb/Python.html>`__.
+  <https://web.archive.org/web/20110715084810/http://sourceware.org/gdb/current/onlinedocs/gdb/Python.html>`__.
   When you begin debugging an executable program P, GDB will look for
   a file named ``P-gdb.py`` and automatically read it.  Dave Malcolm
   contributed a :file:`python-gdb.py` that adds a number of
diff -pruN 3.12.0~a7-1/Doc/whatsnew/3.0.rst 3.12.0~b1-1/Doc/whatsnew/3.0.rst
--- 3.12.0~a7-1/Doc/whatsnew/3.0.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/whatsnew/3.0.rst	2023-05-22 12:07:36.000000000 +0000
@@ -840,7 +840,7 @@ Builtins
   need it; however, 99 percent of the time an explicit :keyword:`for`
   loop is more readable.
 
-* Removed :func:`reload`.  Use :func:`imp.reload`.
+* Removed :func:`reload`.  Use :func:`!imp.reload`.
 
 * Removed. :meth:`dict.has_key` -- use the :keyword:`in` operator
   instead.
diff -pruN 3.12.0~a7-1/Doc/whatsnew/3.10.rst 3.12.0~b1-1/Doc/whatsnew/3.10.rst
--- 3.12.0~a7-1/Doc/whatsnew/3.10.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/whatsnew/3.10.rst	2023-05-22 12:07:36.000000000 +0000
@@ -1608,11 +1608,11 @@ Deprecated
 * Starting in this release, there will be a concerted effort to begin
   cleaning up old import semantics that were kept for Python 2.7
   compatibility. Specifically,
-  :meth:`~importlib.abc.PathEntryFinder.find_loader`/:meth:`~importlib.abc.Finder.find_module`
+  :meth:`!find_loader`/:meth:`!find_module`
   (superseded by :meth:`~importlib.abc.Finder.find_spec`),
   :meth:`~importlib.abc.Loader.load_module`
   (superseded by :meth:`~importlib.abc.Loader.exec_module`),
-  :meth:`~importlib.abc.Loader.module_repr` (which the import system
+  :meth:`!module_repr` (which the import system
   takes care of for you), the ``__package__`` attribute
   (superseded by ``__spec__.parent``), the ``__loader__`` attribute
   (superseded by ``__spec__.loader``), and the ``__cached__`` attribute
@@ -1645,8 +1645,8 @@ Deprecated
   :meth:`~importlib.abc.Loader.exec_module` is preferred.
   (Contributed by Brett Cannon in :issue:`26131`.)
 
-* The use of :meth:`importlib.abc.MetaPathFinder.find_module` and
-  :meth:`importlib.abc.PathEntryFinder.find_module` by the import system now
+* The use of :meth:`!importlib.abc.MetaPathFinder.find_module` and
+  :meth:`!importlib.abc.PathEntryFinder.find_module` by the import system now
   trigger an :exc:`ImportWarning` as
   :meth:`importlib.abc.MetaPathFinder.find_spec` and
   :meth:`importlib.abc.PathEntryFinder.find_spec`
@@ -1654,53 +1654,53 @@ Deprecated
   :func:`importlib.util.spec_from_loader` to help in porting.
   (Contributed by Brett Cannon in :issue:`42134`.)
 
-* The use of :meth:`importlib.abc.PathEntryFinder.find_loader` by the import
+* The use of :meth:`!importlib.abc.PathEntryFinder.find_loader` by the import
   system now triggers an :exc:`ImportWarning` as
   :meth:`importlib.abc.PathEntryFinder.find_spec` is preferred. You can use
   :func:`importlib.util.spec_from_loader` to help in porting.
   (Contributed by Brett Cannon in :issue:`43672`.)
 
 * The various implementations of
-  :meth:`importlib.abc.MetaPathFinder.find_module` (
-  :meth:`importlib.machinery.BuiltinImporter.find_module`,
-  :meth:`importlib.machinery.FrozenImporter.find_module`,
-  :meth:`importlib.machinery.WindowsRegistryFinder.find_module`,
-  :meth:`importlib.machinery.PathFinder.find_module`,
-  :meth:`importlib.abc.MetaPathFinder.find_module` ),
-  :meth:`importlib.abc.PathEntryFinder.find_module` (
-  :meth:`importlib.machinery.FileFinder.find_module` ), and
-  :meth:`importlib.abc.PathEntryFinder.find_loader` (
-  :meth:`importlib.machinery.FileFinder.find_loader` )
+  :meth:`!importlib.abc.MetaPathFinder.find_module` (
+  :meth:`!importlib.machinery.BuiltinImporter.find_module`,
+  :meth:`!importlib.machinery.FrozenImporter.find_module`,
+  :meth:`!importlib.machinery.WindowsRegistryFinder.find_module`,
+  :meth:`!importlib.machinery.PathFinder.find_module`,
+  :meth:`!importlib.abc.MetaPathFinder.find_module` ),
+  :meth:`!importlib.abc.PathEntryFinder.find_module` (
+  :meth:`!importlib.machinery.FileFinder.find_module` ), and
+  :meth:`!importlib.abc.PathEntryFinder.find_loader` (
+  :meth:`!importlib.machinery.FileFinder.find_loader` )
   now raise :exc:`DeprecationWarning` and are slated for removal in
   Python 3.12 (previously they were documented as deprecated in Python 3.4).
   (Contributed by Brett Cannon in :issue:`42135`.)
 
-* :class:`importlib.abc.Finder` is deprecated (including its sole method,
-  :meth:`~importlib.abc.Finder.find_module`). Both
+* :class:`!importlib.abc.Finder` is deprecated (including its sole method,
+  :meth:`!find_module`). Both
   :class:`importlib.abc.MetaPathFinder` and :class:`importlib.abc.PathEntryFinder`
   no longer inherit from the class. Users should inherit from one of these two
   classes as appropriate instead.
   (Contributed by Brett Cannon in :issue:`42135`.)
 
-* The deprecations of :mod:`imp`, :func:`importlib.find_loader`,
-  :func:`importlib.util.set_package_wrapper`,
-  :func:`importlib.util.set_loader_wrapper`,
-  :func:`importlib.util.module_for_loader`,
-  :class:`pkgutil.ImpImporter`, and
-  :class:`pkgutil.ImpLoader` have all been updated to list Python 3.12 as the
+* The deprecations of :mod:`!imp`, :func:`!importlib.find_loader`,
+  :func:`!importlib.util.set_package_wrapper`,
+  :func:`!importlib.util.set_loader_wrapper`,
+  :func:`!importlib.util.module_for_loader`,
+  :class:`!pkgutil.ImpImporter`, and
+  :class:`!pkgutil.ImpLoader` have all been updated to list Python 3.12 as the
   slated version of removal (they began raising :exc:`DeprecationWarning` in
   previous versions of Python).
   (Contributed by Brett Cannon in :issue:`43720`.)
 
 * The import system now uses the ``__spec__`` attribute on modules before
-  falling back on :meth:`~importlib.abc.Loader.module_repr` for a module's
+  falling back on :meth:`!module_repr` for a module's
   ``__repr__()`` method. Removal of the use of ``module_repr()`` is scheduled
   for Python 3.12.
   (Contributed by Brett Cannon in :issue:`42137`.)
 
-* :meth:`importlib.abc.Loader.module_repr`,
-  :meth:`importlib.machinery.FrozenLoader.module_repr`, and
-  :meth:`importlib.machinery.BuiltinLoader.module_repr` are deprecated and
+* :meth:`!importlib.abc.Loader.module_repr`,
+  :meth:`!importlib.machinery.FrozenLoader.module_repr`, and
+  :meth:`!importlib.machinery.BuiltinLoader.module_repr` are deprecated and
   slated for removal in Python 3.12.
   (Contributed by Brett Cannon in :issue:`42136`.)
 
diff -pruN 3.12.0~a7-1/Doc/whatsnew/3.11.rst 3.12.0~b1-1/Doc/whatsnew/3.11.rst
--- 3.12.0~a7-1/Doc/whatsnew/3.11.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/whatsnew/3.11.rst	2023-05-22 12:07:36.000000000 +0000
@@ -220,7 +220,7 @@ The copy of the :ref:`launcher` included
 updated. It now supports company/tag syntax as defined in :pep:`514` using the
 ``-V:<company>/<tag>`` argument instead of the limited ``-<major>.<minor>``.
 This allows launching distributions other than ``PythonCore``,
-the one hosted on `python.org <https://python.org>`_.
+the one hosted on `python.org <https://www.python.org>`_.
 
 When using ``-V:`` selectors, either company or tag can be omitted, but all
 installs will be searched. For example, ``-V:OtherPython/`` will select the
@@ -666,19 +666,11 @@ enum
   for :meth:`~object.__str__` and :meth:`~object.__format__`
   (used by :func:`str`, :func:`format` and :term:`f-string`\s).
 
-* Changed :class:`~enum.IntEnum`, :class:`~enum.IntFlag` and :class:`~enum.StrEnum`
-  to now inherit from :class:`~enum.ReprEnum`,
-  so their :func:`str` output now matches :func:`format`
-  (both ``str(AnIntEnum.ONE)`` and ``format(AnIntEnum.ONE)`` return ``'1'``,
-  whereas before ``str(AnIntEnum.ONE)`` returned ``'AnIntEnum.ONE'``.
-
-* Changed :meth:`Enum.__format__() <enum.Enum.__format__>`
-  (the default for :func:`format`, :meth:`str.format` and :term:`f-string`\s)
-  of enums with mixed-in types (e.g. :class:`int`, :class:`str`)
-  to also include the class name in the output, not just the member's key.
-  This matches the existing behavior of :meth:`enum.Enum.__str__`,
-  returning e.g. ``'AnEnum.MEMBER'`` for an enum ``AnEnum(str, Enum)``
-  instead of just ``'MEMBER'``.
+* Changed :meth:`Enum.__format__() <enum.Enum.__format__>` (the default for
+  :func:`format`, :meth:`str.format` and :term:`f-string`\s) to always produce
+  the same result as :meth:`Enum.__str__()`:  for enums inheriting from
+  :class:`~enum.ReprEnum` it will be the member's value; for all other enums
+  it will be the enum and member name (e.g. ``Color.RED``).
 
 * Added a new *boundary* class parameter to :class:`~enum.Flag` enums
   and the :class:`~enum.FlagBoundary` enum with its options,
@@ -1880,28 +1872,28 @@ C APIs pending removal are
 * The :mod:`asynchat` module
 * The :mod:`asyncore` module
 * The :ref:`entire distutils package <distutils-deprecated>`
-* The :mod:`imp` module
+* The :mod:`!imp` module
 * The :class:`typing.io <typing.IO>` namespace
 * The :class:`typing.re <typing.Pattern>` namespace
 * :func:`!cgi.log`
-* :func:`importlib.find_loader`
-* :meth:`importlib.abc.Loader.module_repr`
-* :meth:`importlib.abc.MetaPathFinder.find_module`
-* :meth:`importlib.abc.PathEntryFinder.find_loader`
-* :meth:`importlib.abc.PathEntryFinder.find_module`
+* :func:`!importlib.find_loader`
+* :meth:`!importlib.abc.Loader.module_repr`
+* :meth:`!importlib.abc.MetaPathFinder.find_module`
+* :meth:`!importlib.abc.PathEntryFinder.find_loader`
+* :meth:`!importlib.abc.PathEntryFinder.find_module`
 * :meth:`!importlib.machinery.BuiltinImporter.find_module`
 * :meth:`!importlib.machinery.BuiltinLoader.module_repr`
 * :meth:`!importlib.machinery.FileFinder.find_loader`
 * :meth:`!importlib.machinery.FileFinder.find_module`
 * :meth:`!importlib.machinery.FrozenImporter.find_module`
 * :meth:`!importlib.machinery.FrozenLoader.module_repr`
-* :meth:`importlib.machinery.PathFinder.find_module`
+* :meth:`!importlib.machinery.PathFinder.find_module`
 * :meth:`!importlib.machinery.WindowsRegistryFinder.find_module`
-* :func:`importlib.util.module_for_loader`
+* :func:`!importlib.util.module_for_loader`
 * :func:`!importlib.util.set_loader_wrapper`
 * :func:`!importlib.util.set_package_wrapper`
-* :class:`pkgutil.ImpImporter`
-* :class:`pkgutil.ImpLoader`
+* :class:`!pkgutil.ImpImporter`
+* :class:`!pkgutil.ImpLoader`
 * :meth:`pathlib.Path.link_to`
 * :func:`!sqlite3.enable_shared_cache`
 * :func:`!sqlite3.OptimizedUnicode`
@@ -2489,7 +2481,7 @@ Porting to Python 3.11
       #endif
 
   Or use the `pythoncapi_compat project
-  <https://github.com/python/pythoncapi_compat>`__ to get these two
+  <https://github.com/python/pythoncapi-compat>`__ to get these two
   functions on older Python versions.
 
 * Changes of the :c:type:`PyThreadState` structure members:
@@ -2541,8 +2533,8 @@ Porting to Python 3.11
       }
       #endif
 
-  Or use `the pythoncapi_compat project
-  <https://github.com/python/pythoncapi_compat>`__ to get these functions
+  Or use `the pythoncapi-compat project
+  <https://github.com/python/pythoncapi-compat>`__ to get these functions
   on old Python functions.
 
 * Distributors are encouraged to build Python with the optimized Blake2
diff -pruN 3.12.0~a7-1/Doc/whatsnew/3.12.rst 3.12.0~b1-1/Doc/whatsnew/3.12.rst
--- 3.12.0~a7-1/Doc/whatsnew/3.12.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/whatsnew/3.12.rst	2023-05-22 12:07:36.000000000 +0000
@@ -66,11 +66,19 @@ Summary -- Release highlights
 
 .. PEP-sized items next.
 
+New typing features:
+
+* :pep:`688`: Making the buffer protocol accessible in Python
+
+* :ref:`whatsnew312-pep692`
+
+* :pep:`698`: Override Decorator for Static Typing
+
 Important deprecations, removals or restrictions:
 
-* :pep:`623`, Remove wstr from Unicode
+* :pep:`623`: Remove wstr from Unicode
 
-* :pep:`632`, Remove the ``distutils`` package.
+* :pep:`632`: Remove the ``distutils`` package
 
 Improved Error Messages
 =======================
@@ -137,7 +145,80 @@ New Features
   (Design by Pablo Galindo. Contributed by Pablo Galindo and Christian Heimes
   with contributions from Gregory P. Smith [Google] and Mark Shannon
   in :gh:`96123`.)
+* The extraction methods in :mod:`tarfile`, and :func:`shutil.unpack_archive`,
+  have a new a *filter* argument that allows limiting tar features than may be
+  surprising or dangerous, such as creating files outside the destination
+  directory.
+  See :ref:`tarfile-extraction-filter` for details.
+  In Python 3.14, the default will switch to ``'data'``.
+  (Contributed by Petr Viktorin in :pep:`706`.)
+
+.. _whatsnew312-pep709:
+
+PEP 709: Comprehension inlining
+-------------------------------
+
+Dictionary, list, and set comprehensions are now inlined, rather than creating a
+new single-use function object for each execution of the comprehension. This
+speeds up execution of a comprehension by up to 2x.
+
+Comprehension iteration variables remain isolated; they don't overwrite a
+variable of the same name in the outer scope, nor are they visible after the
+comprehension. This isolation is now maintained via stack/locals manipulation,
+not via separate function scope.
+
+Inlining does result in a few visible behavior changes:
+
+* There is no longer a separate frame for the comprehension in tracebacks,
+  and tracing/profiling no longer shows the comprehension as a function call.
+* Calling :func:`locals` inside a comprehension now includes variables
+  from outside the comprehension, and no longer includes the synthetic ``.0``
+  variable for the comprehension "argument".
+
+Contributed by Carl Meyer and Vladimir Matveev in :pep:`709`.
+
+PEP 688: Making the buffer protocol accessible in Python
+--------------------------------------------------------
+
+:pep:`688` introduces a way to use the :ref:`buffer protocol <bufferobjects>`
+from Python code. Classes that implement the :meth:`~object.__buffer__` method
+are now usable as buffer types.
+
+The new :class:`collections.abc.Buffer` ABC provides a standard
+way to represent buffer objects, for example in type annotations.
+The new :class:`inspect.BufferFlags` enum represents the flags that
+can be used to customize buffer creation.
+(Contributed by Jelle Zijlstra in :gh:`102500`.)
+
+New Features Related to Type Hints
+==================================
+
+This section covers major changes affecting :pep:`484` type hints and
+the :mod:`typing` module.
+
+.. _whatsnew312-pep692:
+
+PEP 692: Using ``TypedDict`` for more precise ``**kwargs`` typing
+-----------------------------------------------------------------
+
+Typing ``**kwargs`` in a function signature as introduced by :pep:`484` allowed
+for valid annotations only in cases where all of the ``**kwargs`` were of the
+same type.
+
+This PEP specifies a more precise way of typing ``**kwargs`` by relying on
+typed dictionaries::
 
+   from typing import TypedDict, Unpack
+
+   class Movie(TypedDict):
+     name: str
+     year: int
+
+   def foo(**kwargs: Unpack[Movie]): ...
+
+See :pep:`692` for more details.
+
+(PEP written by Franek Magiera)
 
 Other Language Changes
 ======================
@@ -192,6 +273,16 @@ Other Language Changes
 * :class:`slice` objects are now hashable, allowing them to be used as dict keys and
   set items. (Contributed by Will Bradshaw and Furkan Onder in :gh:`101264`.)
 
+* Exceptions raised in a typeobject's ``__set_name__`` method are no longer
+  wrapped by a :exc:`RuntimeError`. Context information is added to the
+  exception as a :pep:`678` note. (Contributed by Irit Katriel in :gh:`77757`.)
+
+* When a ``try-except*`` construct handles the entire :exc:`ExceptionGroup`
+  and raises one other exception, that exception is no longer wrapped in an
+  :exc:`ExceptionGroup`. Also changed in version 3.11.4. (Contributed by Irit
+  Katriel in :gh:`103590`.)
+
+
 New Modules
 ===========
 
@@ -210,6 +301,16 @@ array
 asyncio
 -------
 
+* The performance of writing to sockets in :mod:`asyncio` has been
+  significantly improved. ``asyncio`` now avoids unnecessary copying when
+  writing to sockets and uses :meth:`~socket.socket.sendmsg` if the platform
+  supports it. (Contributed by Kumar Aditya in :gh:`91166`.)
+
+* Added :func:`asyncio.eager_task_factory` and :func:`asyncio.create_eager_task_factory`
+  functions to allow opting an event loop in to eager task execution,
+  making some use-cases 2x to 5x faster.
+  (Contributed by Jacob Bower & Itamar O in :gh:`102853`, :gh:`104140`, and :gh:`104138`)
+
 * On Linux, :mod:`asyncio` uses :class:`~asyncio.PidfdChildWatcher` by default
   if :func:`os.pidfd_open` is available and functional instead of
   :class:`~asyncio.ThreadedChildWatcher`.
@@ -241,9 +342,23 @@ asyncio
   :mod:`asyncio` does not support legacy generator-based coroutines.
   (Contributed by Kumar Aditya in :gh:`102748`.)
 
-* :func:`asyncio.wait` now accepts generators yielding tasks.
+* :func:`asyncio.wait` and :func:`asyncio.as_completed` now accepts generators
+  yielding tasks.
   (Contributed by Kumar Aditya in :gh:`78530`.)
 
+calendar
+--------
+
+* Add enums :data:`~calendar.Month` and :data:`~calendar.Day`.
+  (Contributed by Prince Roshan in :gh:`103636`.)
+
+csv
+---
+
+* Add :data:`~csv.QUOTE_NOTNULL` and :data:`~csv.QUOTE_STRINGS` flags to
+  provide finer grained control of ``None`` and empty strings by
+  :class:`~csv.writer` objects.
+
 inspect
 -------
 
@@ -255,9 +370,19 @@ inspect
   for determining the current state of asynchronous generators.
   (Contributed by Thomas Krennwallner in :issue:`35759`.)
 
+* The performance of :func:`inspect.getattr_static` has been considerably
+  improved. Most calls to the function should be at least 2x faster than they
+  were in Python 3.11, and some may be 6x faster or more. (Contributed by Alex
+  Waygood in :gh:`103193`.)
+
 pathlib
 -------
 
+* Add support for subclassing :class:`pathlib.PurePath` and
+  :class:`~pathlib.Path`, plus their Posix- and Windows-specific variants.
+  Subclasses may override the :meth:`~pathlib.PurePath.with_segments` method
+  to pass information between path instances.
+
 * Add :meth:`~pathlib.Path.walk` for walking the directory trees and generating
   all file or directory names within them, similar to :func:`os.walk`.
   (Contributed by Stanislav Zmiev in :gh:`90385`.)
@@ -270,6 +395,9 @@ pathlib
 * Add :meth:`pathlib.Path.is_junction` as a proxy to :func:`os.path.isjunction`.
   (Contributed by Charles Machalow in :gh:`99547`.)
 
+* Add *case_sensitive* optional parameter to :meth:`pathlib.Path.glob`,
+  :meth:`pathlib.Path.rglob` and :meth:`pathlib.PurePath.match` for matching
+  the path's case sensitivity, allowing for more precise control over the matching process.
 
 dis
 ---
@@ -288,6 +416,13 @@ fractions
 * Objects of type :class:`fractions.Fraction` now support float-style
   formatting. (Contributed by Mark Dickinson in :gh:`100161`.)
 
+itertools
+---------
+
+* Added :class:`itertools.batched()` for collecting into even-sized
+  tuples where the last batch may be shorter than the rest.
+  (Contributed by Raymond Hettinger in :gh:`98363`.)
+
 math
 ----
 
@@ -328,6 +463,14 @@ os.path
 * Add :func:`os.path.splitroot` to split a path into a triad
   ``(drive, root, tail)``. (Contributed by Barney Gale in :gh:`101000`.)
 
+pdb
+---
+
+* Add convenience variables to hold values temporarily for debug session
+  and provide quick access to values like the current frame or the return
+  value.
+  (Contributed by Tian Gao in :gh:`103693`.)
+
 shutil
 ------
 
@@ -343,6 +486,20 @@ shutil
   will be removed in Python 3.14.
   (Contributed by Irit Katriel in :gh:`102828`.)
 
+* :func:`shutil.which` now consults the *PATHEXT* environment variable to
+  find matches within *PATH* on Windows even when the given *cmd* includes
+  a directory component.
+  (Contributed by Charles Machalow in :gh:`103179`.)
+
+  :func:`shutil.which` will call ``NeedCurrentDirectoryForExePathW`` when
+  querying for executables on Windows to determine if the current working
+  directory should be prepended to the search path.
+  (Contributed by Charles Machalow in :gh:`103179`.)
+
+  :func:`shutil.which` will return a path matching the *cmd* with a component
+  from ``PATHEXT`` prior to a direct match elsewhere in the search path on
+  Windows.
+  (Contributed by Charles Machalow in :gh:`103179`.)
 
 sqlite3
 -------
@@ -357,6 +514,16 @@ sqlite3
   :ref:`transaction handling <sqlite3-transaction-control-autocommit>`.
   (Contributed by Erlend E. Aasland in :gh:`83638`.)
 
+* Add *entrypoint* keyword-only parameter to
+  :meth:`~sqlite3.Connection.load_extension`,
+  for overriding the SQLite extension entry point.
+  (Contributed by Erlend E. Aasland in :gh:`103015`.)
+
+* Add :meth:`~sqlite3.Connection.getconfig` and
+  :meth:`~sqlite3.Connection.setconfig` to :class:`~sqlite3.Connection`
+  to make configuration changes to a database connection.
+  (Contributed by Erlend E. Aasland in :gh:`103489`.)
+
 threading
 ---------
 
@@ -365,6 +532,24 @@ threading
   profiling functions in all running threads in addition to the calling one.
   (Contributed by Pablo Galindo in :gh:`93503`.)
 
+tkinter
+-------
+
+* ``tkinter.Canvas.coords()`` now flattens its arguments.
+  It now accepts not only coordinates as separate arguments
+  (``x1, y1, x2, y2, ...``) and a sequence of coordinates
+  (``[x1, y1, x2, y2, ...]``), but also coordinates grouped in pairs
+  (``(x1, y1), (x2, y2), ...`` and ``[(x1, y1), (x2, y2), ...]``),
+  like ``create_*()`` methods.
+  (Contributed by Serhiy Storchaka in :gh:`94473`.)
+
+types
+-----
+
+* Add :func:`types.get_original_bases` to allow for further introspection of
+  :ref:`user-defined-generics` when subclassed. (Contributed by
+  James Hilton-Balfe and Alex Waygood in :gh:`101827`.)
+
 unicodedata
 -----------
 
@@ -401,8 +586,12 @@ uuid
 tempfile
 --------
 
-The :class:`tempfile.NamedTemporaryFile` function has a new optional parameter
-*delete_on_close* (Contributed by Evgeny Zorin in :gh:`58451`.)
+* The :class:`tempfile.NamedTemporaryFile` function has a new optional parameter
+  *delete_on_close* (Contributed by Evgeny Zorin in :gh:`58451`.)
+* :func:`tempfile.mkdtemp` now always returns an absolute path, even if the
+  argument provided to the *dir* parameter is a relative path.
+
+.. _whatsnew-typing-py312:
 
 typing
 ------
@@ -423,6 +612,39 @@ typing
   vice versa. Most users are unlikely to be affected by this change.
   (Contributed by Alex Waygood in :gh:`102433`.)
 
+* The members of a runtime-checkable protocol are now considered "frozen" at
+  runtime as soon as the class has been created. Monkey-patching attributes
+  onto a runtime-checkable protocol will still work, but will have no impact on
+  :func:`isinstance` checks comparing objects to the protocol. For example::
+
+      >>> from typing import Protocol, runtime_checkable
+      >>> @runtime_checkable
+      ... class HasX(Protocol):
+      ...     x = 1
+      ...
+      >>> class Foo: ...
+      ...
+      >>> f = Foo()
+      >>> isinstance(f, HasX)
+      False
+      >>> f.x = 1
+      >>> isinstance(f, HasX)
+      True
+      >>> HasX.y = 2
+      >>> isinstance(f, HasX)  # unchanged, even though HasX now also has a "y" attribute
+      True
+
+  This change was made in order to speed up ``isinstance()`` checks against
+  runtime-checkable protocols.
+
+* The performance profile of :func:`isinstance` checks against
+  :func:`runtime-checkable protocols <typing.runtime_checkable>` has changed
+  significantly. Most ``isinstance()`` checks against protocols with only a few
+  members should be at least 2x faster than in 3.11, and some may be 20x
+  faster or more. However, ``isinstance()`` checks against protocols with fourteen
+  or more members may be slower than in Python 3.11. (Contributed by Alex
+  Waygood in :gh:`74690` and :gh:`103193`.)
+
 sys
 ---
 
@@ -441,6 +663,10 @@ sys
   :data:`sys.last_type`, :data:`sys.last_value` and :data:`sys.last_traceback`.
   (Contributed by Irit Katriel in :gh:`102778`.)
 
+* :func:`sys._current_exceptions` now returns a mapping from thread-id to an
+  exception instance, rather than to a ``(typ, exc, tb)`` tuple.
+  (Contributed by Irit Katriel in :gh:`103176`.)
+
 
 Optimizations
 =============
@@ -451,13 +677,16 @@ Optimizations
 
 * Added experimental support for using the BOLT binary optimizer in the build
   process, which improves performance by 1-5%.
-  (Contributed by Kevin Modzelewski in :gh:`90536`.)
+  (Contributed by Kevin Modzelewski in :gh:`90536` and tuned by Dong-hee Na in :gh:`101525`)
 
 * Speed up the regular expression substitution (functions :func:`re.sub` and
   :func:`re.subn` and corresponding :class:`!re.Pattern` methods) for
   replacement strings containing group references by 2--3 times.
   (Contributed by Serhiy Storchaka in :gh:`91524`.)
 
+* Speed up :class:`asyncio.Task` creation by deferring expensive string formatting.
+  (Contributed by Itamar O in :gh:`103793`.)
+
 
 CPython bytecode changes
 ========================
@@ -542,6 +771,29 @@ Deprecated
 * The *onerror* argument of :func:`shutil.rmtree` is deprecated as will be removed
   in Python 3.14. Use *onexc* instead. (Contributed by Irit Katriel in :gh:`102828`.)
 
+* Extracting tar archives without specifying *filter* is deprecated until
+  Python 3.14, when ``'data'`` filter will become the default.
+  See :ref:`tarfile-extraction-filter` for details.
+
+* ``calendar.January`` and ``calendar.February`` constants are deprecated and
+  replaced by :data:`calendar.Month.JANUARY` and :data:`calendar.Month.FEBRUARY`.
+  (Contributed by Prince Roshan in :gh:`103636`.)
+
+* The bitwise inversion operator (``~``) on bool is deprecated. It will throw an
+  error in Python 3.14. Use ``not`` for logical negation of bools instead.
+  In the rare case that you really need the bitwise inversion of the underlying
+  ``int``, convert to int explicitly with ``~int(x)``. (Contributed by Tim Hoffmann
+  in :gh:`103487`.)
+
+* :class:`datetime.datetime`'s
+  :meth:`~datetime.datetime.utcnow` and
+  :meth:`~datetime.datetime.utcfromtimestamp` are deprecated and will be
+  removed in a future version. Instead, use timezone-aware objects to represent
+  datetimes in UTC: respectively, call
+  :meth:`~datetime.datetime.now` and
+  :meth:`~datetime.datetime.fromtimestamp`  with the *tz* parameter set to
+  :attr:`datetime.UTC`.
+  (Contributed by Paul Ganssle in :gh:`103857`.)
 
 Pending Removal in Python 3.13
 ------------------------------
@@ -598,6 +850,14 @@ Pending Removal in Python 3.14
 
   (Contributed by Jason R. Coombs and Hugo van Kemenade in :gh:`93963`.)
 
+* Deprecated :class:`collections.abc.ByteString`.
+  Prefer :class:`Sequence` or :class:`collections.abc.Buffer`.
+  For use in typing, prefer a union, like ``bytes | bytearray``, or :class:`collections.abc.Buffer`.
+  (Contributed by Shantanu Jain in :gh:`91896`.)
+
+* :class:`typing.ByteString`, deprecated since Python 3.9, now causes a
+  :exc:`DeprecationWarning` to be emitted when it is used.
+
 * Creating immutable types (:data:`Py_TPFLAGS_IMMUTABLETYPE`) with mutable
   bases using the C API.
 
@@ -631,6 +891,29 @@ Pending Removal in Python 3.14
 * The *onerror* argument of :func:`shutil.rmtree` is deprecated in 3.12,
   and will be removed in 3.14.
 
+* The *type*, *choices*, and *metavar* parameters
+  of :class:`!argparse.BooleanOptionalAction` are deprecated
+  and will be removed in 3.14.
+  (Contributed by Nikita Sobolev in :gh:`92248`.)
+
+* :func:`pkgutil.find_loader` and :func:`pkgutil.get_loader`
+  now raise :exc:`DeprecationWarning`;
+  use :func:`importlib.util.find_spec` instead.
+  (Contributed by Nikita Sobolev in :gh:`97850`.)
+
+* The following :mod:`ast` features have been deprecated in documentation since
+  Python 3.8, now cause a :exc:`DeprecationWarning` to be emitted at runtime
+  when they are accessed or used, and will be removed in Python 3.14:
+
+  * :class:`!ast.Num`
+  * :class:`!ast.Str`
+  * :class:`!ast.Bytes`
+  * :class:`!ast.NameConstant`
+  * :class:`!ast.Ellipsis`
+
+  Use :class:`ast.Constant` instead.
+  (Contributed by Serhiy Storchaka in :gh:`90953`.)
+
 Pending Removal in Future Versions
 ----------------------------------
 
@@ -658,6 +941,24 @@ Removed
   project can be installed: it still provides ``distutils``.
   (Contributed by Victor Stinner in :gh:`92584`.)
 
+* Remove the bundled setuptools wheel from :mod:`ensurepip`,
+  and stop installing setuptools in environments created by :mod:`venv`.
+
+  ``pip (>= 22.1)`` does not require setuptools to be installed in the
+  environment. ``setuptools``-based (and ``distutils``-based) packages
+  can still be used with ``pip install``, since pip will provide
+  ``setuptools`` in the build environment it uses for building a
+  package.
+
+  ``easy_install``, ``pkg_resources``, ``setuptools`` and ``distutils``
+  are no longer provided by default in environments created with
+  ``venv`` or bootstrapped with ``ensurepip``, since they are part of
+  the ``setuptools`` package. For projects relying on these at runtime,
+  the ``setuptools`` project should be declared as a dependency and
+  installed separately (typically, using pip).
+
+  (Contributed by Pradyun Gedam in :gh:`95299`.)
+
 * Removed many old deprecated :mod:`unittest` features:
 
   - A number of :class:`~unittest.TestCase` method aliases:
@@ -792,11 +1093,20 @@ Removed
 * Many previously deprecated cleanups in :mod:`importlib` have now been
   completed:
 
-  * References to, and support for ``module_repr()`` has been eradicated.
+  * References to, and support for :meth:`!module_repr()` has been removed.
+    (Contributed by Barry Warsaw in :gh:`97850`.)
 
+  * ``importlib.util.set_package`` has been removed. (Contributed by Brett
+    Cannon in :gh:`65961`.)
 
-* ``importlib.util.set_package`` has been removed.
-  (Contributed by Brett Cannon in :gh:`65961`.)
+  * Support for ``find_loader()`` and ``find_module()`` APIs have been
+    removed.  (Contributed by Barry Warsaw in :gh:`98040`.)
+
+  * ``importlib.abc.Finder``, ``pkg.ImpImporter``, and ``pkg.ImpLoader`` have
+    been removed.  (Contributed by Barry Warsaw in :gh:`98040`.)
+
+  * The :mod:`!imp` module has been removed.  (Contributed by Barry Warsaw in
+    :gh:`98040`.)
 
 * Removed the ``suspicious`` rule from the documentation Makefile, and
   removed ``Doc/tools/rstlint.py``, both in favor of `sphinx-lint
@@ -882,6 +1192,14 @@ Changes in the Python API
   synchronization is needed, implement locking within the cached property getter
   function or around multi-threaded access points.
 
+* :func:`sys._current_exceptions` now returns a mapping from thread-id to an
+  exception instance, rather than to a ``(typ, exc, tb)`` tuple.
+  (Contributed by Irit Katriel in :gh:`103176`.)
+
+* When extracting tar files using :mod:`tarfile` or
+  :func:`shutil.unpack_archive`, pass the *filter* argument to limit features
+  that may be surprising or dangerous.
+  See :ref:`tarfile-extraction-filter` for details.
 
 Build Changes
 =============
@@ -907,6 +1225,16 @@ Build Changes
   optimization levels (0, 1, 2) at once.
   (Contributed by Victor Stinner in :gh:`99289`.)
 
+* Add platform triplets for 64-bit LoongArch:
+
+  * loongarch64-linux-gnusf
+  * loongarch64-linux-gnuf32
+  * loongarch64-linux-gnu
+
+  (Contributed by Zhang Na in :gh:`90656`.)
+
+* ``PYTHON_FOR_REGEN`` now require Python 3.10 or newer.
+
 
 C API Changes
 =============
@@ -937,6 +1265,21 @@ New Features
 
   (Contributed by Petr Viktorin in :gh:`101101`.)
 
+* :pep:`697`: Added API for extending types whose instance memory layout is
+  opaque:
+
+  - :c:member:`PyType_Spec.basicsize` can be zero or negative to specify
+    inheriting or extending the base class size.
+  - :c:func:`PyObject_GetTypeData` and :c:func:`PyType_GetTypeDataSize`
+    added to allow access to subclass-specific instance data.
+  - :const:`Py_TPFLAGS_ITEMS_AT_END` and :c:func:`PyObject_GetItemData`
+    added to allow safely extending certain variable-sized types, including
+    :c:var:`PyType_Type`.
+  - :c:macro:`Py_RELATIVE_OFFSET` added to allow defining
+    :c:type:`members <PyMemberDef>` in terms of a subclass-specific struct.
+
+  (Contributed by Petr Viktorin in :gh:`103509`.)
+
 * Added the new limited C API function :c:func:`PyType_FromMetaclass`,
   which generalizes the existing :c:func:`PyType_FromModuleAndSpec` using
   an additional metaclass argument.
@@ -1026,6 +1369,24 @@ New Features
   to replace the legacy-api :c:func:`!PyErr_Display`. (Contributed by
   Irit Katriel in :gh:`102755`).
 
+* :pep:`683`: Introduced Immortal Objects to Python which allows objects
+  to bypass reference counts and introduced changes to the C-API:
+
+  - ``_Py_IMMORTAL_REFCNT``: The reference count that defines an object
+      as immortal.
+  - ``_Py_IsImmortal`` Checks if an object has the immortal reference count.
+  - ``PyObject_HEAD_INIT`` This will now initialize reference count to
+      ``_Py_IMMORTAL_REFCNT`` when used with ``Py_BUILD_CORE``.
+  - ``SSTATE_INTERNED_IMMORTAL`` An identifier for interned unicode objects
+       that are immortal.
+  - ``SSTATE_INTERNED_IMMORTAL_STATIC`` An identifier for interned unicode
+       objects that are immortal and static
+  - ``sys.getunicodeinternedsize`` This returns the total number of unicode
+      objects that have been interned. This is now needed for refleak.py to
+      correctly track reference counts and allocated blocks
+
+  (Contributed by Eddie Elizondo in :gh:`84436`.)
+
 Porting to Python 3.12
 ----------------------
 
@@ -1052,6 +1413,12 @@ Porting to Python 3.12
   :py:meth:`~class.__subclasses__` (using :c:func:`PyObject_CallMethod`,
   for example).
 
+* Add support of more formatting options (left aligning, octals, uppercase
+  hexadecimals, ``intmax_t``, ``ptrdiff_t``, ``wchar_t`` C
+  strings, variable width and precision) in :c:func:`PyUnicode_FromFormat` and
+  :c:func:`PyUnicode_FromFormatV`.
+  (Contributed by Serhiy Storchaka in :gh:`98836`.)
+
 * An unrecognized format character in :c:func:`PyUnicode_FromFormat` and
   :c:func:`PyUnicode_FromFormatV` now sets a :exc:`SystemError`.
   In previous versions it caused all the rest of the format string to be
@@ -1094,6 +1461,21 @@ Porting to Python 3.12
   available on debug builds.  If you happen to be using it then you'll
   need to start using ``_Py_GetGlobalRefTotal()``.
 
+* The following functions now select an appropriate metaclass for the newly
+  created type:
+
+  * :c:func:`PyType_FromSpec`
+  * :c:func:`PyType_FromSpecWithBases`
+  * :c:func:`PyType_FromModuleAndSpec`
+
+  Creating classes whose metaclass overrides :c:member:`~PyTypeObject.tp_new`
+  is deprecated, and in Python 3.14+ it will be disallowed.
+  Note that these functions ignore ``tp_new`` of the metaclass, possibly
+  allowing incomplete initialization.
+
+  Note that :c:func:`PyType_FromMetaclass` (added in Python 3.12)
+  already disallows creating classes whose metaclass overrides ``tp_new``.
+
 Deprecated
 ----------
 
@@ -1170,6 +1552,11 @@ Deprecated
 * ``_PyErr_ChainExceptions`` is deprecated. Use ``_PyErr_ChainExceptions1``
   instead. (Contributed by Irit Katriel in :gh:`102192`.)
 
+* Using :c:func:`PyType_FromSpec`, :c:func:`PyType_FromSpecWithBases`
+  or :c:func:`PyType_FromModuleAndSpec` to create a class whose metaclass
+  overrides :c:member:`~PyTypeObject.tp_new` is deprecated.
+  Call the metaclass instead.
+
 Removed
 -------
 
@@ -1190,8 +1577,7 @@ Removed
    * :c:func:`!PyUnicode_GetSize`
    * :c:func:`!PyUnicode_GET_DATA_SIZE`
 
-* Remove the ``PyUnicode_InternImmortal()`` function and the
-  ``SSTATE_INTERNED_IMMORTAL`` macro.
+* Remove the ``PyUnicode_InternImmortal()`` function macro.
   (Contributed by Victor Stinner in :gh:`85858`.)
 
 * Remove ``Jython`` compatibility hacks from several stdlib modules and tests.
diff -pruN 3.12.0~a7-1/Doc/whatsnew/3.2.rst 3.12.0~b1-1/Doc/whatsnew/3.2.rst
--- 3.12.0~a7-1/Doc/whatsnew/3.2.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/whatsnew/3.2.rst	2023-05-22 12:07:36.000000000 +0000
@@ -319,7 +319,7 @@ aspects that are visible to the programm
    >>> collections.__cached__ # doctest: +SKIP
    'c:/py32/lib/__pycache__/collections.cpython-32.pyc'
 
-* The tag that is unique to each interpreter is accessible from the :mod:`imp`
+* The tag that is unique to each interpreter is accessible from the :mod:`!imp`
   module:
 
    >>> import imp # doctest: +SKIP
@@ -328,7 +328,7 @@ aspects that are visible to the programm
 
 * Scripts that try to deduce source filename from the imported file now need to
   be smarter.  It is no longer sufficient to simply strip the "c" from a ".pyc"
-  filename.  Instead, use the new functions in the :mod:`imp` module:
+  filename.  Instead, use the new functions in the :mod:`!imp` module:
 
   >>> imp.source_from_cache('c:/py32/lib/__pycache__/collections.cpython-32.pyc') # doctest: +SKIP
   'c:/py32/lib/collections.py'
@@ -785,8 +785,8 @@ functools
 
   (Contributed by Raymond Hettinger and incorporating design ideas from Jim
   Baker, Miki Tebeka, and Nick Coghlan; see `recipe 498245
-  <https://code.activestate.com/recipes/498245>`_\, `recipe 577479
-  <https://code.activestate.com/recipes/577479>`_\, :issue:`10586`, and
+  <https://code.activestate.com/recipes/498245/>`_\, `recipe 577479
+  <https://code.activestate.com/recipes/577479/>`_\, :issue:`10586`, and
   :issue:`10593`.)
 
 * The :func:`functools.wraps` decorator now adds a :attr:`__wrapped__` attribute
@@ -2603,7 +2603,7 @@ Also, there were a number of updates to
 for details.  For users running a 32/64-bit
 build, there is a known problem with the default Tcl/Tk on Mac OS X 10.6.
 Accordingly, we recommend installing an updated alternative such as
-`ActiveState Tcl/Tk 8.5.9 <https://www.activestate.com/activetcl/downloads>`_\.
+`ActiveState Tcl/Tk 8.5.9 <https://web.archive.org/web/20101208191259/https://www.activestate.com/activetcl/downloads>`_\.
 See https://www.python.org/download/mac/tcltk/ for additional details.
 
 Porting to Python 3.2
diff -pruN 3.12.0~a7-1/Doc/whatsnew/3.3.rst 3.12.0~b1-1/Doc/whatsnew/3.3.rst
--- 3.12.0~a7-1/Doc/whatsnew/3.3.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/whatsnew/3.3.rst	2023-05-22 12:07:36.000000000 +0000
@@ -685,7 +685,7 @@ through normal attribute access.
 Using importlib as the Implementation of Import
 ===============================================
 :issue:`2377` - Replace __import__ w/ importlib.__import__
-:issue:`13959` - Re-implement parts of :mod:`imp` in pure Python
+:issue:`13959` - Re-implement parts of :mod:`!imp` in pure Python
 :issue:`14605` - Make import machinery explicit
 :issue:`14646` - Require loaders set __loader__ and __package__
 
@@ -714,7 +714,7 @@ to properly delineate between :term:`met
 and :term:`path entry finders <path entry finder>` by introducing
 :class:`importlib.abc.MetaPathFinder` and
 :class:`importlib.abc.PathEntryFinder`, respectively. The old ABC of
-:class:`importlib.abc.Finder` is now only provided for backwards-compatibility
+:class:`!importlib.abc.Finder` is now only provided for backwards-compatibility
 and does not enforce any method requirements.
 
 In terms of finders, :class:`importlib.machinery.FileFinder` exposes the
@@ -762,7 +762,7 @@ Loaders are also now expected to set the
 from :mod:`importlib` and import itself is setting the attribute post-load.
 
 ``None`` is now inserted into :attr:`sys.path_importer_cache` when no finder
-can be found on :attr:`sys.path_hooks`. Since :class:`imp.NullImporter` is not
+can be found on :attr:`sys.path_hooks`. Since :class:`!imp.NullImporter` is not
 directly exposed on :attr:`sys.path_hooks` it could no longer be relied upon to
 always be available to use as a value representing no finder found.
 
@@ -1893,7 +1893,7 @@ socket
 
 * The :class:`~socket.socket` class now supports the PF_RDS protocol family
   (https://en.wikipedia.org/wiki/Reliable_Datagram_Sockets and
-  https://oss.oracle.com/projects/rds/).
+  `https://oss.oracle.com/projects/rds <https://web.archive.org/web/20130115155505/https://oss.oracle.com/projects/rds/>`__).
 
 * The :class:`~socket.socket` class now supports the ``PF_SYSTEM`` protocol
   family on OS X.  (Contributed by Michael Goderbauer in :issue:`13777`.)
@@ -2385,12 +2385,12 @@ Porting Python code
 * Because ``None`` is now inserted into :attr:`sys.path_importer_cache`, if you
   are clearing out entries in the dictionary of paths that do not have a
   finder, you will need to remove keys paired with values of ``None`` **and**
-  :class:`imp.NullImporter` to be backwards-compatible. This will lead to extra
+  :class:`!imp.NullImporter` to be backwards-compatible. This will lead to extra
   overhead on older versions of Python that re-insert ``None`` into
   :attr:`sys.path_importer_cache` where it represents the use of implicit
   finders, but semantically it should not change anything.
 
-* :class:`importlib.abc.Finder` no longer specifies a ``find_module()`` abstract
+* :class:`!importlib.abc.Finder` no longer specifies a ``find_module()`` abstract
   method that must be implemented. If you were relying on subclasses to
   implement that method, make sure to check for the method's existence first.
   You will probably want to check for ``find_loader()`` first, though, in the
diff -pruN 3.12.0~a7-1/Doc/whatsnew/3.4.rst 3.12.0~b1-1/Doc/whatsnew/3.4.rst
--- 3.12.0~a7-1/Doc/whatsnew/3.4.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/whatsnew/3.4.rst	2023-05-22 12:07:36.000000000 +0000
@@ -991,18 +991,18 @@ for the :meth:`~importlib.abc.InspectLoa
 it will normally be desirable to override the default implementation
 for performance reasons.  (Contributed by Brett Cannon in :issue:`18072`.)
 
-The :func:`~importlib.reload` function has been moved from :mod:`imp` to
-:mod:`importlib` as part of the :mod:`imp` module deprecation.  (Contributed by
+The :func:`~importlib.reload` function has been moved from :mod:`!imp` to
+:mod:`importlib` as part of the :mod:`!imp` module deprecation.  (Contributed by
 Berker Peksag in :issue:`18193`.)
 
 :mod:`importlib.util` now has a :data:`~importlib.util.MAGIC_NUMBER` attribute
 providing access to the bytecode version number.  This replaces the
-:func:`~imp.get_magic` function in the deprecated :mod:`imp` module.
+:func:`!get_magic` function in the deprecated :mod:`!imp` module.
 (Contributed by Brett Cannon in :issue:`18192`.)
 
 New :mod:`importlib.util` functions :func:`~importlib.util.cache_from_source`
 and :func:`~importlib.util.source_from_cache` replace the same-named functions
-in the deprecated :mod:`imp` module.  (Contributed by Brett Cannon in
+in the deprecated :mod:`!imp` module.  (Contributed by Brett Cannon in
 :issue:`18194`.)
 
 The :mod:`importlib` bootstrap :class:`.NamespaceLoader` now conforms to
@@ -2077,31 +2077,31 @@ Deprecations in the Python API
 ------------------------------
 
 * As mentioned in :ref:`whatsnew-pep-451`, a number of :mod:`importlib`
-  methods and functions are deprecated: :meth:`importlib.find_loader` is
+  methods and functions are deprecated: :meth:`!importlib.find_loader` is
   replaced by :func:`importlib.util.find_spec`;
-  :meth:`importlib.machinery.PathFinder.find_module` is replaced by
+  :meth:`!importlib.machinery.PathFinder.find_module` is replaced by
   :meth:`importlib.machinery.PathFinder.find_spec`;
-  :meth:`importlib.abc.MetaPathFinder.find_module` is replaced by
+  :meth:`!importlib.abc.MetaPathFinder.find_module` is replaced by
   :meth:`importlib.abc.MetaPathFinder.find_spec`;
-  :meth:`importlib.abc.PathEntryFinder.find_loader` and
-  :meth:`~importlib.abc.PathEntryFinder.find_module` are replaced by
+  :meth:`!importlib.abc.PathEntryFinder.find_loader` and
+  :meth:`!find_module` are replaced by
   :meth:`importlib.abc.PathEntryFinder.find_spec`; all of the ``xxxLoader`` ABC
-  ``load_module`` methods (:meth:`importlib.abc.Loader.load_module`,
-  :meth:`importlib.abc.InspectLoader.load_module`,
-  :meth:`importlib.abc.FileLoader.load_module`,
-  :meth:`importlib.abc.SourceLoader.load_module`) should no longer be
+  ``load_module`` methods (:meth:`!importlib.abc.Loader.load_module`,
+  :meth:`!importlib.abc.InspectLoader.load_module`,
+  :meth:`!importlib.abc.FileLoader.load_module`,
+  :meth:`!importlib.abc.SourceLoader.load_module`) should no longer be
   implemented, instead loaders should implement an
   ``exec_module`` method
   (:meth:`importlib.abc.Loader.exec_module`,
   :meth:`importlib.abc.InspectLoader.exec_module`
   :meth:`importlib.abc.SourceLoader.exec_module`) and let the import system
   take care of the rest; and
-  :meth:`importlib.abc.Loader.module_repr`,
-  :meth:`importlib.util.module_for_loader`, :meth:`importlib.util.set_loader`,
-  and :meth:`importlib.util.set_package` are no longer needed because their
+  :meth:`!importlib.abc.Loader.module_repr`,
+  :meth:`!importlib.util.module_for_loader`, :meth:`!importlib.util.set_loader`,
+  and :meth:`!importlib.util.set_package` are no longer needed because their
   functions are now handled automatically by the import system.
 
-* The :mod:`imp` module is pending deprecation. To keep compatibility with
+* The :mod:`!imp` module is pending deprecation. To keep compatibility with
   Python 2/3 code bases, the module's removal is currently not scheduled.
 
 * The :mod:`formatter` module is pending deprecation and is slated for removal
@@ -2277,7 +2277,7 @@ Changes in the Python API
   in a backwards-compatible fashion, use e.g.
   ``getattr(module, '__loader__', None) is not None``.  (:issue:`17115`.)
 
-* :meth:`importlib.util.module_for_loader` now sets ``__loader__`` and
+* :meth:`!importlib.util.module_for_loader` now sets ``__loader__`` and
   ``__package__`` unconditionally to properly support reloading. If this is not
   desired then you will need to set these attributes manually. You can use
   :func:`importlib.util.module_to_load` for module management.
@@ -2300,7 +2300,7 @@ Changes in the Python API
   then you can see if the module's ``__spec__.location`` is set to ``'frozen'``,
   check if the loader is a subclass of
   :class:`importlib.machinery.FrozenImporter`,
-  or if Python 2 compatibility is necessary you can use :func:`imp.is_frozen`.
+  or if Python 2 compatibility is necessary you can use :func:`!imp.is_frozen`.
 
 * :func:`py_compile.compile` now raises :exc:`FileExistsError` if the file path
   it would write to is a symlink or a non-regular file. This is to act as a
diff -pruN 3.12.0~a7-1/Doc/whatsnew/3.5.rst 3.12.0~b1-1/Doc/whatsnew/3.5.rst
--- 3.12.0~a7-1/Doc/whatsnew/3.5.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/whatsnew/3.5.rst	2023-05-22 12:07:36.000000000 +0000
@@ -425,7 +425,7 @@ are declared in the annotations::
 While these annotations are available at runtime through the usual
 :attr:`__annotations__` attribute, *no automatic type checking happens at
 runtime*.  Instead, it is assumed that a separate off-line type checker
-(e.g. `mypy <http://mypy-lang.org>`_) will be used for on-demand
+(e.g. `mypy <https://mypy-lang.org>`_) will be used for on-demand
 source code analysis.
 
 The type system supports unions, generic types, and a special type
@@ -2212,7 +2212,7 @@ for details.)
 The :c:member:`PyTypeObject.tp_finalize` slot is now part of the stable ABI.
 
 Windows builds now require Microsoft Visual C++ 14.0, which
-is available as part of `Visual Studio 2015 <https://www.visualstudio.com/>`_.
+is available as part of `Visual Studio 2015 <https://visualstudio.microsoft.com/en/vs/older-downloads/#visual-studio-2015-and-other-products>`_.
 
 Extension modules now include a platform information tag in their filename on
 some platforms (the tag is optional, and CPython will import extensions without
diff -pruN 3.12.0~a7-1/Doc/whatsnew/3.6.rst 3.12.0~b1-1/Doc/whatsnew/3.6.rst
--- 3.12.0~a7-1/Doc/whatsnew/3.6.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/whatsnew/3.6.rst	2023-05-22 12:07:36.000000000 +0000
@@ -238,7 +238,7 @@ and the ``__annotations__`` attribute.
       and Guido van Rossum. Implemented by Ivan Levkivskyi.
 
    Tools that use or will use the new syntax:
-   `mypy <http://www.mypy-lang.org/>`_,
+   `mypy <https://www.mypy-lang.org/>`_,
    `pytype <https://github.com/google/pytype>`_, PyCharm, etc.
 
 
@@ -2180,7 +2180,7 @@ Changes in the Python API
   now raises :exc:`ValueError` for out-of-range values, rather than
   returning :const:`None`.  See :issue:`20059`.
 
-* The :mod:`imp` module now raises a :exc:`DeprecationWarning` instead of
+* The :mod:`!imp` module now raises a :exc:`DeprecationWarning` instead of
   :exc:`PendingDeprecationWarning`.
 
 * The following modules have had missing APIs added to their :attr:`__all__`
diff -pruN 3.12.0~a7-1/Doc/whatsnew/3.7.rst 3.12.0~b1-1/Doc/whatsnew/3.7.rst
--- 3.12.0~a7-1/Doc/whatsnew/3.7.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/whatsnew/3.7.rst	2023-05-22 12:07:36.000000000 +0000
@@ -2004,11 +2004,11 @@ importlib
 ---------
 
 Methods
-:meth:`MetaPathFinder.find_module() <importlib.abc.MetaPathFinder.find_module>`
+:meth:`MetaPathFinder.find_module() <!importlib.abc.MetaPathFinder.find_module>`
 (replaced by
 :meth:`MetaPathFinder.find_spec() <importlib.abc.MetaPathFinder.find_spec>`)
 and
-:meth:`PathEntryFinder.find_loader() <importlib.abc.PathEntryFinder.find_loader>`
+:meth:`PathEntryFinder.find_loader() <!importlib.abc.PathEntryFinder.find_loader>`
 (replaced by
 :meth:`PathEntryFinder.find_spec() <importlib.abc.PathEntryFinder.find_spec>`)
 both deprecated in Python 3.4 now emit :exc:`DeprecationWarning`.
diff -pruN 3.12.0~a7-1/Doc/whatsnew/3.8.rst 3.12.0~b1-1/Doc/whatsnew/3.8.rst
--- 3.12.0~a7-1/Doc/whatsnew/3.8.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/whatsnew/3.8.rst	2023-05-22 12:07:36.000000000 +0000
@@ -2229,7 +2229,7 @@ The benchmarks were measured on an
 `Intel® Core™ i7-4960HQ processor
 <https://ark.intel.com/content/www/us/en/ark/products/76088/intel-core-i7-4960hq-processor-6m-cache-up-to-3-80-ghz.html>`_
 running the macOS 64-bit builds found at
-`python.org <https://www.python.org/downloads/mac-osx/>`_.
+`python.org <https://www.python.org/downloads/macos/>`_.
 The benchmark script displays timings in nanoseconds.
 
 
diff -pruN 3.12.0~a7-1/Doc/whatsnew/3.9.rst 3.12.0~b1-1/Doc/whatsnew/3.9.rst
--- 3.12.0~a7-1/Doc/whatsnew/3.9.rst	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Doc/whatsnew/3.9.rst	2023-05-22 12:07:36.000000000 +0000
@@ -849,7 +849,7 @@ in nanoseconds.  The benchmarks were mea
 `Intel® Core™ i7-4960HQ processor
 <https://ark.intel.com/content/www/us/en/ark/products/76088/intel-core-i7-4960hq-processor-6m-cache-up-to-3-80-ghz.html>`_
 running the macOS 64-bit builds found at
-`python.org <https://www.python.org/downloads/mac-osx/>`_.
+`python.org <https://www.python.org/downloads/macos/>`_.
 
 
 Deprecated
diff -pruN 3.12.0~a7-1/Grammar/Tokens 3.12.0~b1-1/Grammar/Tokens
--- 3.12.0~a7-1/Grammar/Tokens	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Grammar/Tokens	2023-05-22 12:07:36.000000000 +0000
@@ -53,6 +53,7 @@ ATEQUAL                 '@='
 RARROW                  '->'
 ELLIPSIS                '...'
 COLONEQUAL              ':='
+EXCLAMATION             '!'
 
 OP
 AWAIT
@@ -60,9 +61,12 @@ ASYNC
 TYPE_IGNORE
 TYPE_COMMENT
 SOFT_KEYWORD
+FSTRING_START
+FSTRING_MIDDLE
+FSTRING_END
+COMMENT
+NL
 ERRORTOKEN
 
 # These aren't used by the C tokenizer but are needed for tokenize.py
-COMMENT
-NL
 ENCODING
diff -pruN 3.12.0~a7-1/Grammar/python.gram 3.12.0~b1-1/Grammar/python.gram
--- 3.12.0~a7-1/Grammar/python.gram	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Grammar/python.gram	2023-05-22 12:07:36.000000000 +0000
@@ -112,6 +112,7 @@ simple_stmts[asdl_stmt_seq*]:
 # will throw a SyntaxError.
 simple_stmt[stmt_ty] (memo):
     | assignment
+    | &"type" type_alias
     | e=star_expressions { _PyAST_Expr(e, EXTRA) }
     | &'return' return_stmt
     | &('import' | 'from') import_stmt
@@ -194,7 +195,7 @@ yield_stmt[stmt_ty]: y=yield_expr { _PyA
 
 assert_stmt[stmt_ty]: 'assert' a=expression b=[',' z=expression { z }] { _PyAST_Assert(a, b, EXTRA) }
 
-import_stmt[stmt_ty]: 
+import_stmt[stmt_ty]:
     | invalid_import
     | import_name
     | import_from
@@ -252,8 +253,8 @@ class_def[stmt_ty]:
 
 class_def_raw[stmt_ty]:
     | invalid_class_def_raw
-    | 'class' a=NAME b=['(' z=[arguments] ')' { z }] ':' c=block {
-        _PyAST_ClassDef(a->v.Name.id,
+    | 'class' a=NAME t=[type_params] b=['(' z=[arguments] ')' { z }] ':' c=block {
+        _PyAST_ClassDef(a->v.Name.id, t,
                      (b) ? ((expr_ty) b)->v.Call.args : NULL,
                      (b) ? ((expr_ty) b)->v.Call.keywords : NULL,
                      c, NULL, EXTRA) }
@@ -267,16 +268,16 @@ function_def[stmt_ty]:
 
 function_def_raw[stmt_ty]:
     | invalid_def_raw
-    | 'def' n=NAME &&'(' params=[params] ')' a=['->' z=expression { z }] &&':' tc=[func_type_comment] b=block {
-        _PyAST_FunctionDef(n->v.Name.id,
+    | 'def' n=NAME t=[type_params] &&'(' params=[params] ')' a=['->' z=expression { z }] &&':' tc=[func_type_comment] b=block {
+        _PyAST_FunctionDef(n->v.Name.id, t,
                         (params) ? params : CHECK(arguments_ty, _PyPegen_empty_arguments(p)),
                         b, NULL, a, NEW_TYPE_COMMENT(p, tc), EXTRA) }
-    | ASYNC 'def' n=NAME &&'(' params=[params] ')' a=['->' z=expression { z }] &&':' tc=[func_type_comment] b=block {
+    | ASYNC 'def' n=NAME t=[type_params] &&'(' params=[params] ')' a=['->' z=expression { z }] &&':' tc=[func_type_comment] b=block {
         CHECK_VERSION(
             stmt_ty,
             5,
             "Async functions are",
-            _PyAST_AsyncFunctionDef(n->v.Name.id,
+            _PyAST_AsyncFunctionDef(n->v.Name.id, t,
                             (params) ? params : CHECK(arguments_ty, _PyPegen_empty_arguments(p)),
                             b, NULL, a, NEW_TYPE_COMMENT(p, tc), EXTRA)
         ) }
@@ -415,8 +416,8 @@ try_stmt[stmt_ty]:
     | invalid_try_stmt
     | 'try' &&':' b=block f=finally_block { _PyAST_Try(b, NULL, NULL, f, EXTRA) }
     | 'try' &&':' b=block ex[asdl_excepthandler_seq*]=except_block+ el=[else_block] f=[finally_block] { _PyAST_Try(b, ex, el, f, EXTRA) }
-    | 'try' &&':' b=block ex[asdl_excepthandler_seq*]=except_star_block+ el=[else_block] f=[finally_block] { 
-        CHECK_VERSION(stmt_ty, 11, "Exception groups are", 
+    | 'try' &&':' b=block ex[asdl_excepthandler_seq*]=except_star_block+ el=[else_block] f=[finally_block] {
+        CHECK_VERSION(stmt_ty, 11, "Exception groups are",
                       _PyAST_TryStar(b, ex, el, f, EXTRA)) }
 
 
@@ -628,6 +629,39 @@ keyword_patterns[asdl_seq*]:
 keyword_pattern[KeyPatternPair*]:
     | arg=NAME '=' value=pattern { _PyPegen_key_pattern_pair(p, arg, value) }
 
+# Type statement
+# ---------------
+
+type_alias[stmt_ty]:
+    | "type" n=NAME t=[type_params] '=' b=expression {
+        CHECK_VERSION(stmt_ty, 12, "Type statement is",
+        _PyAST_TypeAlias(CHECK(expr_ty, _PyPegen_set_expr_context(p, n, Store)), t, b, EXTRA)) }
+
+# Type parameter declaration
+# --------------------------
+
+type_params[asdl_type_param_seq*]: '[' t=type_param_seq  ']' {
+        CHECK_VERSION(asdl_type_param_seq *, 12, "Type parameter lists are", t) }
+
+type_param_seq[asdl_type_param_seq*]: a[asdl_type_param_seq*]=','.type_param+ [','] { a }
+
+type_param[type_param_ty] (memo):
+    | a=NAME b=[type_param_bound] { _PyAST_TypeVar(a->v.Name.id, b, EXTRA) }
+    | '*' a=NAME colon=":" e=expression {
+            RAISE_SYNTAX_ERROR_STARTING_FROM(colon, e->kind == Tuple_kind
+                ? "cannot use constraints with TypeVarTuple"
+                : "cannot use bound with TypeVarTuple")
+        }
+    | '*' a=NAME { _PyAST_TypeVarTuple(a->v.Name.id, EXTRA) }
+    | '**' a=NAME colon=":" e=expression {
+            RAISE_SYNTAX_ERROR_STARTING_FROM(colon, e->kind == Tuple_kind
+                ? "cannot use constraints with ParamSpec"
+                : "cannot use bound with ParamSpec")
+        }
+    | '**' a=NAME { _PyAST_ParamSpec(a->v.Name.id, EXTRA) }
+
+type_param_bound[expr_ty]: ":" e=expression { e }
+
 # EXPRESSIONS
 # -----------
 
@@ -807,7 +841,7 @@ atom[expr_ty]:
     | 'True' { _PyAST_Constant(Py_True, NULL, EXTRA) }
     | 'False' { _PyAST_Constant(Py_False, NULL, EXTRA) }
     | 'None' { _PyAST_Constant(Py_None, NULL, EXTRA) }
-    | &STRING strings
+    | &(STRING|FSTRING_START) strings
     | NUMBER
     | &'(' (tuple | group | genexp)
     | &'[' (list | listcomp)
@@ -877,7 +911,25 @@ lambda_param[arg_ty]: a=NAME { _PyAST_ar
 # LITERALS
 # ========
 
-strings[expr_ty] (memo): a=STRING+ { _PyPegen_concatenate_strings(p, a) }
+fstring_middle[expr_ty]:
+    | fstring_replacement_field
+    | t=FSTRING_MIDDLE { _PyPegen_constant_from_token(p, t) }
+fstring_replacement_field[expr_ty]:
+    | '{' a=(yield_expr | star_expressions) debug_expr="="? conversion=[fstring_conversion] format=[fstring_full_format_spec] rbrace='}' {
+        _PyPegen_formatted_value(p, a, debug_expr, conversion, format, rbrace, EXTRA) }
+    | invalid_replacement_field
+fstring_conversion[ResultTokenWithMetadata*]:
+    | conv_token="!" conv=NAME { _PyPegen_check_fstring_conversion(p, conv_token, conv) }
+fstring_full_format_spec[ResultTokenWithMetadata*]:
+    | colon=':' spec=fstring_format_spec* { _PyPegen_setup_full_format_spec(p, colon, (asdl_expr_seq *) spec, EXTRA) }
+fstring_format_spec[expr_ty]:
+    | t=FSTRING_MIDDLE { _PyPegen_constant_from_token(p, t) }
+    | fstring_replacement_field
+fstring[expr_ty]:
+    | a=FSTRING_START b=fstring_middle* c=FSTRING_END { _PyPegen_joined_str(p, a, (asdl_expr_seq*)b, c) }
+
+string[expr_ty]: s[Token*]=STRING { _PyPegen_constant_from_string(p, s) }
+strings[expr_ty] (memo): a[asdl_expr_seq*]=(fstring|string)+ { _PyPegen_concatenate_strings(p, a, EXTRA) }
 
 list[expr_ty]:
     | '[' a=[star_named_expressions] ']' { _PyAST_List(a, Load, EXTRA) }
@@ -1118,6 +1170,8 @@ invalid_expression:
         _PyPegen_check_legacy_stmt(p, a) ? NULL : p->tokens[p->mark-1]->level == 0 ? NULL :
         RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, b, "invalid syntax. Perhaps you forgot a comma?") }
    | a=disjunction 'if' b=disjunction !('else'|':') { RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, b, "expected 'else' after 'if' expression") }
+   | a='lambda' [lambda_params] b=':' &(FSTRING_MIDDLE | fstring_replacement_field)  {
+        RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, b, "f-string: lambda expressions are not allowed without parentheses") }
 
 invalid_named_expression(memo):
     | a=expression ':=' expression {
@@ -1241,7 +1295,7 @@ invalid_group:
 invalid_import:
     | a='import' dotted_name 'from' dotted_name {
         RAISE_SYNTAX_ERROR_STARTING_FROM(a, "Did you mean to use 'from ... import ...' instead?") }
- 
+
 invalid_import_from_targets:
     | import_from_as_names ',' NEWLINE {
         RAISE_SYNTAX_ERROR("trailing comma not allowed without surrounding parentheses") }
@@ -1335,3 +1389,24 @@ invalid_kvpair:
     | expression a=':' &('}'|',') {RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "expression expected after dictionary key and ':'") }
 invalid_starred_expression:
     | a='*' expression '=' b=expression { RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, b, "cannot assign to iterable argument unpacking") }
+invalid_replacement_field:
+    | '{' a='=' { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "f-string: valid expression required before '='") }
+    | '{' a='!' { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "f-string: valid expression required before '!'") }
+    | '{' a=':' { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "f-string: valid expression required before ':'") }
+    | '{' a='}' { RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "f-string: valid expression required before '}'") }
+    | '{' !(yield_expr | star_expressions) { RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN("f-string: expecting a valid expression after '{'")}
+    | '{' (yield_expr | star_expressions) !('=' | '!' | ':' | '}') {
+        PyErr_Occurred() ? NULL : RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN("f-string: expecting '=', or '!', or ':', or '}'") }
+    | '{' (yield_expr | star_expressions) '=' !('!' | ':' | '}') {
+        PyErr_Occurred() ? NULL : RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN("f-string: expecting '!', or ':', or '}'") }
+    | '{' (yield_expr | star_expressions) '='? invalid_conversion_character
+    | '{' (yield_expr | star_expressions) '='? ['!' NAME] !(':' | '}') {
+        PyErr_Occurred() ? NULL : RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN("f-string: expecting ':' or '}'") }
+    | '{' (yield_expr | star_expressions) '='? ['!' NAME] ':' fstring_format_spec* !'}' {
+        PyErr_Occurred() ? NULL : RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN("f-string: expecting '}', or format specs") }
+    | '{' (yield_expr | star_expressions) '='? ['!' NAME] !'}' {
+        PyErr_Occurred() ? NULL : RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN("f-string: expecting '}'") }
+
+invalid_conversion_character:
+    | '!' &(':' | '}') { RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN("f-string: missing conversion character") }
+    | '!' !NAME { RAISE_SYNTAX_ERROR_ON_NEXT_TOKEN("f-string: invalid conversion character") }
diff -pruN 3.12.0~a7-1/Include/boolobject.h 3.12.0~b1-1/Include/boolobject.h
--- 3.12.0~a7-1/Include/boolobject.h	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Include/boolobject.h	2023-05-22 12:07:36.000000000 +0000
@@ -11,8 +11,7 @@ PyAPI_DATA(PyTypeObject) PyBool_Type;
 
 #define PyBool_Check(x) Py_IS_TYPE((x), &PyBool_Type)
 
-/* Py_False and Py_True are the only two bools in existence.
-Don't forget to apply Py_INCREF() when returning either!!! */
+/* Py_False and Py_True are the only two bools in existence. */
 
 /* Don't use these directly */
 PyAPI_DATA(PyLongObject) _Py_FalseStruct;
@@ -31,8 +30,8 @@ PyAPI_FUNC(int) Py_IsFalse(PyObject *x);
 #define Py_IsFalse(x) Py_Is((x), Py_False)
 
 /* Macros for returning Py_True or Py_False, respectively */
-#define Py_RETURN_TRUE return Py_NewRef(Py_True)
-#define Py_RETURN_FALSE return Py_NewRef(Py_False)
+#define Py_RETURN_TRUE return Py_True
+#define Py_RETURN_FALSE return Py_False
 
 /* Function to return a bool from a C long */
 PyAPI_FUNC(PyObject *) PyBool_FromLong(long);
diff -pruN 3.12.0~a7-1/Include/cpython/code.h 3.12.0~b1-1/Include/cpython/code.h
--- 3.12.0~a7-1/Include/cpython/code.h	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Include/cpython/code.h	2023-05-22 12:07:36.000000000 +0000
@@ -3,10 +3,22 @@
 #ifndef Py_LIMITED_API
 #ifndef Py_CODE_H
 #define Py_CODE_H
+
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+
+/* Count of all "real" monitoring events (not derived from other events) */
+#define PY_MONITORING_UNGROUPED_EVENTS 14
+/* Count of all  monitoring events */
+#define PY_MONITORING_EVENTS 16
+
+/* Table of which tools are active for each monitored event. */
+typedef struct _Py_Monitors {
+    uint8_t tools[PY_MONITORING_UNGROUPED_EVENTS];
+} _Py_Monitors;
+
 /* Each instruction in a code object is a fixed-width value,
  * currently 2 bytes: 1-byte opcode + 1-byte oparg.  The EXTENDED_ARG
  * opcode allows for larger values but the current limit is 3 uses
@@ -56,6 +68,35 @@ typedef struct {
     PyObject *_co_freevars;
 } _PyCoCached;
 
+/* Ancilliary data structure used for instrumentation.
+   Line instrumentation creates an array of
+   these. One entry per code unit.*/
+typedef struct {
+    uint8_t original_opcode;
+    int8_t line_delta;
+} _PyCoLineInstrumentationData;
+
+/* Main data structure used for instrumentation.
+ * This is allocated when needed for instrumentation
+ */
+typedef struct {
+    /* Monitoring specific to this code object */
+    _Py_Monitors local_monitors;
+    /* Monitoring that is active on this code object */
+    _Py_Monitors active_monitors;
+    /* The tools that are to be notified for events for the matching code unit */
+    uint8_t *tools;
+    /* Information to support line events */
+    _PyCoLineInstrumentationData *lines;
+    /* The tools that are to be notified for line events for the matching code unit */
+    uint8_t *line_tools;
+    /* Information to support instruction events */
+    /* The underlying instructions, which can themselves be instrumented */
+    uint8_t *per_instruction_opcodes;
+    /* The tools that are to be notified for instruction events for the matching code unit */
+    uint8_t *per_instruction_tools;
+} _PyCoMonitoringData;
+
 // To avoid repeating ourselves in deepfreeze.py, all PyCodeObject members are
 // defined in this macro:
 #define _PyCode_DEF(SIZE) {                                                    \
@@ -87,7 +128,6 @@ typedef struct {
     PyObject *co_exceptiontable;   /* Byte string encoding exception handling  \
                                       table */                                 \
     int co_flags;                  /* CO_..., see below */                     \
-    short _co_linearray_entry_size;  /* Size of each entry in _co_linearray */ \
                                                                                \
     /* The rest are not so impactful on performance. */                        \
     int co_argcount;              /* #arguments, except *args */               \
@@ -114,8 +154,9 @@ typedef struct {
     PyObject *co_linetable;       /* bytes object that holds location info */  \
     PyObject *co_weakreflist;     /* to support weakrefs to code objects */    \
     _PyCoCached *_co_cached;      /* cached co_* attributes */                 \
+    uint64_t _co_instrumentation_version; /* current instrumentation version */  \
+    _PyCoMonitoringData *_co_monitoring; /* Monitoring data */                 \
     int _co_firsttraceable;       /* index of first traceable instruction */   \
-    char *_co_linearray;          /* array of line offsets */                  \
     /* Scratch space for extra data relating to the code object.               \
        Type is a void* to keep the format private in codeobject.c to force     \
        people to go through the proper APIs. */                                \
diff -pruN 3.12.0~a7-1/Include/cpython/frameobject.h 3.12.0~b1-1/Include/cpython/frameobject.h
--- 3.12.0~a7-1/Include/cpython/frameobject.h	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Include/cpython/frameobject.h	2023-05-22 12:07:36.000000000 +0000
@@ -4,6 +4,8 @@
 #  error "this header file must not be included directly"
 #endif
 
+struct _PyInterpreterFrame;
+
 /* Standard object interface */
 
 PyAPI_FUNC(PyFrameObject *) PyFrame_New(PyThreadState *, PyCodeObject *,
@@ -27,3 +29,18 @@ PyAPI_FUNC(int) _PyFrame_IsEntryFrame(Py
 
 PyAPI_FUNC(int) PyFrame_FastToLocalsWithError(PyFrameObject *f);
 PyAPI_FUNC(void) PyFrame_FastToLocals(PyFrameObject *);
+
+/* The following functions are for use by debuggers and other tools
+ * implementing custom frame evaluators with PEP 523. */
+
+/* Returns the code object of the frame (strong reference).
+ * Does not raise an exception. */
+PyAPI_FUNC(PyObject *) PyUnstable_InterpreterFrame_GetCode(struct _PyInterpreterFrame *frame);
+
+/* Returns a byte ofsset into the last executed instruction.
+ * Does not raise an exception. */
+PyAPI_FUNC(int) PyUnstable_InterpreterFrame_GetLasti(struct _PyInterpreterFrame *frame);
+
+/* Returns the currently executing line number, or -1 if there is no line number.
+ * Does not raise an exception. */
+PyAPI_FUNC(int) PyUnstable_InterpreterFrame_GetLine(struct _PyInterpreterFrame *frame);
diff -pruN 3.12.0~a7-1/Include/cpython/funcobject.h 3.12.0~b1-1/Include/cpython/funcobject.h
--- 3.12.0~a7-1/Include/cpython/funcobject.h	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Include/cpython/funcobject.h	2023-05-22 12:07:36.000000000 +0000
@@ -41,6 +41,7 @@ typedef struct {
     PyObject *func_weakreflist; /* List of weak references */
     PyObject *func_module;      /* The __module__ attribute, can be anything */
     PyObject *func_annotations; /* Annotations, a dict or NULL */
+    PyObject *func_typeparams;  /* Tuple of active type variables or NULL */
     vectorcallfunc vectorcall;
     /* Version number for use by specializer.
      * Can set to non-zero when we want to specialize.
diff -pruN 3.12.0~a7-1/Include/cpython/genobject.h 3.12.0~b1-1/Include/cpython/genobject.h
--- 3.12.0~a7-1/Include/cpython/genobject.h	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Include/cpython/genobject.h	2023-05-22 12:07:36.000000000 +0000
@@ -77,6 +77,8 @@ PyAPI_FUNC(PyObject *) PyAsyncGen_New(Py
 
 #define PyAsyncGen_CheckExact(op) Py_IS_TYPE((op), &PyAsyncGen_Type)
 
+#define PyAsyncGenASend_CheckExact(op) Py_IS_TYPE((op), &_PyAsyncGenASend_Type)
+
 
 #undef _PyGenObject_HEAD
 
diff -pruN 3.12.0~a7-1/Include/cpython/initconfig.h 3.12.0~b1-1/Include/cpython/initconfig.h
--- 3.12.0~a7-1/Include/cpython/initconfig.h	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Include/cpython/initconfig.h	2023-05-22 12:07:36.000000000 +0000
@@ -245,29 +245,36 @@ PyAPI_FUNC(PyStatus) PyConfig_SetWideStr
 /* --- PyInterpreterConfig ------------------------------------ */
 
 typedef struct {
+    // XXX "allow_object_sharing"?  "own_objects"?
+    int use_main_obmalloc;
     int allow_fork;
     int allow_exec;
     int allow_threads;
     int allow_daemon_threads;
     int check_multi_interp_extensions;
-} _PyInterpreterConfig;
+    int own_gil;
+} PyInterpreterConfig;
 
 #define _PyInterpreterConfig_INIT \
     { \
+        .use_main_obmalloc = 0, \
         .allow_fork = 0, \
         .allow_exec = 0, \
         .allow_threads = 1, \
         .allow_daemon_threads = 0, \
         .check_multi_interp_extensions = 1, \
+        .own_gil = 1, \
     }
 
 #define _PyInterpreterConfig_LEGACY_INIT \
     { \
+        .use_main_obmalloc = 1, \
         .allow_fork = 1, \
         .allow_exec = 1, \
         .allow_threads = 1, \
         .allow_daemon_threads = 1, \
         .check_multi_interp_extensions = 0, \
+        .own_gil = 0, \
     }
 
 /* --- Helper functions --------------------------------------- */
diff -pruN 3.12.0~a7-1/Include/cpython/longintrepr.h 3.12.0~b1-1/Include/cpython/longintrepr.h
--- 3.12.0~a7-1/Include/cpython/longintrepr.h	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Include/cpython/longintrepr.h	2023-05-22 12:07:36.000000000 +0000
@@ -98,6 +98,32 @@ PyAPI_FUNC(PyLongObject *)
 _PyLong_FromDigits(int negative, Py_ssize_t digit_count, digit *digits);
 
 
+/* Inline some internals for speed. These should be in pycore_long.h
+ * if user code didn't need them inlined. */
+
+#define _PyLong_SIGN_MASK 3
+#define _PyLong_NON_SIZE_BITS 3
+
+static inline int
+_PyLong_IsCompact(const PyLongObject* op) {
+    assert(PyLong_Check(op));
+    return op->long_value.lv_tag < (2 << _PyLong_NON_SIZE_BITS);
+}
+
+#define PyUnstable_Long_IsCompact _PyLong_IsCompact
+
+static inline Py_ssize_t
+_PyLong_CompactValue(const PyLongObject *op)
+{
+    assert(PyLong_Check(op));
+    assert(PyUnstable_Long_IsCompact(op));
+    Py_ssize_t sign = 1 - (op->long_value.lv_tag & _PyLong_SIGN_MASK);
+    return sign * (Py_ssize_t)op->long_value.ob_digit[0];
+}
+
+#define PyUnstable_Long_CompactValue _PyLong_CompactValue
+
+
 #ifdef __cplusplus
 }
 #endif
diff -pruN 3.12.0~a7-1/Include/cpython/longobject.h 3.12.0~b1-1/Include/cpython/longobject.h
--- 3.12.0~a7-1/Include/cpython/longobject.h	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Include/cpython/longobject.h	2023-05-22 12:07:36.000000000 +0000
@@ -93,3 +93,8 @@ PyAPI_FUNC(PyObject *) _PyLong_GCD(PyObj
 
 PyAPI_FUNC(PyObject *) _PyLong_Rshift(PyObject *, size_t);
 PyAPI_FUNC(PyObject *) _PyLong_Lshift(PyObject *, size_t);
+
+
+PyAPI_FUNC(int) PyUnstable_Long_IsCompact(const PyLongObject* op);
+PyAPI_FUNC(Py_ssize_t) PyUnstable_Long_CompactValue(const PyLongObject* op);
+
diff -pruN 3.12.0~a7-1/Include/cpython/memoryobject.h 3.12.0~b1-1/Include/cpython/memoryobject.h
--- 3.12.0~a7-1/Include/cpython/memoryobject.h	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Include/cpython/memoryobject.h	2023-05-22 12:07:36.000000000 +0000
@@ -24,6 +24,7 @@ typedef struct {
 #define _Py_MEMORYVIEW_FORTRAN     0x004  /* Fortran contiguous layout */
 #define _Py_MEMORYVIEW_SCALAR      0x008  /* scalar: ndim = 0 */
 #define _Py_MEMORYVIEW_PIL         0x010  /* PIL-style layout */
+#define _Py_MEMORYVIEW_RESTRICTED  0x020  /* Disallow new references to the memoryview's buffer */
 
 typedef struct {
     PyObject_VAR_HEAD
diff -pruN 3.12.0~a7-1/Include/cpython/object.h 3.12.0~b1-1/Include/cpython/object.h
--- 3.12.0~a7-1/Include/cpython/object.h	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Include/cpython/object.h	2023-05-22 12:07:36.000000000 +0000
@@ -553,6 +553,7 @@ Py_DEPRECATED(3.11) typedef int UsingDep
         Py_TRASHCAN_END; \
     } while(0);
 
+PyAPI_FUNC(void *) PyObject_GetItemData(PyObject *obj);
 
 PyAPI_FUNC(int) _PyObject_VisitManagedDict(PyObject *obj, visitproc visit, void *arg);
 PyAPI_FUNC(void) _PyObject_ClearManagedDict(PyObject *obj);
@@ -564,3 +565,10 @@ PyAPI_FUNC(int) PyType_AddWatcher(PyType
 PyAPI_FUNC(int) PyType_ClearWatcher(int watcher_id);
 PyAPI_FUNC(int) PyType_Watch(int watcher_id, PyObject *type);
 PyAPI_FUNC(int) PyType_Unwatch(int watcher_id, PyObject *type);
+
+/* Attempt to assign a version tag to the given type.
+ *
+ * Returns 1 if the type already had a valid version tag or a new one was
+ * assigned, or 0 if a new tag could not be assigned.
+ */
+PyAPI_FUNC(int) PyUnstable_Type_AssignVersionTag(PyTypeObject *type);
diff -pruN 3.12.0~a7-1/Include/cpython/objimpl.h 3.12.0~b1-1/Include/cpython/objimpl.h
--- 3.12.0~a7-1/Include/cpython/objimpl.h	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Include/cpython/objimpl.h	2023-05-22 12:07:36.000000000 +0000
@@ -90,3 +90,6 @@ PyAPI_FUNC(int) PyObject_IS_GC(PyObject
 PyAPI_FUNC(int) PyType_SUPPORTS_WEAKREFS(PyTypeObject *type);
 
 PyAPI_FUNC(PyObject **) PyObject_GET_WEAKREFS_LISTPTR(PyObject *op);
+
+PyAPI_FUNC(PyObject *) PyUnstable_Object_GC_NewWithExtraData(PyTypeObject *,
+                                                             size_t);
diff -pruN 3.12.0~a7-1/Include/cpython/pylifecycle.h 3.12.0~b1-1/Include/cpython/pylifecycle.h
--- 3.12.0~a7-1/Include/cpython/pylifecycle.h	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Include/cpython/pylifecycle.h	2023-05-22 12:07:36.000000000 +0000
@@ -52,6 +52,7 @@ PyAPI_FUNC(const char *) _Py_gitidentifi
 PyAPI_FUNC(const char *) _Py_gitversion(void);
 
 PyAPI_FUNC(int) _Py_IsFinalizing(void);
+PyAPI_FUNC(int) _Py_IsInterpreterFinalizing(PyInterpreterState *interp);
 
 /* Random */
 PyAPI_FUNC(int) _PyOS_URandom(void *buffer, Py_ssize_t size);
@@ -62,6 +63,10 @@ PyAPI_FUNC(int) _Py_CoerceLegacyLocale(i
 PyAPI_FUNC(int) _Py_LegacyLocaleDetected(int warn);
 PyAPI_FUNC(char *) _Py_SetLocaleFromEnv(int category);
 
-PyAPI_FUNC(PyStatus) _Py_NewInterpreterFromConfig(
+PyAPI_FUNC(PyStatus) Py_NewInterpreterFromConfig(
     PyThreadState **tstate_p,
-    const _PyInterpreterConfig *config);
+    const PyInterpreterConfig *config);
+
+typedef void (*atexit_datacallbackfunc)(void *);
+PyAPI_FUNC(int) _Py_AtExit(
+        PyInterpreterState *, atexit_datacallbackfunc, void *);
diff -pruN 3.12.0~a7-1/Include/cpython/pystate.h 3.12.0~b1-1/Include/cpython/pystate.h
--- 3.12.0~a7-1/Include/cpython/pystate.h	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Include/cpython/pystate.h	2023-05-22 12:07:36.000000000 +0000
@@ -11,6 +11,10 @@ is available in a given context.  For ex
 might not be allowed in the current interpreter (i.e. os.fork() would fail).
 */
 
+/* Set if the interpreter share obmalloc runtime state
+   with the main interpreter. */
+#define Py_RTFLAGS_USE_MAIN_OBMALLOC (1UL << 5)
+
 /* Set if import should check a module for subinterpreter support. */
 #define Py_RTFLAGS_MULTI_INTERP_EXTENSIONS (1UL << 8)
 
@@ -58,12 +62,6 @@ typedef int (*Py_tracefunc)(PyObject *,
 #define PyTrace_C_RETURN 6
 #define PyTrace_OPCODE 7
 
-
-typedef struct {
-    PyCodeObject *code; // The code object for the bounds. May be NULL.
-    PyCodeAddressRange bounds; // Only valid if code != NULL.
-} PyTraceInfo;
-
 // Internal structure: you should not use it directly, but use public functions
 // like PyThreadState_EnterTracing() and PyThreadState_LeaveTracing().
 typedef struct _PyCFrame {
@@ -77,7 +75,6 @@ typedef struct _PyCFrame {
      * discipline and make sure that instances of this struct cannot
      * accessed outside of their lifetime.
      */
-    uint8_t use_tracing;  // 0 or 255 (or'ed into opcode, hence 8-bit type)
     /* Pointer to the currently executing frame (it can be NULL) */
     struct _PyInterpreterFrame *current_frame;
     struct _PyCFrame *previous;
@@ -157,7 +154,7 @@ struct _ts {
        This is to prevent the actual trace/profile code from being recorded in
        the trace/profile. */
     int tracing;
-    int tracing_what; /* The event currently being traced, if any. */
+    int what_event; /* The event currently being monitored, if any. */
 
     /* Pointer to current _PyCFrame in the C stack frame of the currently,
      * or most recently, executing _PyEval_EvalFrameDefault. */
@@ -228,8 +225,6 @@ struct _ts {
     /* Unique thread state id. */
     uint64_t id;
 
-    PyTraceInfo trace_info;
-
     _PyStackChunk *datastack_chunk;
     PyObject **datastack_top;
     PyObject **datastack_limit;
diff -pruN 3.12.0~a7-1/Include/cpython/unicodeobject.h 3.12.0~b1-1/Include/cpython/unicodeobject.h
--- 3.12.0~a7-1/Include/cpython/unicodeobject.h	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Include/cpython/unicodeobject.h	2023-05-22 12:07:36.000000000 +0000
@@ -98,9 +98,16 @@ typedef struct {
     Py_ssize_t length;          /* Number of code points in the string */
     Py_hash_t hash;             /* Hash value; -1 if not set */
     struct {
-        /* If interned is set, the two references from the
-           dictionary to this object are *not* counted in ob_refcnt. */
-        unsigned int interned:1;
+        /* If interned is non-zero, the two references from the
+           dictionary to this object are *not* counted in ob_refcnt.
+           The possible values here are:
+               0: Not Interned
+               1: Interned
+               2: Interned and Immortal
+               3: Interned, Immortal, and Static
+           This categorization allows the runtime to determine the right
+           cleanup mechanism at runtime shutdown. */
+        unsigned int interned:2;
         /* Character size:
 
            - PyUnicode_1BYTE_KIND (1):
@@ -135,7 +142,7 @@ typedef struct {
         unsigned int ascii:1;
         /* Padding to ensure that PyUnicode_DATA() is always aligned to
            4 bytes (see issue #19537 on m68k). */
-        unsigned int :26;
+        unsigned int :25;
     } state;
 } PyASCIIObject;
 
@@ -183,6 +190,8 @@ PyAPI_FUNC(int) _PyUnicode_CheckConsiste
 /* Interning state. */
 #define SSTATE_NOT_INTERNED 0
 #define SSTATE_INTERNED_MORTAL 1
+#define SSTATE_INTERNED_IMMORTAL 2
+#define SSTATE_INTERNED_IMMORTAL_STATIC 3
 
 /* Use only if you know it's a string */
 static inline unsigned int PyUnicode_CHECK_INTERNED(PyObject *op) {
diff -pruN 3.12.0~a7-1/Include/descrobject.h 3.12.0~b1-1/Include/descrobject.h
--- 3.12.0~a7-1/Include/descrobject.h	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Include/descrobject.h	2023-05-22 12:07:36.000000000 +0000
@@ -83,6 +83,7 @@ struct PyMemberDef {
 #define Py_READONLY            1
 #define Py_AUDIT_READ          2 // Added in 3.10, harmless no-op before that
 #define _Py_WRITE_RESTRICTED   4 // Deprecated, no-op. Do not reuse the value.
+#define Py_RELATIVE_OFFSET     8
 
 PyAPI_FUNC(PyObject *) PyMember_GetOne(const char *, PyMemberDef *);
 PyAPI_FUNC(int) PyMember_SetOne(char *, PyMemberDef *, PyObject *);
diff -pruN 3.12.0~a7-1/Include/internal/pycore_ast.h 3.12.0~b1-1/Include/internal/pycore_ast.h
--- 3.12.0~a7-1/Include/internal/pycore_ast.h	2023-04-04 15:52:49.000000000 +0000
+++ 3.12.0~b1-1/Include/internal/pycore_ast.h	2023-05-22 12:07:51.000000000 +0000
@@ -51,6 +51,8 @@ typedef struct _pattern *pattern_ty;
 
 typedef struct _type_ignore *type_ignore_ty;
 
+typedef struct _type_param *type_param_ty;
+
 
 typedef struct {
     _ASDL_SEQ_HEAD
@@ -147,6 +149,14 @@ typedef struct {
 asdl_type_ignore_seq *_Py_asdl_type_ignore_seq_new(Py_ssize_t size, PyArena
                                                    *arena);
 
+typedef struct {
+    _ASDL_SEQ_HEAD
+    type_param_ty typed_elements[1];
+} asdl_type_param_seq;
+
+asdl_type_param_seq *_Py_asdl_type_param_seq_new(Py_ssize_t size, PyArena
+                                                 *arena);
+
 
 enum _mod_kind {Module_kind=1, Interactive_kind=2, Expression_kind=3,
                  FunctionType_kind=4};
@@ -176,17 +186,19 @@ struct _mod {
 
 enum _stmt_kind {FunctionDef_kind=1, AsyncFunctionDef_kind=2, ClassDef_kind=3,
                   Return_kind=4, Delete_kind=5, Assign_kind=6,
-                  AugAssign_kind=7, AnnAssign_kind=8, For_kind=9,
-                  AsyncFor_kind=10, While_kind=11, If_kind=12, With_kind=13,
-                  AsyncWith_kind=14, Match_kind=15, Raise_kind=16, Try_kind=17,
-                  TryStar_kind=18, Assert_kind=19, Import_kind=20,
-                  ImportFrom_kind=21, Global_kind=22, Nonlocal_kind=23,
-                  Expr_kind=24, Pass_kind=25, Break_kind=26, Continue_kind=27};
+                  TypeAlias_kind=7, AugAssign_kind=8, AnnAssign_kind=9,
+                  For_kind=10, AsyncFor_kind=11, While_kind=12, If_kind=13,
+                  With_kind=14, AsyncWith_kind=15, Match_kind=16,
+                  Raise_kind=17, Try_kind=18, TryStar_kind=19, Assert_kind=20,
+                  Import_kind=21, ImportFrom_kind=22, Global_kind=23,
+                  Nonlocal_kind=24, Expr_kind=25, Pass_kind=26, Break_kind=27,
+                  Continue_kind=28};
 struct _stmt {
     enum _stmt_kind kind;
     union {
         struct {
             identifier name;
+            asdl_type_param_seq *type_params;
             arguments_ty args;
             asdl_stmt_seq *body;
             asdl_expr_seq *decorator_list;
@@ -196,6 +208,7 @@ struct _stmt {
 
         struct {
             identifier name;
+            asdl_type_param_seq *type_params;
             arguments_ty args;
             asdl_stmt_seq *body;
             asdl_expr_seq *decorator_list;
@@ -205,6 +218,7 @@ struct _stmt {
 
         struct {
             identifier name;
+            asdl_type_param_seq *type_params;
             asdl_expr_seq *bases;
             asdl_keyword_seq *keywords;
             asdl_stmt_seq *body;
@@ -226,6 +240,12 @@ struct _stmt {
         } Assign;
 
         struct {
+            expr_ty name;
+            asdl_type_param_seq *type_params;
+            expr_ty value;
+        } TypeAlias;
+
+        struct {
             expr_ty target;
             operator_ty op;
             expr_ty value;
@@ -630,6 +650,30 @@ struct _type_ignore {
     } v;
 };
 
+enum _type_param_kind {TypeVar_kind=1, ParamSpec_kind=2, TypeVarTuple_kind=3};
+struct _type_param {
+    enum _type_param_kind kind;
+    union {
+        struct {
+            identifier name;
+            expr_ty bound;
+        } TypeVar;
+
+        struct {
+            identifier name;
+        } ParamSpec;
+
+        struct {
+            identifier name;
+        } TypeVarTuple;
+
+    } v;
+    int lineno;
+    int col_offset;
+    int end_lineno;
+    int end_col_offset;
+};
+
 
 // Note: these macros affect function definitions, not only call sites.
 mod_ty _PyAST_Module(asdl_stmt_seq * body, asdl_type_ignore_seq * type_ignores,
@@ -638,21 +682,22 @@ mod_ty _PyAST_Interactive(asdl_stmt_seq
 mod_ty _PyAST_Expression(expr_ty body, PyArena *arena);
 mod_ty _PyAST_FunctionType(asdl_expr_seq * argtypes, expr_ty returns, PyArena
                            *arena);
-stmt_ty _PyAST_FunctionDef(identifier name, arguments_ty args, asdl_stmt_seq *
-                           body, asdl_expr_seq * decorator_list, expr_ty
-                           returns, string type_comment, int lineno, int
-                           col_offset, int end_lineno, int end_col_offset,
-                           PyArena *arena);
-stmt_ty _PyAST_AsyncFunctionDef(identifier name, arguments_ty args,
-                                asdl_stmt_seq * body, asdl_expr_seq *
-                                decorator_list, expr_ty returns, string
-                                type_comment, int lineno, int col_offset, int
-                                end_lineno, int end_col_offset, PyArena *arena);
-stmt_ty _PyAST_ClassDef(identifier name, asdl_expr_seq * bases,
-                        asdl_keyword_seq * keywords, asdl_stmt_seq * body,
-                        asdl_expr_seq * decorator_list, int lineno, int
-                        col_offset, int end_lineno, int end_col_offset, PyArena
-                        *arena);
+stmt_ty _PyAST_FunctionDef(identifier name, asdl_type_param_seq * type_params,
+                           arguments_ty args, asdl_stmt_seq * body,
+                           asdl_expr_seq * decorator_list, expr_ty returns,
+                           string type_comment, int lineno, int col_offset, int
+                           end_lineno, int end_col_offset, PyArena *arena);
+stmt_ty _PyAST_AsyncFunctionDef(identifier name, asdl_type_param_seq *
+                                type_params, arguments_ty args, asdl_stmt_seq *
+                                body, asdl_expr_seq * decorator_list, expr_ty
+                                returns, string type_comment, int lineno, int
+                                col_offset, int end_lineno, int end_col_offset,
+                                PyArena *arena);
+stmt_ty _PyAST_ClassDef(identifier name, asdl_type_param_seq * type_params,
+                        asdl_expr_seq * bases, asdl_keyword_seq * keywords,
+                        asdl_stmt_seq * body, asdl_expr_seq * decorator_list,
+                        int lineno, int col_offset, int end_lineno, int
+                        end_col_offset, PyArena *arena);
 stmt_ty _PyAST_Return(expr_ty value, int lineno, int col_offset, int
                       end_lineno, int end_col_offset, PyArena *arena);
 stmt_ty _PyAST_Delete(asdl_expr_seq * targets, int lineno, int col_offset, int
@@ -660,6 +705,9 @@ stmt_ty _PyAST_Delete(asdl_expr_seq * ta
 stmt_ty _PyAST_Assign(asdl_expr_seq * targets, expr_ty value, string
                       type_comment, int lineno, int col_offset, int end_lineno,
                       int end_col_offset, PyArena *arena);
+stmt_ty _PyAST_TypeAlias(expr_ty name, asdl_type_param_seq * type_params,
+                         expr_ty value, int lineno, int col_offset, int
+                         end_lineno, int end_col_offset, PyArena *arena);
 stmt_ty _PyAST_AugAssign(expr_ty target, operator_ty op, expr_ty value, int
                          lineno, int col_offset, int end_lineno, int
                          end_col_offset, PyArena *arena);
@@ -844,6 +892,14 @@ pattern_ty _PyAST_MatchOr(asdl_pattern_s
                           col_offset, int end_lineno, int end_col_offset,
                           PyArena *arena);
 type_ignore_ty _PyAST_TypeIgnore(int lineno, string tag, PyArena *arena);
+type_param_ty _PyAST_TypeVar(identifier name, expr_ty bound, int lineno, int
+                             col_offset, int end_lineno, int end_col_offset,
+                             PyArena *arena);
+type_param_ty _PyAST_ParamSpec(identifier name, int lineno, int col_offset, int
+                               end_lineno, int end_col_offset, PyArena *arena);
+type_param_ty _PyAST_TypeVarTuple(identifier name, int lineno, int col_offset,
+                                  int end_lineno, int end_col_offset, PyArena
+                                  *arena);
 
 
 PyObject* PyAST_mod2obj(mod_ty t);
diff -pruN 3.12.0~a7-1/Include/internal/pycore_ast_state.h 3.12.0~b1-1/Include/internal/pycore_ast_state.h
--- 3.12.0~a7-1/Include/internal/pycore_ast_state.h	2023-04-04 15:52:49.000000000 +0000
+++ 3.12.0~b1-1/Include/internal/pycore_ast_state.h	2023-05-22 12:07:51.000000000 +0000
@@ -118,6 +118,7 @@ struct ast_state {
     PyObject *Not_type;
     PyObject *Or_singleton;
     PyObject *Or_type;
+    PyObject *ParamSpec_type;
     PyObject *Pass_type;
     PyObject *Pow_singleton;
     PyObject *Pow_type;
@@ -137,7 +138,10 @@ struct ast_state {
     PyObject *TryStar_type;
     PyObject *Try_type;
     PyObject *Tuple_type;
+    PyObject *TypeAlias_type;
     PyObject *TypeIgnore_type;
+    PyObject *TypeVarTuple_type;
+    PyObject *TypeVar_type;
     PyObject *UAdd_singleton;
     PyObject *UAdd_type;
     PyObject *USub_singleton;
@@ -166,6 +170,7 @@ struct ast_state {
     PyObject *bases;
     PyObject *body;
     PyObject *boolop_type;
+    PyObject *bound;
     PyObject *cases;
     PyObject *cause;
     PyObject *cls;
@@ -243,6 +248,8 @@ struct ast_state {
     PyObject *type_comment;
     PyObject *type_ignore_type;
     PyObject *type_ignores;
+    PyObject *type_param_type;
+    PyObject *type_params;
     PyObject *unaryop_type;
     PyObject *upper;
     PyObject *value;
diff -pruN 3.12.0~a7-1/Include/internal/pycore_atexit.h 3.12.0~b1-1/Include/internal/pycore_atexit.h
--- 3.12.0~a7-1/Include/internal/pycore_atexit.h	1970-01-01 00:00:00.000000000 +0000
+++ 3.12.0~b1-1/Include/internal/pycore_atexit.h	2023-05-22 12:07:36.000000000 +0000
@@ -0,0 +1,56 @@
+#ifndef Py_INTERNAL_ATEXIT_H
+#define Py_INTERNAL_ATEXIT_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef Py_BUILD_CORE
+#  error "this header requires Py_BUILD_CORE define"
+#endif
+
+
+//###############
+// runtime atexit
+
+typedef void (*atexit_callbackfunc)(void);
+
+struct _atexit_runtime_state {
+#define NEXITFUNCS 32
+    atexit_callbackfunc callbacks[NEXITFUNCS];
+    int ncallbacks;
+};
+
+
+//###################
+// interpreter atexit
+
+struct atexit_callback;
+typedef struct atexit_callback {
+    atexit_datacallbackfunc func;
+    void *data;
+    struct atexit_callback *next;
+} atexit_callback;
+
+typedef struct {
+    PyObject *func;
+    PyObject *args;
+    PyObject *kwargs;
+} atexit_py_callback;
+
+struct atexit_state {
+    atexit_callback *ll_callbacks;
+    atexit_callback *last_ll_callback;
+
+    // XXX The rest of the state could be moved to the atexit module state
+    // and a low-level callback added for it during module exec.
+    // For the moment we leave it here.
+    atexit_py_callback **callbacks;
+    int ncallbacks;
+    int callback_len;
+};
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !Py_INTERNAL_ATEXIT_H */
diff -pruN 3.12.0~a7-1/Include/internal/pycore_bytesobject.h 3.12.0~b1-1/Include/internal/pycore_bytesobject.h
--- 3.12.0~a7-1/Include/internal/pycore_bytesobject.h	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Include/internal/pycore_bytesobject.h	2023-05-22 12:07:36.000000000 +0000
@@ -9,11 +9,6 @@ extern "C" {
 #endif
 
 
-/* runtime lifecycle */
-
-extern PyStatus _PyBytes_InitTypes(PyInterpreterState *);
-
-
 /* Substring Search.
 
    Returns the index of the first occurrence of
diff -pruN 3.12.0~a7-1/Include/internal/pycore_call.h 3.12.0~b1-1/Include/internal/pycore_call.h
--- 3.12.0~a7-1/Include/internal/pycore_call.h	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Include/internal/pycore_call.h	2023-05-22 12:07:36.000000000 +0000
@@ -116,6 +116,16 @@ _PyObject_FastCallTstate(PyThreadState *
     return _PyObject_VectorcallTstate(tstate, func, args, (size_t)nargs, NULL);
 }
 
+PyObject *const *
+_PyStack_UnpackDict(PyThreadState *tstate,
+    PyObject *const *args, Py_ssize_t nargs,
+    PyObject *kwargs, PyObject **p_kwnames);
+
+void
+_PyStack_UnpackDict_Free(PyObject *const *stack, Py_ssize_t nargs,
+    PyObject *kwnames);
+
+void _PyStack_UnpackDict_FreeNoDecRef(PyObject *const *stack, PyObject *kwnames);
 
 #ifdef __cplusplus
 }
diff -pruN 3.12.0~a7-1/Include/internal/pycore_ceval.h 3.12.0~b1-1/Include/internal/pycore_ceval.h
--- 3.12.0~a7-1/Include/internal/pycore_ceval.h	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Include/internal/pycore_ceval.h	2023-05-22 12:07:36.000000000 +0000
@@ -21,8 +21,7 @@ struct _ceval_runtime_state;
 
 
 extern void _Py_FinishPendingCalls(PyThreadState *tstate);
-extern void _PyEval_InitRuntimeState(struct _ceval_runtime_state *);
-extern void _PyEval_InitState(struct _ceval_state *, PyThread_type_lock);
+extern void _PyEval_InitState(PyInterpreterState *, PyThread_type_lock);
 extern void _PyEval_FiniState(struct _ceval_state *ceval);
 PyAPI_FUNC(void) _PyEval_SignalReceived(PyInterpreterState *interp);
 PyAPI_FUNC(int) _PyEval_AddPendingCall(
@@ -96,11 +95,13 @@ _PyEval_Vector(PyThreadState *tstate,
             PyObject* const* args, size_t argcount,
             PyObject *kwnames);
 
-extern int _PyEval_ThreadsInitialized(struct pyruntimestate *runtime);
-extern PyStatus _PyEval_InitGIL(PyThreadState *tstate);
+extern int _PyEval_ThreadsInitialized(void);
+extern PyStatus _PyEval_InitGIL(PyThreadState *tstate, int own_gil);
 extern void _PyEval_FiniGIL(PyInterpreterState *interp);
 
+extern void _PyEval_AcquireLock(PyThreadState *tstate);
 extern void _PyEval_ReleaseLock(PyThreadState *tstate);
+extern PyThreadState * _PyThreadState_SwapNoGIL(PyThreadState *);
 
 extern void _PyEval_DeactivateOpCache(void);
 
diff -pruN 3.12.0~a7-1/Include/internal/pycore_ceval_state.h 3.12.0~b1-1/Include/internal/pycore_ceval_state.h
--- 3.12.0~a7-1/Include/internal/pycore_ceval_state.h	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Include/internal/pycore_ceval_state.h	2023-05-22 12:07:36.000000000 +0000
@@ -49,7 +49,6 @@ struct _ceval_runtime_state {
        the main thread of the main interpreter can handle signals: see
        _Py_ThreadCanHandleSignals(). */
     _Py_atomic_int signals_pending;
-    struct _gil_runtime_state gil;
 };
 
 #ifdef PY_HAVE_PERF_TRAMPOLINE
@@ -82,12 +81,14 @@ struct _pending_calls {
 };
 
 struct _ceval_state {
-    int recursion_limit;
     /* This single variable consolidates all requests to break out of
        the fast path in the eval loop. */
     _Py_atomic_int eval_breaker;
     /* Request for dropping the GIL */
     _Py_atomic_int gil_drop_request;
+    int recursion_limit;
+    struct _gil_runtime_state *gil;
+    int own_gil;
     /* The GC is ready to be executed */
     _Py_atomic_int gc_scheduled;
     struct _pending_calls pending;
diff -pruN 3.12.0~a7-1/Include/internal/pycore_code.h 3.12.0~b1-1/Include/internal/pycore_code.h
--- 3.12.0~a7-1/Include/internal/pycore_code.h	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Include/internal/pycore_code.h	2023-05-22 12:07:36.000000000 +0000
@@ -53,6 +53,12 @@ typedef struct {
 
 typedef struct {
     uint16_t counter;
+} _PySuperAttrCache;
+
+#define INLINE_CACHE_ENTRIES_LOAD_SUPER_ATTR CACHE_ENTRIES(_PySuperAttrCache)
+
+typedef struct {
+    uint16_t counter;
     uint16_t version[2];
     uint16_t index;
 } _PyAttrCache;
@@ -73,7 +79,6 @@ typedef struct {
 typedef struct {
     uint16_t counter;
     uint16_t func_version[2];
-    uint16_t min_args;
 } _PyCallCache;
 
 #define INLINE_CACHE_ENTRIES_CALL CACHE_ENTRIES(_PyCallCache)
@@ -123,6 +128,7 @@ struct callable_cache {
 // Note that these all fit within a byte, as do combinations.
 // Later, we will use the smaller numbers to differentiate the different
 // kinds of locals (e.g. pos-only arg, varkwargs, local-only).
+#define CO_FAST_HIDDEN  0x10
 #define CO_FAST_LOCAL   0x20
 #define CO_FAST_CELL    0x40
 #define CO_FAST_FREE    0x80
@@ -218,6 +224,8 @@ extern int _PyLineTable_PreviousAddressR
 
 /* Specialization functions */
 
+extern void _Py_Specialize_LoadSuperAttr(PyObject *global_super, PyObject *cls,
+                                         _Py_CODEUNIT *instr, int load_method);
 extern void _Py_Specialize_LoadAttr(PyObject *owner, _Py_CODEUNIT *instr,
                                     PyObject *name);
 extern void _Py_Specialize_StoreAttr(PyObject *owner, _Py_CODEUNIT *instr,
@@ -442,32 +450,6 @@ adaptive_counter_backoff(uint16_t counte
 
 /* Line array cache for tracing */
 
-extern int _PyCode_CreateLineArray(PyCodeObject *co);
-
-static inline int
-_PyCode_InitLineArray(PyCodeObject *co)
-{
-    if (co->_co_linearray) {
-        return 0;
-    }
-    return _PyCode_CreateLineArray(co);
-}
-
-static inline int
-_PyCode_LineNumberFromArray(PyCodeObject *co, int index)
-{
-    assert(co->_co_linearray != NULL);
-    assert(index >= 0);
-    assert(index < Py_SIZE(co));
-    if (co->_co_linearray_entry_size == 2) {
-        return ((int16_t *)co->_co_linearray)[index];
-    }
-    else {
-        assert(co->_co_linearray_entry_size == 4);
-        return ((int32_t *)co->_co_linearray)[index];
-    }
-}
-
 typedef struct _PyShimCodeDef {
     const uint8_t *code;
     int codelen;
@@ -501,6 +483,10 @@ extern uint32_t _Py_next_func_version;
 
 #define COMPARISON_NOT_EQUALS (COMPARISON_UNORDERED | COMPARISON_LESS_THAN | COMPARISON_GREATER_THAN)
 
+extern int _Py_Instrument(PyCodeObject *co, PyInterpreterState *interp);
+
+extern int _Py_GetBaseOpcode(PyCodeObject *code, int offset);
+
 
 #ifdef __cplusplus
 }
diff -pruN 3.12.0~a7-1/Include/internal/pycore_compile.h 3.12.0~b1-1/Include/internal/pycore_compile.h
--- 3.12.0~a7-1/Include/internal/pycore_compile.h	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Include/internal/pycore_compile.h	2023-05-22 12:07:36.000000000 +0000
@@ -19,6 +19,7 @@ PyAPI_FUNC(PyCodeObject*) _PyAST_Compile
     int optimize,
     struct _arena *arena);
 
+static const _PyCompilerSrcLocation NO_LOCATION = {-1, -1, -1, -1};
 
 typedef struct {
     int optimize;
@@ -33,6 +34,54 @@ extern int _PyAST_Optimize(
     struct _arena *arena,
     _PyASTOptimizeState *state);
 
+typedef struct {
+    int h_offset;
+    int h_startdepth;
+    int h_preserve_lasti;
+} _PyCompile_ExceptHandlerInfo;
+
+typedef struct {
+    int i_opcode;
+    int i_oparg;
+    _PyCompilerSrcLocation i_loc;
+    _PyCompile_ExceptHandlerInfo i_except_handler_info;
+} _PyCompile_Instruction;
+
+typedef struct {
+    _PyCompile_Instruction *s_instrs;
+    int s_allocated;
+    int s_used;
+
+    int *s_labelmap;       /* label id --> instr offset */
+    int s_labelmap_size;
+    int s_next_free_label; /* next free label id */
+} _PyCompile_InstructionSequence;
+
+typedef struct {
+    PyObject *u_name;
+    PyObject *u_qualname;  /* dot-separated qualified name (lazy) */
+
+    /* The following fields are dicts that map objects to
+       the index of them in co_XXX.      The index is used as
+       the argument for opcodes that refer to those collections.
+    */
+    PyObject *u_consts;    /* all constants */
+    PyObject *u_names;     /* all names */
+    PyObject *u_varnames;  /* local variables */
+    PyObject *u_cellvars;  /* cell variables */
+    PyObject *u_freevars;  /* free variables */
+    PyObject *u_fasthidden; /* dict; keys are names that are fast-locals only
+                               temporarily within an inlined comprehension. When
+                               value is True, treat as fast-local. */
+
+    Py_ssize_t u_argcount;        /* number of arguments for block */
+    Py_ssize_t u_posonlyargcount;        /* number of positional only arguments for block */
+    Py_ssize_t u_kwonlyargcount; /* number of keyword only arguments for block */
+
+    int u_firstlineno; /* the first lineno of the block */
+} _PyCompile_CodeUnitMetadata;
+
+
 /* Utility for a number of growing arrays used in the compiler */
 int _PyCompile_EnsureArrayLargeEnough(
         int idx,
@@ -43,17 +92,25 @@ int _PyCompile_EnsureArrayLargeEnough(
 
 int _PyCompile_ConstCacheMergeOne(PyObject *const_cache, PyObject **obj);
 
+int _PyCompile_InstrSize(int opcode, int oparg);
+
 /* Access compiler internals for unit testing */
 
 PyAPI_FUNC(PyObject*) _PyCompile_CodeGen(
         PyObject *ast,
         PyObject *filename,
         PyCompilerFlags *flags,
-        int optimize);
+        int optimize,
+        int compile_mode);
 
 PyAPI_FUNC(PyObject*) _PyCompile_OptimizeCfg(
         PyObject *instructions,
-        PyObject *consts);
+        PyObject *consts,
+        int nlocals);
+
+PyAPI_FUNC(PyCodeObject*)
+_PyCompile_Assemble(_PyCompile_CodeUnitMetadata *umd, PyObject *filename,
+                    PyObject *instructions);
 
 #ifdef __cplusplus
 }
diff -pruN 3.12.0~a7-1/Include/internal/pycore_dict_state.h 3.12.0~b1-1/Include/internal/pycore_dict_state.h
--- 3.12.0~a7-1/Include/internal/pycore_dict_state.h	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Include/internal/pycore_dict_state.h	2023-05-22 12:07:36.000000000 +0000
@@ -38,6 +38,11 @@ struct _Py_dict_state {
     PyDict_WatchCallback watchers[DICT_MAX_WATCHERS];
 };
 
+#define _dict_state_INIT \
+    { \
+        .next_keys_version = 2, \
+    }
+
 
 #ifdef __cplusplus
 }
diff -pruN 3.12.0~a7-1/Include/internal/pycore_dtoa.h 3.12.0~b1-1/Include/internal/pycore_dtoa.h
--- 3.12.0~a7-1/Include/internal/pycore_dtoa.h	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Include/internal/pycore_dtoa.h	2023-05-22 12:07:36.000000000 +0000
@@ -64,8 +64,6 @@ PyAPI_FUNC(double) _Py_dg_strtod(const c
 PyAPI_FUNC(char *) _Py_dg_dtoa(double d, int mode, int ndigits,
                         int *decpt, int *sign, char **rve);
 PyAPI_FUNC(void) _Py_dg_freedtoa(char *s);
-PyAPI_FUNC(double) _Py_dg_stdnan(int sign);
-PyAPI_FUNC(double) _Py_dg_infinity(int sign);
 
 #endif // _PY_SHORT_FLOAT_REPR == 1
 
diff -pruN 3.12.0~a7-1/Include/internal/pycore_fileutils_windows.h 3.12.0~b1-1/Include/internal/pycore_fileutils_windows.h
--- 3.12.0~a7-1/Include/internal/pycore_fileutils_windows.h	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Include/internal/pycore_fileutils_windows.h	2023-05-22 12:07:36.000000000 +0000
@@ -75,6 +75,24 @@ static inline BOOL _Py_GetFileInformatio
     return GetFileInformationByName(FileName, FileInformationClass, FileInfoBuffer, FileInfoBufferSize);
 }
 
+static inline BOOL _Py_GetFileInformationByName_ErrorIsTrustworthy(int error)
+{
+    switch(error) {
+        case ERROR_FILE_NOT_FOUND:
+        case ERROR_PATH_NOT_FOUND:
+        case ERROR_NOT_READY:
+        case ERROR_BAD_NET_NAME:
+        case ERROR_BAD_NETPATH:
+        case ERROR_BAD_PATHNAME:
+        case ERROR_INVALID_NAME:
+        case ERROR_FILENAME_EXCED_RANGE:
+            return TRUE;
+        case ERROR_NOT_SUPPORTED:
+            return FALSE;
+    }
+    return FALSE;
+}
+
 #endif
 
 #endif
diff -pruN 3.12.0~a7-1/Include/internal/pycore_flowgraph.h 3.12.0~b1-1/Include/internal/pycore_flowgraph.h
--- 3.12.0~a7-1/Include/internal/pycore_flowgraph.h	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Include/internal/pycore_flowgraph.h	2023-05-22 12:07:36.000000000 +0000
@@ -9,8 +9,8 @@ extern "C" {
 #endif
 
 #include "pycore_opcode_utils.h"
+#include "pycore_compile.h"
 
-static const _PyCompilerSrcLocation NO_LOCATION = {-1, -1, -1, -1};
 
 typedef struct {
     int i_opcode;
@@ -33,7 +33,8 @@ typedef struct {
 typedef struct _PyCfgBasicblock_ {
     /* Each basicblock in a compilation unit is linked via b_list in the
        reverse order that the block are allocated.  b_list points to the next
-       block, not to be confused with b_next, which is next by control flow. */
+       block in this list, not to be confused with b_next, which is next by
+       control flow. */
     struct _PyCfgBasicblock_ *b_list;
     /* The label of this block if it is a jump target, -1 otherwise */
     _PyCfgJumpTargetLabel b_label;
@@ -91,12 +92,10 @@ void _PyCfgBuilder_Fini(_PyCfgBuilder *g
 
 _PyCfgInstruction* _PyCfg_BasicblockLastInstr(const _PyCfgBasicblock *b);
 int _PyCfg_OptimizeCodeUnit(_PyCfgBuilder *g, PyObject *consts, PyObject *const_cache,
-                            int code_flags, int nlocals, int nparams);
+                            int code_flags, int nlocals, int nparams, int firstlineno);
 int _PyCfg_Stackdepth(_PyCfgBasicblock *entryblock, int code_flags);
-void _PyCfg_ConvertExceptionHandlersToNops(_PyCfgBasicblock *entryblock);
-int _PyCfg_ResolveLineNumbers(_PyCfgBuilder *g, int firstlineno);
+void _PyCfg_ConvertPseudoOps(_PyCfgBasicblock *entryblock);
 int _PyCfg_ResolveJumps(_PyCfgBuilder *g);
-int _PyCfg_InstrSize(_PyCfgInstruction *instruction);
 
 
 static inline int
@@ -110,6 +109,10 @@ basicblock_nofallthrough(const _PyCfgBas
 #define BB_NO_FALLTHROUGH(B) (basicblock_nofallthrough(B))
 #define BB_HAS_FALLTHROUGH(B) (!basicblock_nofallthrough(B))
 
+PyCodeObject *
+_PyAssemble_MakeCodeObject(_PyCompile_CodeUnitMetadata *u, PyObject *const_cache,
+                           PyObject *consts, int maxdepth, _PyCompile_InstructionSequence *instrs,
+                           int nlocalsplus, int code_flags, PyObject *filename);
 
 #ifdef __cplusplus
 }
diff -pruN 3.12.0~a7-1/Include/internal/pycore_format.h 3.12.0~b1-1/Include/internal/pycore_format.h
--- 3.12.0~a7-1/Include/internal/pycore_format.h	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Include/internal/pycore_format.h	2023-05-22 12:07:36.000000000 +0000
@@ -14,14 +14,12 @@ extern "C" {
  * F_BLANK      ' '
  * F_ALT        '#'
  * F_ZERO       '0'
- * F_NO_NEG_0   'z'
  */
 #define F_LJUST (1<<0)
 #define F_SIGN  (1<<1)
 #define F_BLANK (1<<2)
 #define F_ALT   (1<<3)
 #define F_ZERO  (1<<4)
-#define F_NO_NEG_0 (1<<5)
 
 #ifdef __cplusplus
 }
diff -pruN 3.12.0~a7-1/Include/internal/pycore_frame.h 3.12.0~b1-1/Include/internal/pycore_frame.h
--- 3.12.0~a7-1/Include/internal/pycore_frame.h	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Include/internal/pycore_frame.h	2023-05-22 12:07:36.000000000 +0000
@@ -60,7 +60,13 @@ typedef struct _PyInterpreterFrame {
     // over, or (in the case of a newly-created frame) a totally invalid value:
     _Py_CODEUNIT *prev_instr;
     int stacktop;  /* Offset of TOS from localsplus  */
-    uint16_t yield_offset;
+    /* The return_offset determines where a `RETURN` should go in the caller,
+     * relative to `prev_instr`.
+     * It is only meaningful to the callee,
+     * so it needs to be set in any CALL (to a Python function)
+     * or SEND (to a coroutine or generator).
+     * If there is no callee, then it is meaningless. */
+    uint16_t return_offset;
     char owner;
     /* Locals and stack */
     PyObject *localsplus[1];
@@ -120,7 +126,7 @@ _PyFrame_Initialize(
     frame->stacktop = code->co_nlocalsplus;
     frame->frame_obj = NULL;
     frame->prev_instr = _PyCode_CODE(code) - 1;
-    frame->yield_offset = 0;
+    frame->return_offset = 0;
     frame->owner = FRAME_OWNED_BY_THREAD;
 
     for (int i = null_locals_from; i < code->co_nlocalsplus; i++) {
@@ -137,10 +143,16 @@ _PyFrame_GetLocalsArray(_PyInterpreterFr
     return frame->localsplus;
 }
 
+/* Fetches the stack pointer, and sets stacktop to -1.
+   Having stacktop <= 0 ensures that invalid
+   values are not visible to the cycle GC.
+   We choose -1 rather than 0 to assist debugging. */
 static inline PyObject**
 _PyFrame_GetStackPointer(_PyInterpreterFrame *frame)
 {
-    return frame->localsplus+frame->stacktop;
+    PyObject **sp = frame->localsplus + frame->stacktop;
+    frame->stacktop = -1;
+    return sp;
 }
 
 static inline void
@@ -252,8 +264,6 @@ _PyFrame_PushUnchecked(PyThreadState *ts
     return new_frame;
 }
 
-int _PyInterpreterFrame_GetLine(_PyInterpreterFrame *frame);
-
 static inline
 PyGenObject *_PyFrame_GetGenerator(_PyInterpreterFrame *frame)
 {
diff -pruN 3.12.0~a7-1/Include/internal/pycore_function.h 3.12.0~b1-1/Include/internal/pycore_function.h
--- 3.12.0~a7-1/Include/internal/pycore_function.h	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Include/internal/pycore_function.h	2023-05-22 12:07:36.000000000 +0000
@@ -17,6 +17,8 @@ struct _py_func_state {
 extern PyFunctionObject* _PyFunction_FromConstructor(PyFrameConstructor *constr);
 
 extern uint32_t _PyFunction_GetVersionForCurrentState(PyFunctionObject *func);
+extern PyObject *_Py_set_function_type_params(
+    PyThreadState* unused, PyObject *func, PyObject *type_params);
 
 #ifdef __cplusplus
 }
diff -pruN 3.12.0~a7-1/Include/internal/pycore_global_objects.h 3.12.0~b1-1/Include/internal/pycore_global_objects.h
--- 3.12.0~a7-1/Include/internal/pycore_global_objects.h	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Include/internal/pycore_global_objects.h	2023-05-22 12:07:36.000000000 +0000
@@ -68,6 +68,13 @@ struct _Py_interp_cached_objects {
     PyObject *type_slots_pname;
     pytype_slotdef *type_slots_ptrs[MAX_EQUIV];
 
+    /* TypeVar and related types */
+    PyTypeObject *generic_type;
+    PyTypeObject *typevar_type;
+    PyTypeObject *typevartuple_type;
+    PyTypeObject *paramspec_type;
+    PyTypeObject *paramspecargs_type;
+    PyTypeObject *paramspeckwargs_type;
 };
 
 #define _Py_INTERP_STATIC_OBJECT(interp, NAME) \
diff -pruN 3.12.0~a7-1/Include/internal/pycore_global_objects_fini_generated.h 3.12.0~b1-1/Include/internal/pycore_global_objects_fini_generated.h
--- 3.12.0~a7-1/Include/internal/pycore_global_objects_fini_generated.h	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Include/internal/pycore_global_objects_fini_generated.h	2023-05-22 12:07:36.000000000 +0000
@@ -8,15 +8,13 @@ extern "C" {
 #  error "this header requires Py_BUILD_CORE define"
 #endif
 
-#include "pycore_object.h"  // _PyObject_IMMORTAL_REFCNT
-
 #ifdef Py_DEBUG
 static inline void
 _PyStaticObject_CheckRefcnt(PyObject *obj) {
-    if (Py_REFCNT(obj) < _PyObject_IMMORTAL_REFCNT) {
+    if (Py_REFCNT(obj) < _Py_IMMORTAL_REFCNT) {
         _PyObject_ASSERT_FAILED_MSG(obj,
             "immortal object has less refcnt than expected "
-            "_PyObject_IMMORTAL_REFCNT");
+            "_Py_IMMORTAL_REFCNT");
     }
 }
 #endif
@@ -557,15 +555,19 @@ _PyStaticObjects_CheckRefcnt(PyInterpret
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(dbl_close_br));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(dbl_open_br));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(dbl_percent));
+    _PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(defaults));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(dot));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(dot_locals));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(empty));
+    _PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(generic_base));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(json_decoder));
+    _PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(kwdefaults));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(list_err));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(newline));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(open_br));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(percent));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(shim_name));
+    _PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(type_params));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_STR(utf_8));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(CANCELLED));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(FINISHED));
@@ -595,6 +597,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpret
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__await__));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__bases__));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__bool__));
+    _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__buffer__));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__build_class__));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__builtins__));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__bytes__));
@@ -603,6 +606,8 @@ _PyStaticObjects_CheckRefcnt(PyInterpret
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__class__));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__class_getitem__));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__classcell__));
+    _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__classdict__));
+    _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__classdictcell__));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__complex__));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__contains__));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__copy__));
@@ -694,6 +699,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpret
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__rdivmod__));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__reduce__));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__reduce_ex__));
+    _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__release_buffer__));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__repr__));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__reversed__));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__rfloordiv__));
@@ -724,6 +730,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpret
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__subclasshook__));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__truediv__));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__trunc__));
+    _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__type_params__));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__typing_is_unpacked_typevartuple__));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__typing_prepare_subst__));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__typing_subst__));
@@ -779,8 +786,11 @@ _PyStaticObjects_CheckRefcnt(PyInterpret
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(after_in_child));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(after_in_parent));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(aggregate_class));
+    _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(alias));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(append));
+    _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(arg));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(argdefs));
+    _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(args));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(arguments));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(argv));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(as_integer_ratio));
@@ -795,6 +805,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpret
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(big));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(binary_form));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(block));
+    _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(bound));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(buffer));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(buffer_callback));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(buffer_size));
@@ -847,13 +858,16 @@ _PyStaticObjects_CheckRefcnt(PyInterpret
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(code));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(command));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(comment_factory));
+    _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(compile_mode));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(consts));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(context));
+    _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(contravariant));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(cookie));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(copy));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(copyreg));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(coro));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(count));
+    _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(covariant));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(cwd));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(d));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(data));
@@ -884,6 +898,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpret
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(dst_dir_fd));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(duration));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(e));
+    _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(eager_start));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(effective_ids));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(element_factory));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(encode));
@@ -892,6 +907,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpret
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(end_lineno));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(end_offset));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(endpos));
+    _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(entrypoint));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(env));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(errors));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(event));
@@ -902,6 +918,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpret
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(exception));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(exp));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(extend));
+    _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(extra_tokens));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(facility));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(factory));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(false));
@@ -961,6 +978,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpret
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(incoming));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(indexgroup));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(inf));
+    _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(infer_variance));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(inheritable));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(initial));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(initial_bytes));
@@ -973,6 +991,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpret
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(instructions));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(intern));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(intersection));
+    _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(is_running));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(isatty));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(isinstance));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(isoformat));
@@ -1028,6 +1047,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpret
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(memlimit));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(message));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(metaclass));
+    _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(metadata));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(method));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(mod));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(mode));
@@ -1052,6 +1072,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpret
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(newline));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(newlines));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(next));
+    _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(nlocals));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(node_depth));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(node_offset));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(ns));
@@ -1075,6 +1096,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpret
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(optimize));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(options));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(order));
+    _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(origin));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(out_fd));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(outgoing));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(overlapped));
@@ -1120,6 +1142,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpret
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(reducer_override));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(registry));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(rel_tol));
+    _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(release));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(reload));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(repl));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(replace));
@@ -1171,6 +1194,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpret
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(stdin));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(stdout));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(step));
+    _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(steps));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(store_name));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(strategy));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(strftime));
@@ -1207,6 +1231,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpret
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(twice));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(txt));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(type));
+    _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(type_params));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(tz));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(tzname));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(uid));
diff -pruN 3.12.0~a7-1/Include/internal/pycore_global_strings.h 3.12.0~b1-1/Include/internal/pycore_global_strings.h
--- 3.12.0~a7-1/Include/internal/pycore_global_strings.h	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Include/internal/pycore_global_strings.h	2023-05-22 12:07:36.000000000 +0000
@@ -40,15 +40,19 @@ struct _Py_global_strings {
         STRUCT_FOR_STR(dbl_close_br, "}}")
         STRUCT_FOR_STR(dbl_open_br, "{{")
         STRUCT_FOR_STR(dbl_percent, "%%")
+        STRUCT_FOR_STR(defaults, ".defaults")
         STRUCT_FOR_STR(dot, ".")
         STRUCT_FOR_STR(dot_locals, ".<locals>")
         STRUCT_FOR_STR(empty, "")
+        STRUCT_FOR_STR(generic_base, ".generic_base")
         STRUCT_FOR_STR(json_decoder, "json.decoder")
+        STRUCT_FOR_STR(kwdefaults, ".kwdefaults")
         STRUCT_FOR_STR(list_err, "list index out of range")
         STRUCT_FOR_STR(newline, "\n")
         STRUCT_FOR_STR(open_br, "{")
         STRUCT_FOR_STR(percent, "%")
         STRUCT_FOR_STR(shim_name, "<shim>")
+        STRUCT_FOR_STR(type_params, ".type_params")
         STRUCT_FOR_STR(utf_8, "utf-8")
     } literals;
 
@@ -81,6 +85,7 @@ struct _Py_global_strings {
         STRUCT_FOR_ID(__await__)
         STRUCT_FOR_ID(__bases__)
         STRUCT_FOR_ID(__bool__)
+        STRUCT_FOR_ID(__buffer__)
         STRUCT_FOR_ID(__build_class__)
         STRUCT_FOR_ID(__builtins__)
         STRUCT_FOR_ID(__bytes__)
@@ -89,6 +94,8 @@ struct _Py_global_strings {
         STRUCT_FOR_ID(__class__)
         STRUCT_FOR_ID(__class_getitem__)
         STRUCT_FOR_ID(__classcell__)
+        STRUCT_FOR_ID(__classdict__)
+        STRUCT_FOR_ID(__classdictcell__)
         STRUCT_FOR_ID(__complex__)
         STRUCT_FOR_ID(__contains__)
         STRUCT_FOR_ID(__copy__)
@@ -180,6 +187,7 @@ struct _Py_global_strings {
         STRUCT_FOR_ID(__rdivmod__)
         STRUCT_FOR_ID(__reduce__)
         STRUCT_FOR_ID(__reduce_ex__)
+        STRUCT_FOR_ID(__release_buffer__)
         STRUCT_FOR_ID(__repr__)
         STRUCT_FOR_ID(__reversed__)
         STRUCT_FOR_ID(__rfloordiv__)
@@ -210,6 +218,7 @@ struct _Py_global_strings {
         STRUCT_FOR_ID(__subclasshook__)
         STRUCT_FOR_ID(__truediv__)
         STRUCT_FOR_ID(__trunc__)
+        STRUCT_FOR_ID(__type_params__)
         STRUCT_FOR_ID(__typing_is_unpacked_typevartuple__)
         STRUCT_FOR_ID(__typing_prepare_subst__)
         STRUCT_FOR_ID(__typing_subst__)
@@ -265,8 +274,11 @@ struct _Py_global_strings {
         STRUCT_FOR_ID(after_in_child)
         STRUCT_FOR_ID(after_in_parent)
         STRUCT_FOR_ID(aggregate_class)
+        STRUCT_FOR_ID(alias)
         STRUCT_FOR_ID(append)
+        STRUCT_FOR_ID(arg)
         STRUCT_FOR_ID(argdefs)
+        STRUCT_FOR_ID(args)
         STRUCT_FOR_ID(arguments)
         STRUCT_FOR_ID(argv)
         STRUCT_FOR_ID(as_integer_ratio)
@@ -281,6 +293,7 @@ struct _Py_global_strings {
         STRUCT_FOR_ID(big)
         STRUCT_FOR_ID(binary_form)
         STRUCT_FOR_ID(block)
+        STRUCT_FOR_ID(bound)
         STRUCT_FOR_ID(buffer)
         STRUCT_FOR_ID(buffer_callback)
         STRUCT_FOR_ID(buffer_size)
@@ -333,13 +346,16 @@ struct _Py_global_strings {
         STRUCT_FOR_ID(code)
         STRUCT_FOR_ID(command)
         STRUCT_FOR_ID(comment_factory)
+        STRUCT_FOR_ID(compile_mode)
         STRUCT_FOR_ID(consts)
         STRUCT_FOR_ID(context)
+        STRUCT_FOR_ID(contravariant)
         STRUCT_FOR_ID(cookie)
         STRUCT_FOR_ID(copy)
         STRUCT_FOR_ID(copyreg)
         STRUCT_FOR_ID(coro)
         STRUCT_FOR_ID(count)
+        STRUCT_FOR_ID(covariant)
         STRUCT_FOR_ID(cwd)
         STRUCT_FOR_ID(d)
         STRUCT_FOR_ID(data)
@@ -370,6 +386,7 @@ struct _Py_global_strings {
         STRUCT_FOR_ID(dst_dir_fd)
         STRUCT_FOR_ID(duration)
         STRUCT_FOR_ID(e)
+        STRUCT_FOR_ID(eager_start)
         STRUCT_FOR_ID(effective_ids)
         STRUCT_FOR_ID(element_factory)
         STRUCT_FOR_ID(encode)
@@ -378,6 +395,7 @@ struct _Py_global_strings {
         STRUCT_FOR_ID(end_lineno)
         STRUCT_FOR_ID(end_offset)
         STRUCT_FOR_ID(endpos)
+        STRUCT_FOR_ID(entrypoint)
         STRUCT_FOR_ID(env)
         STRUCT_FOR_ID(errors)
         STRUCT_FOR_ID(event)
@@ -388,6 +406,7 @@ struct _Py_global_strings {
         STRUCT_FOR_ID(exception)
         STRUCT_FOR_ID(exp)
         STRUCT_FOR_ID(extend)
+        STRUCT_FOR_ID(extra_tokens)
         STRUCT_FOR_ID(facility)
         STRUCT_FOR_ID(factory)
         STRUCT_FOR_ID(false)
@@ -447,6 +466,7 @@ struct _Py_global_strings {
         STRUCT_FOR_ID(incoming)
         STRUCT_FOR_ID(indexgroup)
         STRUCT_FOR_ID(inf)
+        STRUCT_FOR_ID(infer_variance)
         STRUCT_FOR_ID(inheritable)
         STRUCT_FOR_ID(initial)
         STRUCT_FOR_ID(initial_bytes)
@@ -459,6 +479,7 @@ struct _Py_global_strings {
         STRUCT_FOR_ID(instructions)
         STRUCT_FOR_ID(intern)
         STRUCT_FOR_ID(intersection)
+        STRUCT_FOR_ID(is_running)
         STRUCT_FOR_ID(isatty)
         STRUCT_FOR_ID(isinstance)
         STRUCT_FOR_ID(isoformat)
@@ -514,6 +535,7 @@ struct _Py_global_strings {
         STRUCT_FOR_ID(memlimit)
         STRUCT_FOR_ID(message)
         STRUCT_FOR_ID(metaclass)
+        STRUCT_FOR_ID(metadata)
         STRUCT_FOR_ID(method)
         STRUCT_FOR_ID(mod)
         STRUCT_FOR_ID(mode)
@@ -538,6 +560,7 @@ struct _Py_global_strings {
         STRUCT_FOR_ID(newline)
         STRUCT_FOR_ID(newlines)
         STRUCT_FOR_ID(next)
+        STRUCT_FOR_ID(nlocals)
         STRUCT_FOR_ID(node_depth)
         STRUCT_FOR_ID(node_offset)
         STRUCT_FOR_ID(ns)
@@ -561,6 +584,7 @@ struct _Py_global_strings {
         STRUCT_FOR_ID(optimize)
         STRUCT_FOR_ID(options)
         STRUCT_FOR_ID(order)
+        STRUCT_FOR_ID(origin)
         STRUCT_FOR_ID(out_fd)
         STRUCT_FOR_ID(outgoing)
         STRUCT_FOR_ID(overlapped)
@@ -606,6 +630,7 @@ struct _Py_global_strings {
         STRUCT_FOR_ID(reducer_override)
         STRUCT_FOR_ID(registry)
         STRUCT_FOR_ID(rel_tol)
+        STRUCT_FOR_ID(release)
         STRUCT_FOR_ID(reload)
         STRUCT_FOR_ID(repl)
         STRUCT_FOR_ID(replace)
@@ -657,6 +682,7 @@ struct _Py_global_strings {
         STRUCT_FOR_ID(stdin)
         STRUCT_FOR_ID(stdout)
         STRUCT_FOR_ID(step)
+        STRUCT_FOR_ID(steps)
         STRUCT_FOR_ID(store_name)
         STRUCT_FOR_ID(strategy)
         STRUCT_FOR_ID(strftime)
@@ -693,6 +719,7 @@ struct _Py_global_strings {
         STRUCT_FOR_ID(twice)
         STRUCT_FOR_ID(txt)
         STRUCT_FOR_ID(type)
+        STRUCT_FOR_ID(type_params)
         STRUCT_FOR_ID(tz)
         STRUCT_FOR_ID(tzname)
         STRUCT_FOR_ID(uid)
diff -pruN 3.12.0~a7-1/Include/internal/pycore_import.h 3.12.0~b1-1/Include/internal/pycore_import.h
--- 3.12.0~a7-1/Include/internal/pycore_import.h	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Include/internal/pycore_import.h	2023-05-22 12:07:36.000000000 +0000
@@ -19,6 +19,8 @@ struct _import_runtime_state {
            used exclusively for when the extensions dict is access/modified
            from an arbitrary thread. */
         PyThreadState main_tstate;
+        /* A lock to guard the dict. */
+        PyThread_type_lock mutex;
         /* A dict mapping (filename, name) to PyModuleDef for modules.
            Only legacy (single-phase init) extension modules are added
            and only if they support multiple initialization (m_size >- 0)
diff -pruN 3.12.0~a7-1/Include/internal/pycore_instruments.h 3.12.0~b1-1/Include/internal/pycore_instruments.h
--- 3.12.0~a7-1/Include/internal/pycore_instruments.h	1970-01-01 00:00:00.000000000 +0000
+++ 3.12.0~b1-1/Include/internal/pycore_instruments.h	2023-05-22 12:07:36.000000000 +0000
@@ -0,0 +1,108 @@
+
+#ifndef Py_INTERNAL_INSTRUMENT_H
+#define Py_INTERNAL_INSTRUMENT_H
+
+
+#include "pycore_bitutils.h"      // _Py_popcount32
+#include "pycore_frame.h"
+
+#include "cpython/code.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define PY_MONITORING_TOOL_IDS 8
+
+/* Local events.
+ * These require bytecode instrumentation */
+
+#define PY_MONITORING_EVENT_PY_START 0
+#define PY_MONITORING_EVENT_PY_RESUME 1
+#define PY_MONITORING_EVENT_PY_RETURN 2
+#define PY_MONITORING_EVENT_PY_YIELD 3
+#define PY_MONITORING_EVENT_CALL 4
+#define PY_MONITORING_EVENT_LINE 5
+#define PY_MONITORING_EVENT_INSTRUCTION 6
+#define PY_MONITORING_EVENT_JUMP 7
+#define PY_MONITORING_EVENT_BRANCH 8
+#define PY_MONITORING_EVENT_STOP_ITERATION 9
+
+#define PY_MONITORING_INSTRUMENTED_EVENTS 10
+
+/* Other events, mainly exceptions */
+
+#define PY_MONITORING_EVENT_RAISE 10
+#define PY_MONITORING_EVENT_EXCEPTION_HANDLED 11
+#define PY_MONITORING_EVENT_PY_UNWIND 12
+#define PY_MONITORING_EVENT_PY_THROW 13
+
+
+/* Ancilliary events */
+
+#define PY_MONITORING_EVENT_C_RETURN 14
+#define PY_MONITORING_EVENT_C_RAISE 15
+
+
+typedef uint32_t _PyMonitoringEventSet;
+
+/* Tool IDs */
+
+/* These are defined in PEP 669 for convenience to avoid clashes */
+#define PY_MONITORING_DEBUGGER_ID 0
+#define PY_MONITORING_COVERAGE_ID 1
+#define PY_MONITORING_PROFILER_ID 2
+#define PY_MONITORING_OPTIMIZER_ID 5
+
+/* Internal IDs used to suuport sys.setprofile() and sys.settrace() */
+#define PY_MONITORING_SYS_PROFILE_ID 6
+#define PY_MONITORING_SYS_TRACE_ID 7
+
+
+PyObject *_PyMonitoring_RegisterCallback(int tool_id, int event_id, PyObject *obj);
+
+int _PyMonitoring_SetEvents(int tool_id, _PyMonitoringEventSet events);
+
+extern int
+_Py_call_instrumentation(PyThreadState *tstate, int event,
+    _PyInterpreterFrame *frame, _Py_CODEUNIT *instr);
+
+extern int
+_Py_call_instrumentation_line(PyThreadState *tstate, _PyInterpreterFrame* frame,
+                              _Py_CODEUNIT *instr, _Py_CODEUNIT *prev);
+
+extern int
+_Py_call_instrumentation_instruction(
+    PyThreadState *tstate, _PyInterpreterFrame* frame, _Py_CODEUNIT *instr);
+
+_Py_CODEUNIT *
+_Py_call_instrumentation_jump(
+    PyThreadState *tstate, int event,
+    _PyInterpreterFrame *frame, _Py_CODEUNIT *instr, _Py_CODEUNIT *target);
+
+extern int
+_Py_call_instrumentation_arg(PyThreadState *tstate, int event,
+    _PyInterpreterFrame *frame, _Py_CODEUNIT *instr, PyObject *arg);
+
+extern int
+_Py_call_instrumentation_2args(PyThreadState *tstate, int event,
+    _PyInterpreterFrame *frame, _Py_CODEUNIT *instr, PyObject *arg0, PyObject *arg1);
+
+extern void
+_Py_call_instrumentation_exc0(PyThreadState *tstate, int event,
+    _PyInterpreterFrame *frame, _Py_CODEUNIT *instr);
+
+extern void
+_Py_call_instrumentation_exc2(PyThreadState *tstate, int event,
+    _PyInterpreterFrame *frame, _Py_CODEUNIT *instr, PyObject *arg0, PyObject *arg1);
+
+extern int
+_Py_Instrumentation_GetLine(PyCodeObject *code, int index);
+
+extern PyObject _PyInstrumentation_MISSING;
+extern PyObject _PyInstrumentation_DISABLE;
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !Py_INTERNAL_INSTRUMENT_H */
diff -pruN 3.12.0~a7-1/Include/internal/pycore_interp.h 3.12.0~b1-1/Include/internal/pycore_interp.h
--- 3.12.0~a7-1/Include/internal/pycore_interp.h	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Include/internal/pycore_interp.h	2023-05-22 12:07:36.000000000 +0000
@@ -10,8 +10,9 @@ extern "C" {
 
 #include <stdbool.h>
 
-#include "pycore_atomic.h"        // _Py_atomic_address
 #include "pycore_ast_state.h"     // struct ast_state
+#include "pycore_atexit.h"        // struct atexit_state
+#include "pycore_atomic.h"        // _Py_atomic_address
 #include "pycore_ceval_state.h"   // struct _ceval_state
 #include "pycore_code.h"          // struct callable_cache
 #include "pycore_context.h"       // struct _Py_context_state
@@ -22,35 +23,22 @@ extern "C" {
 #include "pycore_function.h"      // FUNC_MAX_WATCHERS
 #include "pycore_genobject.h"     // struct _Py_async_gen_state
 #include "pycore_gc.h"            // struct _gc_runtime_state
+#include "pycore_global_objects.h"  // struct _Py_interp_static_objects
 #include "pycore_import.h"        // struct _import_state
+#include "pycore_instruments.h"   // PY_MONITORING_EVENTS
 #include "pycore_list.h"          // struct _Py_list_state
-#include "pycore_global_objects.h"  // struct _Py_interp_static_objects
 #include "pycore_object_state.h"   // struct _py_object_state
+#include "pycore_obmalloc.h"      // struct obmalloc_state
 #include "pycore_tuple.h"         // struct _Py_tuple_state
 #include "pycore_typeobject.h"    // struct type_cache
 #include "pycore_unicodeobject.h" // struct _Py_unicode_state
 #include "pycore_warnings.h"      // struct _warnings_runtime_state
 
 
-// atexit state
-typedef struct {
-    PyObject *func;
-    PyObject *args;
-    PyObject *kwargs;
-} atexit_callback;
-
-struct atexit_state {
-    atexit_callback **callbacks;
-    int ncallbacks;
-    int callback_len;
-};
-
-
 struct _Py_long_state {
     int max_str_digits;
 };
 
-
 /* interpreter state */
 
 /* PyInterpreterState holds the global state for one of the runtime's
@@ -60,8 +48,12 @@ struct _Py_long_state {
    */
 struct _is {
 
+    struct _ceval_state ceval;
     PyInterpreterState *next;
 
+    uint64_t monitoring_version;
+    uint64_t last_restart_version;
+
     struct pythreads {
         uint64_t next_unique_id;
         /* The linked list of threads, newest first. */
@@ -92,7 +84,15 @@ struct _is {
     int _initialized;
     int finalizing;
 
-    struct _ceval_state ceval;
+    /* Set by Py_EndInterpreter().
+
+       Use _PyInterpreterState_GetFinalizing()
+       and _PyInterpreterState_SetFinalizing()
+       to access it, don't access it directly. */
+    _Py_atomic_address _finalizing;
+
+    struct _obmalloc_state obmalloc;
+
     struct _gc_runtime_state gc;
 
     struct _import_state imports;
@@ -161,6 +161,15 @@ struct _is {
     struct callable_cache callable_cache;
     PyCodeObject *interpreter_trampoline;
 
+    _Py_Monitors monitors;
+    bool f_opcode_trace_set;
+    bool sys_profile_initialized;
+    bool sys_trace_initialized;
+    Py_ssize_t sys_profiling_threads; /* Count of threads with c_profilefunc set */
+    Py_ssize_t sys_tracing_threads; /* Count of threads with c_tracefunc set */
+    PyObject *monitoring_callables[PY_MONITORING_TOOL_IDS][PY_MONITORING_EVENTS];
+    PyObject *monitoring_tool_names[PY_MONITORING_TOOL_IDS];
+
     struct _Py_interp_cached_objects cached_objects;
     struct _Py_interp_static_objects static_objects;
 
@@ -176,6 +185,9 @@ struct _is {
        basis.  Also see _PyRuntimeState regarding the various mutex fields.
        */
 
+    /* The per-interpreter GIL, which might not be used. */
+    struct _gil_runtime_state _gil;
+
     /* the initial PyInterpreterState.threads.head */
     PyThreadState _initial_thread;
 };
@@ -186,6 +198,17 @@ struct _is {
 extern void _PyInterpreterState_Clear(PyThreadState *tstate);
 
 
+static inline PyThreadState*
+_PyInterpreterState_GetFinalizing(PyInterpreterState *interp) {
+    return (PyThreadState*)_Py_atomic_load_relaxed(&interp->_finalizing);
+}
+
+static inline void
+_PyInterpreterState_SetFinalizing(PyInterpreterState *interp, PyThreadState *tstate) {
+    _Py_atomic_store_relaxed(&interp->_finalizing, (uintptr_t)tstate);
+}
+
+
 /* cross-interpreter data registry */
 
 /* For now we use a global registry of shareable classes.  An
diff -pruN 3.12.0~a7-1/Include/internal/pycore_intrinsics.h 3.12.0~b1-1/Include/internal/pycore_intrinsics.h
--- 3.12.0~a7-1/Include/internal/pycore_intrinsics.h	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Include/internal/pycore_intrinsics.h	2023-05-22 12:07:36.000000000 +0000
@@ -1,26 +1,32 @@
+// Auto-generated by Tools/build/generate_opcode_h.py from Lib/opcode.py
 
 /* Unary Functions: */
+#define INTRINSIC_1_INVALID                      0
+#define INTRINSIC_PRINT                          1
+#define INTRINSIC_IMPORT_STAR                    2
+#define INTRINSIC_STOPITERATION_ERROR            3
+#define INTRINSIC_ASYNC_GEN_WRAP                 4
+#define INTRINSIC_UNARY_POSITIVE                 5
+#define INTRINSIC_LIST_TO_TUPLE                  6
+#define INTRINSIC_TYPEVAR                        7
+#define INTRINSIC_PARAMSPEC                      8
+#define INTRINSIC_TYPEVARTUPLE                   9
+#define INTRINSIC_SUBSCRIPT_GENERIC             10
+#define INTRINSIC_TYPEALIAS                     11
 
-#define INTRINSIC_PRINT 1
-#define INTRINSIC_IMPORT_STAR 2
-#define INTRINSIC_STOPITERATION_ERROR 3
-#define INTRINSIC_ASYNC_GEN_WRAP 4
-#define INTRINSIC_UNARY_POSITIVE 5
-#define INTRINSIC_LIST_TO_TUPLE 6
-
-#define MAX_INTRINSIC_1 6
+#define MAX_INTRINSIC_1                         11
 
 
 /* Binary Functions: */
+#define INTRINSIC_2_INVALID                      0
+#define INTRINSIC_PREP_RERAISE_STAR              1
+#define INTRINSIC_TYPEVAR_WITH_BOUND             2
+#define INTRINSIC_TYPEVAR_WITH_CONSTRAINTS       3
+#define INTRINSIC_SET_FUNCTION_TYPE_PARAMS       4
 
-#define INTRINSIC_PREP_RERAISE_STAR 1
-
-#define MAX_INTRINSIC_2 1
-
+#define MAX_INTRINSIC_2                          4
 
 typedef PyObject *(*instrinsic_func1)(PyThreadState* tstate, PyObject *value);
 typedef PyObject *(*instrinsic_func2)(PyThreadState* tstate, PyObject *value1, PyObject *value2);
-
 extern const instrinsic_func1 _PyIntrinsics_UnaryFunctions[];
 extern const instrinsic_func2 _PyIntrinsics_BinaryFunctions[];
-
diff -pruN 3.12.0~a7-1/Include/internal/pycore_long.h 3.12.0~b1-1/Include/internal/pycore_long.h
--- 3.12.0~a7-1/Include/internal/pycore_long.h	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Include/internal/pycore_long.h	2023-05-22 12:07:36.000000000 +0000
@@ -118,6 +118,21 @@ PyAPI_FUNC(char*) _PyLong_FormatBytesWri
 #define SIGN_NEGATIVE 2
 #define NON_SIZE_BITS 3
 
+/* The functions _PyLong_IsCompact and _PyLong_CompactValue are defined
+ * in Include/cpython/longobject.h, since they need to be inline.
+ *
+ * "Compact" values have at least one bit to spare,
+ * so that addition and subtraction can be performed on the values
+ * without risk of overflow.
+ *
+ * The inline functions need tag bits.
+ * For readability, rather than do `#define SIGN_MASK _PyLong_SIGN_MASK`
+ * we define them to the numbers in both places and then assert that
+ * they're the same.
+ */
+static_assert(SIGN_MASK == _PyLong_SIGN_MASK, "SIGN_MASK does not match _PyLong_SIGN_MASK");
+static_assert(NON_SIZE_BITS == _PyLong_NON_SIZE_BITS, "NON_SIZE_BITS does not match _PyLong_NON_SIZE_BITS");
+
 /* All *compact" values are guaranteed to fit into
  * a Py_ssize_t with at least one bit to spare.
  * In other words, for 64 bit machines, compact
@@ -131,11 +146,6 @@ _PyLong_IsNonNegativeCompact(const PyLon
     return op->long_value.lv_tag <= (1 << NON_SIZE_BITS);
 }
 
-static inline int
-_PyLong_IsCompact(const PyLongObject* op) {
-    assert(PyLong_Check(op));
-    return op->long_value.lv_tag < (2 << NON_SIZE_BITS);
-}
 
 static inline int
 _PyLong_BothAreCompact(const PyLongObject* a, const PyLongObject* b) {
@@ -144,21 +154,6 @@ _PyLong_BothAreCompact(const PyLongObjec
     return (a->long_value.lv_tag | b->long_value.lv_tag) < (2 << NON_SIZE_BITS);
 }
 
-/* Returns a *compact* value, iff `_PyLong_IsCompact` is true for `op`.
- *
- * "Compact" values have at least one bit to spare,
- * so that addition and subtraction can be performed on the values
- * without risk of overflow.
- */
-static inline Py_ssize_t
-_PyLong_CompactValue(const PyLongObject *op)
-{
-    assert(PyLong_Check(op));
-    assert(_PyLong_IsCompact(op));
-    Py_ssize_t sign = 1 - (op->long_value.lv_tag & SIGN_MASK);
-    return sign * (Py_ssize_t)op->long_value.ob_digit[0];
-}
-
 static inline bool
 _PyLong_IsZero(const PyLongObject *op)
 {
@@ -245,7 +240,7 @@ _PyLong_FlipSign(PyLongObject *op) {
 
 #define _PyLong_DIGIT_INIT(val) \
     { \
-        .ob_base = _PyObject_IMMORTAL_INIT(&PyLong_Type), \
+        .ob_base = _PyObject_HEAD_INIT(&PyLong_Type) \
         .long_value  = { \
             .lv_tag = TAG_FROM_SIGN_AND_SIZE( \
                 (val) == 0 ? 0 : ((val) < 0 ? -1 : 1), \
diff -pruN 3.12.0~a7-1/Include/internal/pycore_memoryobject.h 3.12.0~b1-1/Include/internal/pycore_memoryobject.h
--- 3.12.0~a7-1/Include/internal/pycore_memoryobject.h	1970-01-01 00:00:00.000000000 +0000
+++ 3.12.0~b1-1/Include/internal/pycore_memoryobject.h	2023-05-22 12:07:36.000000000 +0000
@@ -0,0 +1,18 @@
+#ifndef Py_INTERNAL_MEMORYOBJECT_H
+#define Py_INTERNAL_MEMORYOBJECT_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef Py_BUILD_CORE
+#  error "this header requires Py_BUILD_CORE define"
+#endif
+
+PyObject *
+_PyMemoryView_FromBufferProc(PyObject *v, int flags,
+                             getbufferproc bufferproc);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !Py_INTERNAL_MEMORYOBJECT_H */
diff -pruN 3.12.0~a7-1/Include/internal/pycore_moduleobject.h 3.12.0~b1-1/Include/internal/pycore_moduleobject.h
--- 3.12.0~a7-1/Include/internal/pycore_moduleobject.h	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Include/internal/pycore_moduleobject.h	2023-05-22 12:07:36.000000000 +0000
@@ -36,6 +36,9 @@ static inline PyObject* _PyModule_GetDic
     return dict;
 }
 
+PyObject* _Py_module_getattro_impl(PyModuleObject *m, PyObject *name, int suppress);
+PyObject* _Py_module_getattro(PyModuleObject *m, PyObject *name);
+
 #ifdef __cplusplus
 }
 #endif
diff -pruN 3.12.0~a7-1/Include/internal/pycore_object.h 3.12.0~b1-1/Include/internal/pycore_object.h
--- 3.12.0~a7-1/Include/internal/pycore_object.h	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Include/internal/pycore_object.h	2023-05-22 12:07:36.000000000 +0000
@@ -14,21 +14,25 @@ extern "C" {
 #include "pycore_pystate.h"       // _PyInterpreterState_GET()
 #include "pycore_runtime.h"       // _PyRuntime
 
-/* This value provides *effective* immortality, meaning the object should never
-    be deallocated (until runtime finalization).  See PEP 683 for more details about
-    immortality, as well as a proposed mechanism for proper immortality. */
-#define _PyObject_IMMORTAL_REFCNT 999999999
-
-#define _PyObject_IMMORTAL_INIT(type) \
-    { \
-        .ob_refcnt = _PyObject_IMMORTAL_REFCNT, \
-        .ob_type = (type), \
-    }
-#define _PyVarObject_IMMORTAL_INIT(type, size) \
-    { \
-        .ob_base = _PyObject_IMMORTAL_INIT(type), \
-        .ob_size = size, \
-    }
+/* We need to maintain an internal copy of Py{Var}Object_HEAD_INIT to avoid
+   designated initializer conflicts in C++20. If we use the deinition in
+   object.h, we will be mixing designated and non-designated initializers in
+   pycore objects which is forbiddent in C++20. However, if we then use
+   designated initializers in object.h then Extensions without designated break.
+   Furthermore, we can't use designated initializers in Extensions since these
+   are not supported pre-C++20. Thus, keeping an internal copy here is the most
+   backwards compatible solution */
+#define _PyObject_HEAD_INIT(type)         \
+    {                                     \
+        _PyObject_EXTRA_INIT              \
+        .ob_refcnt = _Py_IMMORTAL_REFCNT, \
+        .ob_type = (type)                 \
+    },
+#define _PyVarObject_HEAD_INIT(type, size)    \
+    {                                         \
+        .ob_base = _PyObject_HEAD_INIT(type)  \
+        .ob_size = size                       \
+    },
 
 PyAPI_FUNC(void) _Py_NO_RETURN _Py_FatalRefcountErrorFunc(
     const char *func,
@@ -54,6 +58,9 @@ extern void _Py_DecRefTotal(PyInterprete
 // Increment reference count by n
 static inline void _Py_RefcntAdd(PyObject* op, Py_ssize_t n)
 {
+    if (_Py_IsImmortal(op)) {
+        return;
+    }
 #ifdef Py_REF_DEBUG
     _Py_AddRefTotal(_PyInterpreterState_GET(), n);
 #endif
@@ -61,9 +68,20 @@ static inline void _Py_RefcntAdd(PyObjec
 }
 #define _Py_RefcntAdd(op, n) _Py_RefcntAdd(_PyObject_CAST(op), n)
 
+static inline void _Py_SetImmortal(PyObject *op)
+{
+    if (op) {
+        op->ob_refcnt = _Py_IMMORTAL_REFCNT;
+    }
+}
+#define _Py_SetImmortal(op) _Py_SetImmortal(_PyObject_CAST(op))
+
 static inline void
 _Py_DECREF_SPECIALIZED(PyObject *op, const destructor destruct)
 {
+    if (_Py_IsImmortal(op)) {
+        return;
+    }
     _Py_DECREF_STAT_INC();
 #ifdef Py_REF_DEBUG
     _Py_DEC_REFTOTAL(_PyInterpreterState_GET());
@@ -82,6 +100,9 @@ _Py_DECREF_SPECIALIZED(PyObject *op, con
 static inline void
 _Py_DECREF_NO_DEALLOC(PyObject *op)
 {
+    if (_Py_IsImmortal(op)) {
+        return;
+    }
     _Py_DECREF_STAT_INC();
 #ifdef Py_REF_DEBUG
     _Py_DEC_REFTOTAL(_PyInterpreterState_GET());
@@ -254,8 +275,9 @@ _PyObject_GET_WEAKREFS_LISTPTR(PyObject
 {
     if (PyType_Check(op) &&
             ((PyTypeObject *)op)->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN) {
+        PyInterpreterState *interp = _PyInterpreterState_GET();
         static_builtin_state *state = _PyStaticType_GetState(
-                                                        (PyTypeObject *)op);
+                                                interp, (PyTypeObject *)op);
         return _PyStaticType_GET_WEAKREFS_LISTPTR(state);
     }
     // Essentially _PyObject_GET_WEAKREFS_LISTPTR_FROM_OFFSET():
@@ -312,10 +334,6 @@ extern int _Py_CheckSlotResult(
     const char *slot_name,
     int success);
 
-// PyType_Ready() must be called if _PyType_IsReady() is false.
-// See also the Py_TPFLAGS_READY flag.
-#define _PyType_IsReady(type) ((type)->tp_dict != NULL)
-
 // Test if a type supports weak references
 static inline int _PyType_SUPPORTS_WEAKREFS(PyTypeObject *type) {
     return (type->tp_weaklistoffset != 0);
@@ -373,14 +391,6 @@ _PyDictOrValues_SetValues(PyDictOrValues
 extern PyObject ** _PyObject_ComputedDictPointer(PyObject *);
 extern void _PyObject_FreeInstanceAttributes(PyObject *obj);
 extern int _PyObject_IsInstanceDictEmpty(PyObject *);
-extern int _PyType_HasSubclasses(PyTypeObject *);
-extern PyObject* _PyType_GetSubclasses(PyTypeObject *);
-extern PyObject* _PyObject_GenericTryGetAttr(PyObject *, PyObject *);
-
-// Access macro to the members which are floating "behind" the object
-static inline PyMemberDef* _PyHeapType_GET_MEMBERS(PyHeapTypeObject *etype) {
-    return (PyMemberDef*)((char*)etype + Py_TYPE(etype)->tp_basicsize);
-}
 
 PyAPI_FUNC(PyObject *) _PyObject_LookupSpecial(PyObject *, PyObject *);
 
diff -pruN 3.12.0~a7-1/Include/internal/pycore_obmalloc.h 3.12.0~b1-1/Include/internal/pycore_obmalloc.h
--- 3.12.0~a7-1/Include/internal/pycore_obmalloc.h	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Include/internal/pycore_obmalloc.h	2023-05-22 12:07:36.000000000 +0000
@@ -657,8 +657,12 @@ struct _obmalloc_usage {
 #endif /* WITH_PYMALLOC_RADIX_TREE */
 
 
-struct _obmalloc_state {
+struct _obmalloc_global_state {
     int dump_debug_stats;
+    Py_ssize_t interpreter_leaks;
+};
+
+struct _obmalloc_state {
     struct _obmalloc_pools pools;
     struct _obmalloc_mgmt mgmt;
     struct _obmalloc_usage usage;
@@ -675,7 +679,11 @@ void _PyObject_VirtualFree(void *, size_
 
 
 /* This function returns the number of allocated memory blocks, regardless of size */
-PyAPI_FUNC(Py_ssize_t) _Py_GetAllocatedBlocks(void);
+extern Py_ssize_t _Py_GetGlobalAllocatedBlocks(void);
+#define _Py_GetAllocatedBlocks() \
+    _Py_GetGlobalAllocatedBlocks()
+extern Py_ssize_t _PyInterpreterState_GetAllocatedBlocks(PyInterpreterState *);
+extern void _PyInterpreterState_FinalizeAllocatedBlocks(PyInterpreterState *);
 
 
 #ifdef WITH_PYMALLOC
diff -pruN 3.12.0~a7-1/Include/internal/pycore_obmalloc_init.h 3.12.0~b1-1/Include/internal/pycore_obmalloc_init.h
--- 3.12.0~a7-1/Include/internal/pycore_obmalloc_init.h	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Include/internal/pycore_obmalloc_init.h	2023-05-22 12:07:36.000000000 +0000
@@ -54,9 +54,13 @@ extern "C" {
 #  error "NB_SMALL_SIZE_CLASSES should be less than 64"
 #endif
 
-#define _obmalloc_state_INIT(obmalloc) \
+#define _obmalloc_global_state_INIT \
     { \
         .dump_debug_stats = -1, \
+    }
+
+#define _obmalloc_state_INIT(obmalloc) \
+    { \
         .pools = { \
             .used = _obmalloc_pools_INIT(obmalloc.pools), \
         }, \
diff -pruN 3.12.0~a7-1/Include/internal/pycore_opcode.h 3.12.0~b1-1/Include/internal/pycore_opcode.h
--- 3.12.0~a7-1/Include/internal/pycore_opcode.h	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Include/internal/pycore_opcode.h	2023-05-22 12:07:36.000000000 +0000
@@ -12,8 +12,6 @@ extern "C" {
 
 #include "opcode.h"
 
-extern const uint32_t _PyOpcode_RelativeJump[9];
-
 extern const uint32_t _PyOpcode_Jump[9];
 
 extern const uint8_t _PyOpcode_Caches[256];
@@ -21,17 +19,6 @@ extern const uint8_t _PyOpcode_Caches[25
 extern const uint8_t _PyOpcode_Deopt[256];
 
 #ifdef NEED_OPCODE_TABLES
-const uint32_t _PyOpcode_RelativeJump[9] = {
-    0U,
-    0U,
-    536870912U,
-    135020544U,
-    4163U,
-    0U,
-    0U,
-    0U,
-    48U,
-};
 const uint32_t _PyOpcode_Jump[9] = {
     0U,
     0U,
@@ -55,7 +42,8 @@ const uint8_t _PyOpcode_Caches[256] = {
     [LOAD_GLOBAL] = 4,
     [BINARY_OP] = 1,
     [SEND] = 1,
-    [CALL] = 4,
+    [LOAD_SUPER_ATTR] = 1,
+    [CALL] = 3,
 };
 
 const uint8_t _PyOpcode_Deopt[256] = {
@@ -125,6 +113,7 @@ const uint8_t _PyOpcode_Deopt[256] = {
     [DICT_UPDATE] = DICT_UPDATE,
     [END_ASYNC_FOR] = END_ASYNC_FOR,
     [END_FOR] = END_FOR,
+    [END_SEND] = END_SEND,
     [EXTENDED_ARG] = EXTENDED_ARG,
     [FORMAT_VALUE] = FORMAT_VALUE,
     [FOR_ITER] = FOR_ITER,
@@ -140,6 +129,24 @@ const uint8_t _PyOpcode_Deopt[256] = {
     [GET_YIELD_FROM_ITER] = GET_YIELD_FROM_ITER,
     [IMPORT_FROM] = IMPORT_FROM,
     [IMPORT_NAME] = IMPORT_NAME,
+    [INSTRUMENTED_CALL] = INSTRUMENTED_CALL,
+    [INSTRUMENTED_CALL_FUNCTION_EX] = INSTRUMENTED_CALL_FUNCTION_EX,
+    [INSTRUMENTED_END_FOR] = INSTRUMENTED_END_FOR,
+    [INSTRUMENTED_END_SEND] = INSTRUMENTED_END_SEND,
+    [INSTRUMENTED_FOR_ITER] = INSTRUMENTED_FOR_ITER,
+    [INSTRUMENTED_INSTRUCTION] = INSTRUMENTED_INSTRUCTION,
+    [INSTRUMENTED_JUMP_BACKWARD] = INSTRUMENTED_JUMP_BACKWARD,
+    [INSTRUMENTED_JUMP_FORWARD] = INSTRUMENTED_JUMP_FORWARD,
+    [INSTRUMENTED_LINE] = INSTRUMENTED_LINE,
+    [INSTRUMENTED_LOAD_SUPER_ATTR] = INSTRUMENTED_LOAD_SUPER_ATTR,
+    [INSTRUMENTED_POP_JUMP_IF_FALSE] = INSTRUMENTED_POP_JUMP_IF_FALSE,
+    [INSTRUMENTED_POP_JUMP_IF_NONE] = INSTRUMENTED_POP_JUMP_IF_NONE,
+    [INSTRUMENTED_POP_JUMP_IF_NOT_NONE] = INSTRUMENTED_POP_JUMP_IF_NOT_NONE,
+    [INSTRUMENTED_POP_JUMP_IF_TRUE] = INSTRUMENTED_POP_JUMP_IF_TRUE,
+    [INSTRUMENTED_RESUME] = INSTRUMENTED_RESUME,
+    [INSTRUMENTED_RETURN_CONST] = INSTRUMENTED_RETURN_CONST,
+    [INSTRUMENTED_RETURN_VALUE] = INSTRUMENTED_RETURN_VALUE,
+    [INSTRUMENTED_YIELD_VALUE] = INSTRUMENTED_YIELD_VALUE,
     [INTERPRETER_EXIT] = INTERPRETER_EXIT,
     [IS_OP] = IS_OP,
     [JUMP_BACKWARD] = JUMP_BACKWARD,
@@ -161,19 +168,25 @@ const uint8_t _PyOpcode_Deopt[256] = {
     [LOAD_ATTR_SLOT] = LOAD_ATTR,
     [LOAD_ATTR_WITH_HINT] = LOAD_ATTR,
     [LOAD_BUILD_CLASS] = LOAD_BUILD_CLASS,
-    [LOAD_CLASSDEREF] = LOAD_CLASSDEREF,
     [LOAD_CLOSURE] = LOAD_CLOSURE,
     [LOAD_CONST] = LOAD_CONST,
     [LOAD_CONST__LOAD_FAST] = LOAD_CONST,
     [LOAD_DEREF] = LOAD_DEREF,
     [LOAD_FAST] = LOAD_FAST,
+    [LOAD_FAST_AND_CLEAR] = LOAD_FAST_AND_CLEAR,
     [LOAD_FAST_CHECK] = LOAD_FAST_CHECK,
     [LOAD_FAST__LOAD_CONST] = LOAD_FAST,
     [LOAD_FAST__LOAD_FAST] = LOAD_FAST,
+    [LOAD_FROM_DICT_OR_DEREF] = LOAD_FROM_DICT_OR_DEREF,
+    [LOAD_FROM_DICT_OR_GLOBALS] = LOAD_FROM_DICT_OR_GLOBALS,
     [LOAD_GLOBAL] = LOAD_GLOBAL,
     [LOAD_GLOBAL_BUILTIN] = LOAD_GLOBAL,
     [LOAD_GLOBAL_MODULE] = LOAD_GLOBAL,
+    [LOAD_LOCALS] = LOAD_LOCALS,
     [LOAD_NAME] = LOAD_NAME,
+    [LOAD_SUPER_ATTR] = LOAD_SUPER_ATTR,
+    [LOAD_SUPER_ATTR_ATTR] = LOAD_SUPER_ATTR,
+    [LOAD_SUPER_ATTR_METHOD] = LOAD_SUPER_ATTR,
     [MAKE_CELL] = MAKE_CELL,
     [MAKE_FUNCTION] = MAKE_FUNCTION,
     [MAP_ADD] = MAP_ADD,
@@ -192,6 +205,7 @@ const uint8_t _PyOpcode_Deopt[256] = {
     [PUSH_NULL] = PUSH_NULL,
     [RAISE_VARARGS] = RAISE_VARARGS,
     [RERAISE] = RERAISE,
+    [RESERVED] = RESERVED,
     [RESUME] = RESUME,
     [RETURN_CONST] = RETURN_CONST,
     [RETURN_GENERATOR] = RETURN_GENERATOR,
@@ -230,23 +244,25 @@ const uint8_t _PyOpcode_Deopt[256] = {
 #endif   // NEED_OPCODE_TABLES
 
 #ifdef Py_DEBUG
-static const char *const _PyOpcode_OpName[263] = {
+static const char *const _PyOpcode_OpName[267] = {
     [CACHE] = "CACHE",
     [POP_TOP] = "POP_TOP",
     [PUSH_NULL] = "PUSH_NULL",
     [INTERPRETER_EXIT] = "INTERPRETER_EXIT",
     [END_FOR] = "END_FOR",
+    [END_SEND] = "END_SEND",
     [BINARY_OP_ADD_FLOAT] = "BINARY_OP_ADD_FLOAT",
     [BINARY_OP_ADD_INT] = "BINARY_OP_ADD_INT",
     [BINARY_OP_ADD_UNICODE] = "BINARY_OP_ADD_UNICODE",
-    [BINARY_OP_INPLACE_ADD_UNICODE] = "BINARY_OP_INPLACE_ADD_UNICODE",
     [NOP] = "NOP",
-    [BINARY_OP_MULTIPLY_FLOAT] = "BINARY_OP_MULTIPLY_FLOAT",
+    [BINARY_OP_INPLACE_ADD_UNICODE] = "BINARY_OP_INPLACE_ADD_UNICODE",
     [UNARY_NEGATIVE] = "UNARY_NEGATIVE",
     [UNARY_NOT] = "UNARY_NOT",
+    [BINARY_OP_MULTIPLY_FLOAT] = "BINARY_OP_MULTIPLY_FLOAT",
     [BINARY_OP_MULTIPLY_INT] = "BINARY_OP_MULTIPLY_INT",
-    [BINARY_OP_SUBTRACT_FLOAT] = "BINARY_OP_SUBTRACT_FLOAT",
     [UNARY_INVERT] = "UNARY_INVERT",
+    [BINARY_OP_SUBTRACT_FLOAT] = "BINARY_OP_SUBTRACT_FLOAT",
+    [RESERVED] = "RESERVED",
     [BINARY_OP_SUBTRACT_INT] = "BINARY_OP_SUBTRACT_INT",
     [BINARY_SUBSCR_DICT] = "BINARY_SUBSCR_DICT",
     [BINARY_SUBSCR_GETITEM] = "BINARY_SUBSCR_GETITEM",
@@ -254,21 +270,21 @@ static const char *const _PyOpcode_OpNam
     [BINARY_SUBSCR_TUPLE_INT] = "BINARY_SUBSCR_TUPLE_INT",
     [CALL_PY_EXACT_ARGS] = "CALL_PY_EXACT_ARGS",
     [CALL_PY_WITH_DEFAULTS] = "CALL_PY_WITH_DEFAULTS",
-    [CALL_BOUND_METHOD_EXACT_ARGS] = "CALL_BOUND_METHOD_EXACT_ARGS",
-    [CALL_BUILTIN_CLASS] = "CALL_BUILTIN_CLASS",
     [BINARY_SUBSCR] = "BINARY_SUBSCR",
     [BINARY_SLICE] = "BINARY_SLICE",
     [STORE_SLICE] = "STORE_SLICE",
-    [CALL_BUILTIN_FAST_WITH_KEYWORDS] = "CALL_BUILTIN_FAST_WITH_KEYWORDS",
-    [CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = "CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS",
+    [CALL_BOUND_METHOD_EXACT_ARGS] = "CALL_BOUND_METHOD_EXACT_ARGS",
+    [CALL_BUILTIN_CLASS] = "CALL_BUILTIN_CLASS",
     [GET_LEN] = "GET_LEN",
     [MATCH_MAPPING] = "MATCH_MAPPING",
     [MATCH_SEQUENCE] = "MATCH_SEQUENCE",
     [MATCH_KEYS] = "MATCH_KEYS",
-    [CALL_NO_KW_BUILTIN_FAST] = "CALL_NO_KW_BUILTIN_FAST",
+    [CALL_BUILTIN_FAST_WITH_KEYWORDS] = "CALL_BUILTIN_FAST_WITH_KEYWORDS",
     [PUSH_EXC_INFO] = "PUSH_EXC_INFO",
     [CHECK_EXC_MATCH] = "CHECK_EXC_MATCH",
     [CHECK_EG_MATCH] = "CHECK_EG_MATCH",
+    [CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = "CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS",
+    [CALL_NO_KW_BUILTIN_FAST] = "CALL_NO_KW_BUILTIN_FAST",
     [CALL_NO_KW_BUILTIN_O] = "CALL_NO_KW_BUILTIN_O",
     [CALL_NO_KW_ISINSTANCE] = "CALL_NO_KW_ISINSTANCE",
     [CALL_NO_KW_LEN] = "CALL_NO_KW_LEN",
@@ -278,8 +294,6 @@ static const char *const _PyOpcode_OpNam
     [CALL_NO_KW_METHOD_DESCRIPTOR_O] = "CALL_NO_KW_METHOD_DESCRIPTOR_O",
     [CALL_NO_KW_STR_1] = "CALL_NO_KW_STR_1",
     [CALL_NO_KW_TUPLE_1] = "CALL_NO_KW_TUPLE_1",
-    [CALL_NO_KW_TYPE_1] = "CALL_NO_KW_TYPE_1",
-    [COMPARE_OP_FLOAT] = "COMPARE_OP_FLOAT",
     [WITH_EXCEPT_START] = "WITH_EXCEPT_START",
     [GET_AITER] = "GET_AITER",
     [GET_ANEXT] = "GET_ANEXT",
@@ -287,39 +301,39 @@ static const char *const _PyOpcode_OpNam
     [BEFORE_WITH] = "BEFORE_WITH",
     [END_ASYNC_FOR] = "END_ASYNC_FOR",
     [CLEANUP_THROW] = "CLEANUP_THROW",
+    [CALL_NO_KW_TYPE_1] = "CALL_NO_KW_TYPE_1",
+    [COMPARE_OP_FLOAT] = "COMPARE_OP_FLOAT",
     [COMPARE_OP_INT] = "COMPARE_OP_INT",
     [COMPARE_OP_STR] = "COMPARE_OP_STR",
-    [FOR_ITER_LIST] = "FOR_ITER_LIST",
-    [FOR_ITER_TUPLE] = "FOR_ITER_TUPLE",
     [STORE_SUBSCR] = "STORE_SUBSCR",
     [DELETE_SUBSCR] = "DELETE_SUBSCR",
+    [FOR_ITER_LIST] = "FOR_ITER_LIST",
+    [FOR_ITER_TUPLE] = "FOR_ITER_TUPLE",
     [FOR_ITER_RANGE] = "FOR_ITER_RANGE",
     [FOR_ITER_GEN] = "FOR_ITER_GEN",
+    [LOAD_SUPER_ATTR_ATTR] = "LOAD_SUPER_ATTR_ATTR",
+    [LOAD_SUPER_ATTR_METHOD] = "LOAD_SUPER_ATTR_METHOD",
+    [GET_ITER] = "GET_ITER",
+    [GET_YIELD_FROM_ITER] = "GET_YIELD_FROM_ITER",
     [LOAD_ATTR_CLASS] = "LOAD_ATTR_CLASS",
+    [LOAD_BUILD_CLASS] = "LOAD_BUILD_CLASS",
     [LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN] = "LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN",
     [LOAD_ATTR_INSTANCE_VALUE] = "LOAD_ATTR_INSTANCE_VALUE",
+    [LOAD_ASSERTION_ERROR] = "LOAD_ASSERTION_ERROR",
+    [RETURN_GENERATOR] = "RETURN_GENERATOR",
     [LOAD_ATTR_MODULE] = "LOAD_ATTR_MODULE",
-    [GET_ITER] = "GET_ITER",
-    [GET_YIELD_FROM_ITER] = "GET_YIELD_FROM_ITER",
     [LOAD_ATTR_PROPERTY] = "LOAD_ATTR_PROPERTY",
-    [LOAD_BUILD_CLASS] = "LOAD_BUILD_CLASS",
     [LOAD_ATTR_SLOT] = "LOAD_ATTR_SLOT",
     [LOAD_ATTR_WITH_HINT] = "LOAD_ATTR_WITH_HINT",
-    [LOAD_ASSERTION_ERROR] = "LOAD_ASSERTION_ERROR",
-    [RETURN_GENERATOR] = "RETURN_GENERATOR",
     [LOAD_ATTR_METHOD_LAZY_DICT] = "LOAD_ATTR_METHOD_LAZY_DICT",
     [LOAD_ATTR_METHOD_NO_DICT] = "LOAD_ATTR_METHOD_NO_DICT",
     [LOAD_ATTR_METHOD_WITH_VALUES] = "LOAD_ATTR_METHOD_WITH_VALUES",
+    [RETURN_VALUE] = "RETURN_VALUE",
     [LOAD_CONST__LOAD_FAST] = "LOAD_CONST__LOAD_FAST",
+    [SETUP_ANNOTATIONS] = "SETUP_ANNOTATIONS",
     [LOAD_FAST__LOAD_CONST] = "LOAD_FAST__LOAD_CONST",
+    [LOAD_LOCALS] = "LOAD_LOCALS",
     [LOAD_FAST__LOAD_FAST] = "LOAD_FAST__LOAD_FAST",
-    [LOAD_GLOBAL_BUILTIN] = "LOAD_GLOBAL_BUILTIN",
-    [RETURN_VALUE] = "RETURN_VALUE",
-    [LOAD_GLOBAL_MODULE] = "LOAD_GLOBAL_MODULE",
-    [SETUP_ANNOTATIONS] = "SETUP_ANNOTATIONS",
-    [STORE_ATTR_INSTANCE_VALUE] = "STORE_ATTR_INSTANCE_VALUE",
-    [STORE_ATTR_SLOT] = "STORE_ATTR_SLOT",
-    [STORE_ATTR_WITH_HINT] = "STORE_ATTR_WITH_HINT",
     [POP_EXCEPT] = "POP_EXCEPT",
     [STORE_NAME] = "STORE_NAME",
     [DELETE_NAME] = "DELETE_NAME",
@@ -342,9 +356,9 @@ static const char *const _PyOpcode_OpNam
     [IMPORT_NAME] = "IMPORT_NAME",
     [IMPORT_FROM] = "IMPORT_FROM",
     [JUMP_FORWARD] = "JUMP_FORWARD",
-    [STORE_FAST__LOAD_FAST] = "STORE_FAST__LOAD_FAST",
-    [STORE_FAST__STORE_FAST] = "STORE_FAST__STORE_FAST",
-    [STORE_SUBSCR_DICT] = "STORE_SUBSCR_DICT",
+    [LOAD_GLOBAL_BUILTIN] = "LOAD_GLOBAL_BUILTIN",
+    [LOAD_GLOBAL_MODULE] = "LOAD_GLOBAL_MODULE",
+    [STORE_ATTR_INSTANCE_VALUE] = "STORE_ATTR_INSTANCE_VALUE",
     [POP_JUMP_IF_FALSE] = "POP_JUMP_IF_FALSE",
     [POP_JUMP_IF_TRUE] = "POP_JUMP_IF_TRUE",
     [LOAD_GLOBAL] = "LOAD_GLOBAL",
@@ -372,42 +386,42 @@ static const char *const _PyOpcode_OpNam
     [STORE_DEREF] = "STORE_DEREF",
     [DELETE_DEREF] = "DELETE_DEREF",
     [JUMP_BACKWARD] = "JUMP_BACKWARD",
-    [STORE_SUBSCR_LIST_INT] = "STORE_SUBSCR_LIST_INT",
+    [LOAD_SUPER_ATTR] = "LOAD_SUPER_ATTR",
     [CALL_FUNCTION_EX] = "CALL_FUNCTION_EX",
-    [UNPACK_SEQUENCE_LIST] = "UNPACK_SEQUENCE_LIST",
+    [LOAD_FAST_AND_CLEAR] = "LOAD_FAST_AND_CLEAR",
     [EXTENDED_ARG] = "EXTENDED_ARG",
     [LIST_APPEND] = "LIST_APPEND",
     [SET_ADD] = "SET_ADD",
     [MAP_ADD] = "MAP_ADD",
-    [LOAD_CLASSDEREF] = "LOAD_CLASSDEREF",
+    [STORE_ATTR_SLOT] = "STORE_ATTR_SLOT",
     [COPY_FREE_VARS] = "COPY_FREE_VARS",
     [YIELD_VALUE] = "YIELD_VALUE",
     [RESUME] = "RESUME",
     [MATCH_CLASS] = "MATCH_CLASS",
-    [UNPACK_SEQUENCE_TUPLE] = "UNPACK_SEQUENCE_TUPLE",
-    [UNPACK_SEQUENCE_TWO_TUPLE] = "UNPACK_SEQUENCE_TWO_TUPLE",
+    [STORE_ATTR_WITH_HINT] = "STORE_ATTR_WITH_HINT",
+    [STORE_FAST__LOAD_FAST] = "STORE_FAST__LOAD_FAST",
     [FORMAT_VALUE] = "FORMAT_VALUE",
     [BUILD_CONST_KEY_MAP] = "BUILD_CONST_KEY_MAP",
     [BUILD_STRING] = "BUILD_STRING",
-    [SEND_GEN] = "SEND_GEN",
-    [159] = "<159>",
-    [160] = "<160>",
-    [161] = "<161>",
+    [STORE_FAST__STORE_FAST] = "STORE_FAST__STORE_FAST",
+    [STORE_SUBSCR_DICT] = "STORE_SUBSCR_DICT",
+    [STORE_SUBSCR_LIST_INT] = "STORE_SUBSCR_LIST_INT",
+    [UNPACK_SEQUENCE_LIST] = "UNPACK_SEQUENCE_LIST",
     [LIST_EXTEND] = "LIST_EXTEND",
     [SET_UPDATE] = "SET_UPDATE",
     [DICT_MERGE] = "DICT_MERGE",
     [DICT_UPDATE] = "DICT_UPDATE",
-    [166] = "<166>",
-    [167] = "<167>",
-    [168] = "<168>",
+    [UNPACK_SEQUENCE_TUPLE] = "UNPACK_SEQUENCE_TUPLE",
+    [UNPACK_SEQUENCE_TWO_TUPLE] = "UNPACK_SEQUENCE_TWO_TUPLE",
+    [SEND_GEN] = "SEND_GEN",
     [169] = "<169>",
     [170] = "<170>",
     [CALL] = "CALL",
     [KW_NAMES] = "KW_NAMES",
     [CALL_INTRINSIC_1] = "CALL_INTRINSIC_1",
     [CALL_INTRINSIC_2] = "CALL_INTRINSIC_2",
-    [175] = "<175>",
-    [176] = "<176>",
+    [LOAD_FROM_DICT_OR_GLOBALS] = "LOAD_FROM_DICT_OR_GLOBALS",
+    [LOAD_FROM_DICT_OR_DEREF] = "LOAD_FROM_DICT_OR_DEREF",
     [177] = "<177>",
     [178] = "<178>",
     [179] = "<179>",
@@ -468,25 +482,25 @@ static const char *const _PyOpcode_OpNam
     [234] = "<234>",
     [235] = "<235>",
     [236] = "<236>",
-    [237] = "<237>",
-    [238] = "<238>",
-    [239] = "<239>",
-    [240] = "<240>",
-    [241] = "<241>",
-    [242] = "<242>",
-    [243] = "<243>",
-    [244] = "<244>",
-    [245] = "<245>",
-    [246] = "<246>",
-    [247] = "<247>",
-    [248] = "<248>",
-    [249] = "<249>",
-    [250] = "<250>",
-    [251] = "<251>",
-    [252] = "<252>",
-    [253] = "<253>",
-    [254] = "<254>",
-    [DO_TRACING] = "DO_TRACING",
+    [INSTRUMENTED_LOAD_SUPER_ATTR] = "INSTRUMENTED_LOAD_SUPER_ATTR",
+    [INSTRUMENTED_POP_JUMP_IF_NONE] = "INSTRUMENTED_POP_JUMP_IF_NONE",
+    [INSTRUMENTED_POP_JUMP_IF_NOT_NONE] = "INSTRUMENTED_POP_JUMP_IF_NOT_NONE",
+    [INSTRUMENTED_RESUME] = "INSTRUMENTED_RESUME",
+    [INSTRUMENTED_CALL] = "INSTRUMENTED_CALL",
+    [INSTRUMENTED_RETURN_VALUE] = "INSTRUMENTED_RETURN_VALUE",
+    [INSTRUMENTED_YIELD_VALUE] = "INSTRUMENTED_YIELD_VALUE",
+    [INSTRUMENTED_CALL_FUNCTION_EX] = "INSTRUMENTED_CALL_FUNCTION_EX",
+    [INSTRUMENTED_JUMP_FORWARD] = "INSTRUMENTED_JUMP_FORWARD",
+    [INSTRUMENTED_JUMP_BACKWARD] = "INSTRUMENTED_JUMP_BACKWARD",
+    [INSTRUMENTED_RETURN_CONST] = "INSTRUMENTED_RETURN_CONST",
+    [INSTRUMENTED_FOR_ITER] = "INSTRUMENTED_FOR_ITER",
+    [INSTRUMENTED_POP_JUMP_IF_FALSE] = "INSTRUMENTED_POP_JUMP_IF_FALSE",
+    [INSTRUMENTED_POP_JUMP_IF_TRUE] = "INSTRUMENTED_POP_JUMP_IF_TRUE",
+    [INSTRUMENTED_END_FOR] = "INSTRUMENTED_END_FOR",
+    [INSTRUMENTED_END_SEND] = "INSTRUMENTED_END_SEND",
+    [INSTRUMENTED_INSTRUCTION] = "INSTRUMENTED_INSTRUCTION",
+    [INSTRUMENTED_LINE] = "INSTRUMENTED_LINE",
+    [255] = "<255>",
     [SETUP_FINALLY] = "SETUP_FINALLY",
     [SETUP_CLEANUP] = "SETUP_CLEANUP",
     [SETUP_WITH] = "SETUP_WITH",
@@ -494,20 +508,16 @@ static const char *const _PyOpcode_OpNam
     [JUMP] = "JUMP",
     [JUMP_NO_INTERRUPT] = "JUMP_NO_INTERRUPT",
     [LOAD_METHOD] = "LOAD_METHOD",
+    [LOAD_SUPER_METHOD] = "LOAD_SUPER_METHOD",
+    [LOAD_ZERO_SUPER_METHOD] = "LOAD_ZERO_SUPER_METHOD",
+    [LOAD_ZERO_SUPER_ATTR] = "LOAD_ZERO_SUPER_ATTR",
+    [STORE_FAST_MAYBE_NULL] = "STORE_FAST_MAYBE_NULL",
 };
 #endif
 
 #define EXTRA_CASES \
-    case 159: \
-    case 160: \
-    case 161: \
-    case 166: \
-    case 167: \
-    case 168: \
     case 169: \
     case 170: \
-    case 175: \
-    case 176: \
     case 177: \
     case 178: \
     case 179: \
@@ -568,24 +578,7 @@ static const char *const _PyOpcode_OpNam
     case 234: \
     case 235: \
     case 236: \
-    case 237: \
-    case 238: \
-    case 239: \
-    case 240: \
-    case 241: \
-    case 242: \
-    case 243: \
-    case 244: \
-    case 245: \
-    case 246: \
-    case 247: \
-    case 248: \
-    case 249: \
-    case 250: \
-    case 251: \
-    case 252: \
-    case 253: \
-    case 254: \
+    case 255: \
         ;
 
 #ifdef __cplusplus
diff -pruN 3.12.0~a7-1/Include/internal/pycore_opcode_utils.h 3.12.0~b1-1/Include/internal/pycore_opcode_utils.h
--- 3.12.0~a7-1/Include/internal/pycore_opcode_utils.h	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Include/internal/pycore_opcode_utils.h	2023-05-22 12:07:36.000000000 +0000
@@ -8,7 +8,7 @@ extern "C" {
 #  error "this header requires Py_BUILD_CORE define"
 #endif
 
-#include "pycore_opcode.h"        // _PyOpcode_RelativeJump
+#include "pycore_opcode.h"        // _PyOpcode_Jump
 
 
 #define MAX_REAL_OPCODE 254
@@ -85,9 +85,6 @@ is_bit_set_in_table(const uint32_t *tabl
 #undef LOG_BITS_PER_INT
 #undef MASK_LOW_LOG_BITS
 
-#define IS_RELATIVE_JUMP(opcode) (is_bit_set_in_table(_PyOpcode_RelativeJump, opcode))
-
-
 
 #ifdef __cplusplus
 }
diff -pruN 3.12.0~a7-1/Include/internal/pycore_pyerrors.h 3.12.0~b1-1/Include/internal/pycore_pyerrors.h
--- 3.12.0~a7-1/Include/internal/pycore_pyerrors.h	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Include/internal/pycore_pyerrors.h	2023-05-22 12:07:36.000000000 +0000
@@ -109,6 +109,8 @@ extern PyObject* _Py_Offer_Suggestions(P
 PyAPI_FUNC(Py_ssize_t) _Py_UTF8_Edit_Cost(PyObject *str_a, PyObject *str_b,
                                           Py_ssize_t max_cost);
 
+void _PyErr_FormatNote(const char *format, ...);
+
 #ifdef __cplusplus
 }
 #endif
diff -pruN 3.12.0~a7-1/Include/internal/pycore_pylifecycle.h 3.12.0~b1-1/Include/internal/pycore_pylifecycle.h
--- 3.12.0~a7-1/Include/internal/pycore_pylifecycle.h	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Include/internal/pycore_pylifecycle.h	2023-05-22 12:07:36.000000000 +0000
@@ -31,7 +31,6 @@ PyAPI_FUNC(int) _Py_IsLocaleCoercionTarg
 
 extern void _Py_InitVersion(void);
 extern PyStatus _PyFaulthandler_Init(int enable);
-extern int _PyTraceMalloc_Init(int enable);
 extern PyObject * _PyBuiltin_Init(PyInterpreterState *interp);
 extern PyStatus _PySys_Create(
     PyThreadState *tstate,
@@ -39,7 +38,7 @@ extern PyStatus _PySys_Create(
 extern PyStatus _PySys_ReadPreinitWarnOptions(PyWideStringList *options);
 extern PyStatus _PySys_ReadPreinitXOptions(PyConfig *config);
 extern int _PySys_UpdateConfig(PyThreadState *tstate);
-extern void _PySys_Fini(PyInterpreterState *interp);
+extern void _PySys_FiniTypes(PyInterpreterState *interp);
 extern int _PyBuiltins_AddExceptions(PyObject * bltinmod);
 extern PyStatus _Py_HashRandomization_Init(const PyConfig *);
 
@@ -64,6 +63,7 @@ extern void _PyAtExit_Fini(PyInterpreter
 extern void _PyThread_FiniType(PyInterpreterState *interp);
 extern void _Py_Deepfreeze_Fini(void);
 extern void _PyArg_Fini(void);
+extern void _Py_FinalizeAllocatedBlocks(_PyRuntimeState *);
 
 extern PyStatus _PyGILState_Init(PyInterpreterState *interp);
 extern PyStatus _PyGILState_SetTstate(PyThreadState *tstate);
diff -pruN 3.12.0~a7-1/Include/internal/pycore_pystate.h 3.12.0~b1-1/Include/internal/pycore_pystate.h
--- 3.12.0~a7-1/Include/internal/pycore_pystate.h	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Include/internal/pycore_pystate.h	2023-05-22 12:07:36.000000000 +0000
@@ -33,6 +33,13 @@ _Py_IsMainInterpreter(PyInterpreterState
     return (interp == _PyInterpreterState_Main());
 }
 
+static inline int
+_Py_IsMainInterpreterFinalizing(PyInterpreterState *interp)
+{
+    return (_PyRuntimeState_GetFinalizing(interp->runtime) != NULL &&
+            interp == &interp->runtime->_main_interpreter);
+}
+
 
 static inline const PyConfig *
 _Py_GetMainConfig(void)
@@ -61,20 +68,17 @@ _Py_ThreadCanHandlePendingCalls(void)
 }
 
 
-/* Variable and macro for in-line access to current thread
+/* Variable and static inline functions for in-line access to current thread
    and interpreter state */
 
-static inline PyThreadState*
-_PyRuntimeState_GetThreadState(_PyRuntimeState *runtime)
-{
-    return (PyThreadState*)_Py_atomic_load_relaxed(&runtime->tstate_current);
-}
+#if defined(HAVE_THREAD_LOCAL) && !defined(Py_BUILD_CORE_MODULE)
+extern _Py_thread_local PyThreadState *_Py_tss_tstate;
+#endif
+PyAPI_DATA(PyThreadState *) _PyThreadState_GetCurrent(void);
 
 /* Get the current Python thread state.
 
-   Efficient macro reading directly the 'tstate_current' atomic
-   variable. The macro is unsafe: it does not check for error and it can
-   return NULL.
+   This function is unsafe: it does not check for error and it can return NULL.
 
    The caller must hold the GIL.
 
@@ -82,9 +86,14 @@ _PyRuntimeState_GetThreadState(_PyRuntim
 static inline PyThreadState*
 _PyThreadState_GET(void)
 {
-    return _PyRuntimeState_GetThreadState(&_PyRuntime);
+#if defined(HAVE_THREAD_LOCAL) && !defined(Py_BUILD_CORE_MODULE)
+    return _Py_tss_tstate;
+#else
+    return _PyThreadState_GetCurrent();
+#endif
 }
 
+
 static inline void
 _Py_EnsureFuncTstateNotNULL(const char *func, PyThreadState *tstate)
 {
@@ -103,7 +112,7 @@ _Py_EnsureFuncTstateNotNULL(const char *
 
 /* Get the current interpreter state.
 
-   The macro is unsafe: it does not check for error and it can return NULL.
+   The function is unsafe: it does not check for error and it can return NULL.
 
    The caller must hold the GIL.
 
@@ -133,16 +142,6 @@ extern void _PyThreadState_BindDetached(
 extern void _PyThreadState_UnbindDetached(PyThreadState *);
 
 
-static inline void
-_PyThreadState_UpdateTracingState(PyThreadState *tstate)
-{
-    bool use_tracing =
-        (tstate->tracing == 0) &&
-        (tstate->c_tracefunc != NULL || tstate->c_profilefunc != NULL);
-    tstate->cframe->use_tracing = (use_tracing ? 255 : 0);
-}
-
-
 /* Other */
 
 PyAPI_FUNC(PyThreadState *) _PyThreadState_Swap(
diff -pruN 3.12.0~a7-1/Include/internal/pycore_runtime.h 3.12.0~b1-1/Include/internal/pycore_runtime.h
--- 3.12.0~a7-1/Include/internal/pycore_runtime.h	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Include/internal/pycore_runtime.h	2023-05-22 12:07:36.000000000 +0000
@@ -8,6 +8,7 @@ extern "C" {
 #  error "this header requires Py_BUILD_CORE define"
 #endif
 
+#include "pycore_atexit.h"          // struct atexit_runtime_state
 #include "pycore_atomic.h"          /* _Py_atomic_address */
 #include "pycore_ceval_state.h"     // struct _ceval_runtime_state
 #include "pycore_floatobject.h"     // struct _Py_float_runtime_state
@@ -20,10 +21,10 @@ extern "C" {
 #include "pycore_pymem.h"           // struct _pymem_allocators
 #include "pycore_pyhash.h"          // struct pyhash_runtime_state
 #include "pycore_pythread.h"        // struct _pythread_runtime_state
-#include "pycore_obmalloc.h"        // struct obmalloc_state
 #include "pycore_signal.h"          // struct _signals_runtime_state
 #include "pycore_time.h"            // struct _time_runtime_state
 #include "pycore_tracemalloc.h"     // struct _tracemalloc_runtime_state
+#include "pycore_typeobject.h"      // struct types_runtime_state
 #include "pycore_unicodeobject.h"   // struct _Py_unicode_runtime_ids
 
 struct _getargs_runtime_state {
@@ -31,8 +32,6 @@ struct _getargs_runtime_state {
     struct _PyArg_Parser *static_parsers;
 };
 
-/* ceval state */
-
 /* GIL state */
 
 struct _gilstate_runtime_state {
@@ -86,7 +85,7 @@ typedef struct pyruntimestate {
     _Py_atomic_address _finalizing;
 
     struct _pymem_allocators allocators;
-    struct _obmalloc_state obmalloc;
+    struct _obmalloc_global_state obmalloc;
     struct pyhash_runtime_state pyhash_state;
     struct _time_runtime_state time;
     struct _pythread_runtime_state threads;
@@ -118,9 +117,6 @@ typedef struct pyruntimestate {
 
     unsigned long main_thread;
 
-    /* Assuming the current thread holds the GIL, this is the
-       PyThreadState for the current thread. */
-    _Py_atomic_address tstate_current;
     /* Used for the thread state bound to the current thread. */
     Py_tss_t autoTSSkey;
 
@@ -131,9 +127,7 @@ typedef struct pyruntimestate {
 
     struct _parser_runtime_state parser;
 
-#define NEXITFUNCS 32
-    void (*exitfuncs[NEXITFUNCS])(void);
-    int nexitfuncs;
+    struct _atexit_runtime_state atexit;
 
     struct _import_runtime_state imports;
     struct _ceval_runtime_state ceval;
@@ -154,13 +148,7 @@ typedef struct pyruntimestate {
     struct _py_object_runtime_state object_state;
     struct _Py_float_runtime_state float_state;
     struct _Py_unicode_runtime_state unicode_state;
-
-    struct {
-        /* Used to set PyTypeObject.tp_version_tag */
-        // bpo-42745: next_version_tag remains shared by all interpreters
-        // because of static types.
-        unsigned int next_version_tag;
-    } types;
+    struct _types_runtime_state types;
 
     /* All the objects that are shared by the runtime's interpreters. */
     struct _Py_static_objects static_objects;
diff -pruN 3.12.0~a7-1/Include/internal/pycore_runtime_init.h 3.12.0~b1-1/Include/internal/pycore_runtime_init.h
--- 3.12.0~a7-1/Include/internal/pycore_runtime_init.h	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Include/internal/pycore_runtime_init.h	2023-05-22 12:07:36.000000000 +0000
@@ -29,7 +29,7 @@ extern PyTypeObject _PyExc_MemoryError;
             _pymem_allocators_debug_INIT, \
             _pymem_allocators_obj_arena_INIT, \
         }, \
-        .obmalloc = _obmalloc_state_INIT(runtime.obmalloc), \
+        .obmalloc = _obmalloc_global_state_INIT, \
         .pyhash_state = pyhash_state_INIT, \
         .signals = _signals_RUNTIME_INIT, \
         .interpreters = { \
@@ -76,13 +76,13 @@ extern PyTypeObject _PyExc_MemoryError;
                     .latin1 = _Py_str_latin1_INIT, \
                 }, \
                 .tuple_empty = { \
-                    .ob_base = _PyVarObject_IMMORTAL_INIT(&PyTuple_Type, 0) \
+                    .ob_base = _PyVarObject_HEAD_INIT(&PyTuple_Type, 0) \
                 }, \
                 .hamt_bitmap_node_empty = { \
-                    .ob_base = _PyVarObject_IMMORTAL_INIT(&_PyHamt_BitmapNode_Type, 0) \
+                    .ob_base = _PyVarObject_HEAD_INIT(&_PyHamt_BitmapNode_Type, 0) \
                 }, \
                 .context_token_missing = { \
-                    .ob_base = _PyObject_IMMORTAL_INIT(&_PyContextTokenMissing_Type), \
+                    .ob_base = _PyObject_HEAD_INIT(&_PyContextTokenMissing_Type) \
                 }, \
             }, \
         }, \
@@ -93,6 +93,7 @@ extern PyTypeObject _PyExc_MemoryError;
     { \
         .id_refcount = -1, \
         .imports = IMPORTS_INIT, \
+        .obmalloc = _obmalloc_state_INIT(INTERP.obmalloc), \
         .ceval = { \
             .recursion_limit = Py_DEFAULT_RECURSION_LIMIT, \
         }, \
@@ -106,21 +107,22 @@ extern PyTypeObject _PyExc_MemoryError;
             }, \
         }, \
         .dtoa = _dtoa_state_INIT(&(INTERP)), \
-        .dict_state = { \
-            .next_keys_version = 2, \
-        }, \
+        .dict_state = _dict_state_INIT, \
         .func_state = { \
             .next_version = 1, \
         }, \
+        .types = { \
+            .next_version_tag = _Py_TYPE_BASE_VERSION_TAG, \
+        }, \
         .static_objects = { \
             .singletons = { \
                 ._not_used = 1, \
                 .hamt_empty = { \
-                    .ob_base = _PyObject_IMMORTAL_INIT(&_PyHamt_Type), \
+                    .ob_base = _PyObject_HEAD_INIT(&_PyHamt_Type) \
                     .h_root = (PyHamtNode*)&_Py_SINGLETON(hamt_bitmap_node_empty), \
                 }, \
                 .last_resort_memory_error = { \
-                    _PyObject_IMMORTAL_INIT(&_PyExc_MemoryError), \
+                    _PyObject_HEAD_INIT(&_PyExc_MemoryError) \
                 }, \
             }, \
         }, \
@@ -138,7 +140,7 @@ extern PyTypeObject _PyExc_MemoryError;
 
 #define _PyBytes_SIMPLE_INIT(CH, LEN) \
     { \
-        _PyVarObject_IMMORTAL_INIT(&PyBytes_Type, (LEN)), \
+        _PyVarObject_HEAD_INIT(&PyBytes_Type, (LEN)) \
         .ob_shash = -1, \
         .ob_sval = { (CH) }, \
     }
@@ -149,7 +151,7 @@ extern PyTypeObject _PyExc_MemoryError;
 
 #define _PyUnicode_ASCII_BASE_INIT(LITERAL, ASCII) \
     { \
-        .ob_base = _PyObject_IMMORTAL_INIT(&PyUnicode_Type), \
+        .ob_base = _PyObject_HEAD_INIT(&PyUnicode_Type) \
         .length = sizeof(LITERAL) - 1, \
         .hash = -1, \
         .state = { \
diff -pruN 3.12.0~a7-1/Include/internal/pycore_runtime_init_generated.h 3.12.0~b1-1/Include/internal/pycore_runtime_init_generated.h
--- 3.12.0~a7-1/Include/internal/pycore_runtime_init_generated.h	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Include/internal/pycore_runtime_init_generated.h	2023-05-22 12:07:36.000000000 +0000
@@ -546,15 +546,19 @@ extern "C" {
     INIT_STR(dbl_close_br, "}}"), \
     INIT_STR(dbl_open_br, "{{"), \
     INIT_STR(dbl_percent, "%%"), \
+    INIT_STR(defaults, ".defaults"), \
     INIT_STR(dot, "."), \
     INIT_STR(dot_locals, ".<locals>"), \
     INIT_STR(empty, ""), \
+    INIT_STR(generic_base, ".generic_base"), \
     INIT_STR(json_decoder, "json.decoder"), \
+    INIT_STR(kwdefaults, ".kwdefaults"), \
     INIT_STR(list_err, "list index out of range"), \
     INIT_STR(newline, "\n"), \
     INIT_STR(open_br, "{"), \
     INIT_STR(percent, "%"), \
     INIT_STR(shim_name, "<shim>"), \
+    INIT_STR(type_params, ".type_params"), \
     INIT_STR(utf_8, "utf-8"), \
 }
 
@@ -587,6 +591,7 @@ extern "C" {
     INIT_ID(__await__), \
     INIT_ID(__bases__), \
     INIT_ID(__bool__), \
+    INIT_ID(__buffer__), \
     INIT_ID(__build_class__), \
     INIT_ID(__builtins__), \
     INIT_ID(__bytes__), \
@@ -595,6 +600,8 @@ extern "C" {
     INIT_ID(__class__), \
     INIT_ID(__class_getitem__), \
     INIT_ID(__classcell__), \
+    INIT_ID(__classdict__), \
+    INIT_ID(__classdictcell__), \
     INIT_ID(__complex__), \
     INIT_ID(__contains__), \
     INIT_ID(__copy__), \
@@ -686,6 +693,7 @@ extern "C" {
     INIT_ID(__rdivmod__), \
     INIT_ID(__reduce__), \
     INIT_ID(__reduce_ex__), \
+    INIT_ID(__release_buffer__), \
     INIT_ID(__repr__), \
     INIT_ID(__reversed__), \
     INIT_ID(__rfloordiv__), \
@@ -716,6 +724,7 @@ extern "C" {
     INIT_ID(__subclasshook__), \
     INIT_ID(__truediv__), \
     INIT_ID(__trunc__), \
+    INIT_ID(__type_params__), \
     INIT_ID(__typing_is_unpacked_typevartuple__), \
     INIT_ID(__typing_prepare_subst__), \
     INIT_ID(__typing_subst__), \
@@ -771,8 +780,11 @@ extern "C" {
     INIT_ID(after_in_child), \
     INIT_ID(after_in_parent), \
     INIT_ID(aggregate_class), \
+    INIT_ID(alias), \
     INIT_ID(append), \
+    INIT_ID(arg), \
     INIT_ID(argdefs), \
+    INIT_ID(args), \
     INIT_ID(arguments), \
     INIT_ID(argv), \
     INIT_ID(as_integer_ratio), \
@@ -787,6 +799,7 @@ extern "C" {
     INIT_ID(big), \
     INIT_ID(binary_form), \
     INIT_ID(block), \
+    INIT_ID(bound), \
     INIT_ID(buffer), \
     INIT_ID(buffer_callback), \
     INIT_ID(buffer_size), \
@@ -839,13 +852,16 @@ extern "C" {
     INIT_ID(code), \
     INIT_ID(command), \
     INIT_ID(comment_factory), \
+    INIT_ID(compile_mode), \
     INIT_ID(consts), \
     INIT_ID(context), \
+    INIT_ID(contravariant), \
     INIT_ID(cookie), \
     INIT_ID(copy), \
     INIT_ID(copyreg), \
     INIT_ID(coro), \
     INIT_ID(count), \
+    INIT_ID(covariant), \
     INIT_ID(cwd), \
     INIT_ID(d), \
     INIT_ID(data), \
@@ -876,6 +892,7 @@ extern "C" {
     INIT_ID(dst_dir_fd), \
     INIT_ID(duration), \
     INIT_ID(e), \
+    INIT_ID(eager_start), \
     INIT_ID(effective_ids), \
     INIT_ID(element_factory), \
     INIT_ID(encode), \
@@ -884,6 +901,7 @@ extern "C" {
     INIT_ID(end_lineno), \
     INIT_ID(end_offset), \
     INIT_ID(endpos), \
+    INIT_ID(entrypoint), \
     INIT_ID(env), \
     INIT_ID(errors), \
     INIT_ID(event), \
@@ -894,6 +912,7 @@ extern "C" {
     INIT_ID(exception), \
     INIT_ID(exp), \
     INIT_ID(extend), \
+    INIT_ID(extra_tokens), \
     INIT_ID(facility), \
     INIT_ID(factory), \
     INIT_ID(false), \
@@ -953,6 +972,7 @@ extern "C" {
     INIT_ID(incoming), \
     INIT_ID(indexgroup), \
     INIT_ID(inf), \
+    INIT_ID(infer_variance), \
     INIT_ID(inheritable), \
     INIT_ID(initial), \
     INIT_ID(initial_bytes), \
@@ -965,6 +985,7 @@ extern "C" {
     INIT_ID(instructions), \
     INIT_ID(intern), \
     INIT_ID(intersection), \
+    INIT_ID(is_running), \
     INIT_ID(isatty), \
     INIT_ID(isinstance), \
     INIT_ID(isoformat), \
@@ -1020,6 +1041,7 @@ extern "C" {
     INIT_ID(memlimit), \
     INIT_ID(message), \
     INIT_ID(metaclass), \
+    INIT_ID(metadata), \
     INIT_ID(method), \
     INIT_ID(mod), \
     INIT_ID(mode), \
@@ -1044,6 +1066,7 @@ extern "C" {
     INIT_ID(newline), \
     INIT_ID(newlines), \
     INIT_ID(next), \
+    INIT_ID(nlocals), \
     INIT_ID(node_depth), \
     INIT_ID(node_offset), \
     INIT_ID(ns), \
@@ -1067,6 +1090,7 @@ extern "C" {
     INIT_ID(optimize), \
     INIT_ID(options), \
     INIT_ID(order), \
+    INIT_ID(origin), \
     INIT_ID(out_fd), \
     INIT_ID(outgoing), \
     INIT_ID(overlapped), \
@@ -1112,6 +1136,7 @@ extern "C" {
     INIT_ID(reducer_override), \
     INIT_ID(registry), \
     INIT_ID(rel_tol), \
+    INIT_ID(release), \
     INIT_ID(reload), \
     INIT_ID(repl), \
     INIT_ID(replace), \
@@ -1163,6 +1188,7 @@ extern "C" {
     INIT_ID(stdin), \
     INIT_ID(stdout), \
     INIT_ID(step), \
+    INIT_ID(steps), \
     INIT_ID(store_name), \
     INIT_ID(strategy), \
     INIT_ID(strftime), \
@@ -1199,6 +1225,7 @@ extern "C" {
     INIT_ID(twice), \
     INIT_ID(txt), \
     INIT_ID(type), \
+    INIT_ID(type_params), \
     INIT_ID(tz), \
     INIT_ID(tzname), \
     INIT_ID(uid), \
diff -pruN 3.12.0~a7-1/Include/internal/pycore_structseq.h 3.12.0~b1-1/Include/internal/pycore_structseq.h
--- 3.12.0~a7-1/Include/internal/pycore_structseq.h	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Include/internal/pycore_structseq.h	2023-05-22 12:07:36.000000000 +0000
@@ -15,19 +15,23 @@ PyAPI_FUNC(PyTypeObject *) _PyStructSequ
     PyStructSequence_Desc *desc,
     unsigned long tp_flags);
 
-PyAPI_FUNC(int) _PyStructSequence_InitBuiltinWithFlags(
+extern int _PyStructSequence_InitBuiltinWithFlags(
+    PyInterpreterState *interp,
     PyTypeObject *type,
     PyStructSequence_Desc *desc,
     unsigned long tp_flags);
 
 static inline int
-_PyStructSequence_InitBuiltin(PyTypeObject *type,
+_PyStructSequence_InitBuiltin(PyInterpreterState *interp,
+                              PyTypeObject *type,
                               PyStructSequence_Desc *desc)
 {
-    return _PyStructSequence_InitBuiltinWithFlags(type, desc, 0);
+    return _PyStructSequence_InitBuiltinWithFlags(interp, type, desc, 0);
 }
 
-extern void _PyStructSequence_FiniType(PyTypeObject *type);
+extern void _PyStructSequence_FiniBuiltin(
+    PyInterpreterState *interp,
+    PyTypeObject *type);
 
 #ifdef __cplusplus
 }
diff -pruN 3.12.0~a7-1/Include/internal/pycore_symtable.h 3.12.0~b1-1/Include/internal/pycore_symtable.h
--- 3.12.0~a7-1/Include/internal/pycore_symtable.h	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Include/internal/pycore_symtable.h	2023-05-22 12:07:36.000000000 +0000
@@ -10,8 +10,17 @@ extern "C" {
 
 struct _mod;   // Type defined in pycore_ast.h
 
-typedef enum _block_type { FunctionBlock, ClassBlock, ModuleBlock, AnnotationBlock }
-    _Py_block_ty;
+typedef enum _block_type {
+    FunctionBlock, ClassBlock, ModuleBlock,
+    // Used for annotations if 'from __future__ import annotations' is active.
+    // Annotation blocks cannot bind names and are not evaluated.
+    AnnotationBlock,
+    // Used for generics and type aliases. These work mostly like functions
+    // (see PEP 695 for details). The three different blocks function identically;
+    // they are different enum entries only so that error messages can be more
+    // precise.
+    TypeVarBoundBlock, TypeAliasBlock, TypeParamBlock
+} _Py_block_ty;
 
 typedef enum _comprehension_type {
     NoComprehension = 0,
@@ -49,7 +58,7 @@ typedef struct _symtable_entry {
     PyObject *ste_varnames;  /* list of function parameters */
     PyObject *ste_children;  /* list of child blocks */
     PyObject *ste_directives;/* locations of global and nonlocal statements */
-    _Py_block_ty ste_type;   /* module, class, function or annotation */
+    _Py_block_ty ste_type;
     int ste_nested;      /* true if block is nested */
     unsigned ste_free : 1;        /* true if block has free variables */
     unsigned ste_child_free : 1;  /* true if a child block has free vars,
@@ -64,7 +73,12 @@ typedef struct _symtable_entry {
     unsigned ste_needs_class_closure : 1; /* for class scopes, true if a
                                              closure over __class__
                                              should be created */
+    unsigned ste_needs_classdict : 1; /* for class scopes, true if a closure
+                                         over the class dict should be created */
+    unsigned ste_comp_inlined : 1; /* true if this comprehension is inlined */
     unsigned ste_comp_iter_target : 1; /* true if visiting comprehension target */
+    unsigned ste_can_see_class_scope : 1; /* true if this block can see names bound in an
+                                             enclosing class scope */
     int ste_comp_iter_expr; /* non-zero if visiting a comprehension range expression */
     int ste_lineno;          /* first line of block */
     int ste_col_offset;      /* offset of first line of block */
@@ -81,6 +95,7 @@ extern PyTypeObject PySTEntry_Type;
 
 extern long _PyST_GetSymbol(PySTEntryObject *, PyObject *);
 extern int _PyST_GetScope(PySTEntryObject *, PyObject *);
+extern int _PyST_IsFunctionLike(PySTEntryObject *);
 
 extern struct symtable* _PySymtable_Build(
     struct _mod *mod,
@@ -104,14 +119,16 @@ extern PyObject* _Py_Mangle(PyObject *p,
 #define DEF_IMPORT 2<<6        /* assignment occurred via import */
 #define DEF_ANNOT 2<<7         /* this name is annotated */
 #define DEF_COMP_ITER 2<<8     /* this name is a comprehension iteration variable */
+#define DEF_TYPE_PARAM 2<<9    /* this name is a type parameter */
+#define DEF_COMP_CELL 2<<10    /* this name is a cell in an inlined comprehension */
 
 #define DEF_BOUND (DEF_LOCAL | DEF_PARAM | DEF_IMPORT)
 
 /* GLOBAL_EXPLICIT and GLOBAL_IMPLICIT are used internally by the symbol
    table.  GLOBAL is returned from PyST_GetScope() for either of them.
-   It is stored in ste_symbols at bits 12-15.
+   It is stored in ste_symbols at bits 13-16.
 */
-#define SCOPE_OFFSET 11
+#define SCOPE_OFFSET 12
 #define SCOPE_MASK (DEF_GLOBAL | DEF_LOCAL | DEF_PARAM | DEF_NONLOCAL)
 
 #define LOCAL 1
diff -pruN 3.12.0~a7-1/Include/internal/pycore_token.h 3.12.0~b1-1/Include/internal/pycore_token.h
--- 3.12.0~a7-1/Include/internal/pycore_token.h	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Include/internal/pycore_token.h	2023-05-22 12:07:36.000000000 +0000
@@ -67,14 +67,20 @@ extern "C" {
 #define RARROW          51
 #define ELLIPSIS        52
 #define COLONEQUAL      53
-#define OP              54
-#define AWAIT           55
-#define ASYNC           56
-#define TYPE_IGNORE     57
-#define TYPE_COMMENT    58
-#define SOFT_KEYWORD    59
-#define ERRORTOKEN      60
-#define N_TOKENS        64
+#define EXCLAMATION     54
+#define OP              55
+#define AWAIT           56
+#define ASYNC           57
+#define TYPE_IGNORE     58
+#define TYPE_COMMENT    59
+#define SOFT_KEYWORD    60
+#define FSTRING_START   61
+#define FSTRING_MIDDLE  62
+#define FSTRING_END     63
+#define COMMENT         64
+#define NL              65
+#define ERRORTOKEN      66
+#define N_TOKENS        68
 #define NT_OFFSET       256
 
 /* Special definitions for cooperation with parser */
@@ -86,6 +92,8 @@ extern "C" {
                                  (x) == NEWLINE   || \
                                  (x) == INDENT    || \
                                  (x) == DEDENT)
+#define ISSTRINGLIT(x)          ((x) == STRING           || \
+                                 (x) == FSTRING_MIDDLE)
 
 
 // Symbols exported for test_peg_generator
diff -pruN 3.12.0~a7-1/Include/internal/pycore_tuple.h 3.12.0~b1-1/Include/internal/pycore_tuple.h
--- 3.12.0~a7-1/Include/internal/pycore_tuple.h	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Include/internal/pycore_tuple.h	2023-05-22 12:07:36.000000000 +0000
@@ -14,7 +14,6 @@ extern "C" {
 /* runtime lifecycle */
 
 extern PyStatus _PyTuple_InitGlobalObjects(PyInterpreterState *);
-extern PyStatus _PyTuple_InitTypes(PyInterpreterState *);
 extern void _PyTuple_Fini(PyInterpreterState *);
 
 
diff -pruN 3.12.0~a7-1/Include/internal/pycore_typeobject.h 3.12.0~b1-1/Include/internal/pycore_typeobject.h
--- 3.12.0~a7-1/Include/internal/pycore_typeobject.h	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Include/internal/pycore_typeobject.h	2023-05-22 12:07:36.000000000 +0000
@@ -11,22 +11,17 @@ extern "C" {
 #endif
 
 
-/* runtime lifecycle */
+/* state */
 
-extern PyStatus _PyTypes_InitTypes(PyInterpreterState *);
-extern void _PyTypes_FiniTypes(PyInterpreterState *);
-extern void _PyTypes_Fini(PyInterpreterState *);
-
-
-/* other API */
-
-/* Length of array of slotdef pointers used to store slots with the
-   same __name__.  There should be at most MAX_EQUIV-1 slotdef entries with
-   the same __name__, for any __name__. Since that's a static property, it is
-   appropriate to declare fixed-size arrays for this. */
-#define MAX_EQUIV 10
+#define _Py_TYPE_BASE_VERSION_TAG (2<<16)
+#define _Py_MAX_GLOBAL_TYPE_VERSION_TAG (_Py_TYPE_BASE_VERSION_TAG - 1)
 
-typedef struct wrapperbase pytype_slotdef;
+struct _types_runtime_state {
+    /* Used to set PyTypeObject.tp_version_tag for core static types. */
+    // bpo-42745: next_version_tag remains shared by all interpreters
+    // because of static types.
+    unsigned int next_version_tag;
+};
 
 
 // Type attribute lookup cache: speed up attribute and method lookups,
@@ -49,6 +44,13 @@ struct type_cache {
 
 typedef struct {
     PyTypeObject *type;
+    int readying;
+    int ready;
+    // XXX tp_dict, tp_bases, and tp_mro can probably be statically
+    // allocated, instead of dynamically and stored on the interpreter.
+    PyObject *tp_dict;
+    PyObject *tp_bases;
+    PyObject *tp_mro;
     PyObject *tp_subclasses;
     /* We never clean up weakrefs for static builtin types since
        they will effectively never get triggered.  However, there
@@ -57,6 +59,36 @@ typedef struct {
     PyObject *tp_weaklist;
 } static_builtin_state;
 
+struct types_state {
+    /* Used to set PyTypeObject.tp_version_tag.
+       It starts at _Py_MAX_GLOBAL_TYPE_VERSION_TAG + 1,
+       where all those lower numbers are used for core static types. */
+    unsigned int next_version_tag;
+
+    struct type_cache type_cache;
+    size_t num_builtins_initialized;
+    static_builtin_state builtins[_Py_MAX_STATIC_BUILTIN_TYPES];
+};
+
+
+/* runtime lifecycle */
+
+extern PyStatus _PyTypes_InitTypes(PyInterpreterState *);
+extern void _PyTypes_FiniTypes(PyInterpreterState *);
+extern void _PyTypes_Fini(PyInterpreterState *);
+
+
+/* other API */
+
+/* Length of array of slotdef pointers used to store slots with the
+   same __name__.  There should be at most MAX_EQUIV-1 slotdef entries with
+   the same __name__, for any __name__. Since that's a static property, it is
+   appropriate to declare fixed-size arrays for this. */
+#define MAX_EQUIV 10
+
+typedef struct wrapperbase pytype_slotdef;
+
+
 static inline PyObject **
 _PyStaticType_GET_WEAKREFS_LISTPTR(static_builtin_state *state)
 {
@@ -78,17 +110,25 @@ _PyType_GetModuleState(PyTypeObject *typ
     return mod->md_state;
 }
 
-struct types_state {
-    struct type_cache type_cache;
-    size_t num_builtins_initialized;
-    static_builtin_state builtins[_Py_MAX_STATIC_BUILTIN_TYPES];
-};
 
-
-extern int _PyStaticType_InitBuiltin(PyTypeObject *type);
-extern static_builtin_state * _PyStaticType_GetState(PyTypeObject *);
-extern void _PyStaticType_ClearWeakRefs(PyTypeObject *type);
-extern void _PyStaticType_Dealloc(PyTypeObject *type);
+extern int _PyStaticType_InitBuiltin(PyInterpreterState *, PyTypeObject *type);
+extern static_builtin_state * _PyStaticType_GetState(PyInterpreterState *, PyTypeObject *);
+extern void _PyStaticType_ClearWeakRefs(PyInterpreterState *, PyTypeObject *type);
+extern void _PyStaticType_Dealloc(PyInterpreterState *, PyTypeObject *);
+
+PyAPI_FUNC(PyObject *) _PyType_GetDict(PyTypeObject *);
+extern PyObject * _PyType_GetBases(PyTypeObject *type);
+extern PyObject * _PyType_GetMRO(PyTypeObject *type);
+extern PyObject* _PyType_GetSubclasses(PyTypeObject *);
+extern int _PyType_HasSubclasses(PyTypeObject *);
+
+// PyType_Ready() must be called if _PyType_IsReady() is false.
+// See also the Py_TPFLAGS_READY flag.
+static inline int
+_PyType_IsReady(PyTypeObject *type)
+{
+    return _PyType_GetDict(type) != NULL;
+}
 
 PyObject *
 _Py_type_getattro_impl(PyTypeObject *type, PyObject *name, int *suppress_missing_attribute);
@@ -98,6 +138,11 @@ _Py_type_getattro(PyTypeObject *type, Py
 PyObject *_Py_slot_tp_getattro(PyObject *self, PyObject *name);
 PyObject *_Py_slot_tp_getattr_hook(PyObject *self, PyObject *name);
 
+PyAPI_DATA(PyTypeObject) _PyBufferWrapper_Type;
+
+PyObject *
+_PySuper_Lookup(PyTypeObject *su_type, PyObject *su_obj, PyObject *name, int *meth_found);
+
 #ifdef __cplusplus
 }
 #endif
diff -pruN 3.12.0~a7-1/Include/internal/pycore_typevarobject.h 3.12.0~b1-1/Include/internal/pycore_typevarobject.h
--- 3.12.0~a7-1/Include/internal/pycore_typevarobject.h	1970-01-01 00:00:00.000000000 +0000
+++ 3.12.0~b1-1/Include/internal/pycore_typevarobject.h	2023-05-22 12:07:36.000000000 +0000
@@ -0,0 +1,24 @@
+#ifndef Py_INTERNAL_TYPEVAROBJECT_H
+#define Py_INTERNAL_TYPEVAROBJECT_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef Py_BUILD_CORE
+#  error "this header requires Py_BUILD_CORE define"
+#endif
+
+extern PyObject *_Py_make_typevar(PyObject *, PyObject *, PyObject *);
+extern PyObject *_Py_make_paramspec(PyThreadState *, PyObject *);
+extern PyObject *_Py_make_typevartuple(PyThreadState *, PyObject *);
+extern PyObject *_Py_make_typealias(PyThreadState *, PyObject *);
+extern PyObject *_Py_subscript_generic(PyThreadState *, PyObject *);
+extern int _Py_initialize_generic(PyInterpreterState *);
+extern void _Py_clear_generic_types(PyInterpreterState *);
+
+extern PyTypeObject _PyTypeAlias_Type;
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !Py_INTERNAL_TYPEVAROBJECT_H */
diff -pruN 3.12.0~a7-1/Include/internal/pycore_unicodeobject.h 3.12.0~b1-1/Include/internal/pycore_unicodeobject.h
--- 3.12.0~a7-1/Include/internal/pycore_unicodeobject.h	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Include/internal/pycore_unicodeobject.h	2023-05-22 12:07:36.000000000 +0000
@@ -12,6 +12,7 @@ extern "C" {
 #include "pycore_ucnhash.h"       // _PyUnicode_Name_CAPI
 
 void _PyUnicode_ExactDealloc(PyObject *op);
+Py_ssize_t _PyUnicode_InternedSize(void);
 
 /* runtime lifecycle */
 
diff -pruN 3.12.0~a7-1/Include/internal/pycore_unicodeobject_generated.h 3.12.0~b1-1/Include/internal/pycore_unicodeobject_generated.h
--- 3.12.0~a7-1/Include/internal/pycore_unicodeobject_generated.h	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Include/internal/pycore_unicodeobject_generated.h	2023-05-22 12:07:36.000000000 +0000
@@ -96,6 +96,9 @@ _PyUnicode_InitStaticStrings(PyInterpret
     string = &_Py_ID(__bool__);
     assert(_PyUnicode_CheckConsistency(string, 1));
     _PyUnicode_InternInPlace(interp, &string);
+    string = &_Py_ID(__buffer__);
+    assert(_PyUnicode_CheckConsistency(string, 1));
+    _PyUnicode_InternInPlace(interp, &string);
     string = &_Py_ID(__build_class__);
     assert(_PyUnicode_CheckConsistency(string, 1));
     _PyUnicode_InternInPlace(interp, &string);
@@ -120,6 +123,12 @@ _PyUnicode_InitStaticStrings(PyInterpret
     string = &_Py_ID(__classcell__);
     assert(_PyUnicode_CheckConsistency(string, 1));
     _PyUnicode_InternInPlace(interp, &string);
+    string = &_Py_ID(__classdict__);
+    assert(_PyUnicode_CheckConsistency(string, 1));
+    _PyUnicode_InternInPlace(interp, &string);
+    string = &_Py_ID(__classdictcell__);
+    assert(_PyUnicode_CheckConsistency(string, 1));
+    _PyUnicode_InternInPlace(interp, &string);
     string = &_Py_ID(__complex__);
     assert(_PyUnicode_CheckConsistency(string, 1));
     _PyUnicode_InternInPlace(interp, &string);
@@ -393,6 +402,9 @@ _PyUnicode_InitStaticStrings(PyInterpret
     string = &_Py_ID(__reduce_ex__);
     assert(_PyUnicode_CheckConsistency(string, 1));
     _PyUnicode_InternInPlace(interp, &string);
+    string = &_Py_ID(__release_buffer__);
+    assert(_PyUnicode_CheckConsistency(string, 1));
+    _PyUnicode_InternInPlace(interp, &string);
     string = &_Py_ID(__repr__);
     assert(_PyUnicode_CheckConsistency(string, 1));
     _PyUnicode_InternInPlace(interp, &string);
@@ -483,6 +495,9 @@ _PyUnicode_InitStaticStrings(PyInterpret
     string = &_Py_ID(__trunc__);
     assert(_PyUnicode_CheckConsistency(string, 1));
     _PyUnicode_InternInPlace(interp, &string);
+    string = &_Py_ID(__type_params__);
+    assert(_PyUnicode_CheckConsistency(string, 1));
+    _PyUnicode_InternInPlace(interp, &string);
     string = &_Py_ID(__typing_is_unpacked_typevartuple__);
     assert(_PyUnicode_CheckConsistency(string, 1));
     _PyUnicode_InternInPlace(interp, &string);
@@ -648,12 +663,21 @@ _PyUnicode_InitStaticStrings(PyInterpret
     string = &_Py_ID(aggregate_class);
     assert(_PyUnicode_CheckConsistency(string, 1));
     _PyUnicode_InternInPlace(interp, &string);
+    string = &_Py_ID(alias);
+    assert(_PyUnicode_CheckConsistency(string, 1));
+    _PyUnicode_InternInPlace(interp, &string);
     string = &_Py_ID(append);
     assert(_PyUnicode_CheckConsistency(string, 1));
     _PyUnicode_InternInPlace(interp, &string);
+    string = &_Py_ID(arg);
+    assert(_PyUnicode_CheckConsistency(string, 1));
+    _PyUnicode_InternInPlace(interp, &string);
     string = &_Py_ID(argdefs);
     assert(_PyUnicode_CheckConsistency(string, 1));
     _PyUnicode_InternInPlace(interp, &string);
+    string = &_Py_ID(args);
+    assert(_PyUnicode_CheckConsistency(string, 1));
+    _PyUnicode_InternInPlace(interp, &string);
     string = &_Py_ID(arguments);
     assert(_PyUnicode_CheckConsistency(string, 1));
     _PyUnicode_InternInPlace(interp, &string);
@@ -696,6 +720,9 @@ _PyUnicode_InitStaticStrings(PyInterpret
     string = &_Py_ID(block);
     assert(_PyUnicode_CheckConsistency(string, 1));
     _PyUnicode_InternInPlace(interp, &string);
+    string = &_Py_ID(bound);
+    assert(_PyUnicode_CheckConsistency(string, 1));
+    _PyUnicode_InternInPlace(interp, &string);
     string = &_Py_ID(buffer);
     assert(_PyUnicode_CheckConsistency(string, 1));
     _PyUnicode_InternInPlace(interp, &string);
@@ -852,12 +879,18 @@ _PyUnicode_InitStaticStrings(PyInterpret
     string = &_Py_ID(comment_factory);
     assert(_PyUnicode_CheckConsistency(string, 1));
     _PyUnicode_InternInPlace(interp, &string);
+    string = &_Py_ID(compile_mode);
+    assert(_PyUnicode_CheckConsistency(string, 1));
+    _PyUnicode_InternInPlace(interp, &string);
     string = &_Py_ID(consts);
     assert(_PyUnicode_CheckConsistency(string, 1));
     _PyUnicode_InternInPlace(interp, &string);
     string = &_Py_ID(context);
     assert(_PyUnicode_CheckConsistency(string, 1));
     _PyUnicode_InternInPlace(interp, &string);
+    string = &_Py_ID(contravariant);
+    assert(_PyUnicode_CheckConsistency(string, 1));
+    _PyUnicode_InternInPlace(interp, &string);
     string = &_Py_ID(cookie);
     assert(_PyUnicode_CheckConsistency(string, 1));
     _PyUnicode_InternInPlace(interp, &string);
@@ -873,6 +906,9 @@ _PyUnicode_InitStaticStrings(PyInterpret
     string = &_Py_ID(count);
     assert(_PyUnicode_CheckConsistency(string, 1));
     _PyUnicode_InternInPlace(interp, &string);
+    string = &_Py_ID(covariant);
+    assert(_PyUnicode_CheckConsistency(string, 1));
+    _PyUnicode_InternInPlace(interp, &string);
     string = &_Py_ID(cwd);
     assert(_PyUnicode_CheckConsistency(string, 1));
     _PyUnicode_InternInPlace(interp, &string);
@@ -963,6 +999,9 @@ _PyUnicode_InitStaticStrings(PyInterpret
     string = &_Py_ID(e);
     assert(_PyUnicode_CheckConsistency(string, 1));
     _PyUnicode_InternInPlace(interp, &string);
+    string = &_Py_ID(eager_start);
+    assert(_PyUnicode_CheckConsistency(string, 1));
+    _PyUnicode_InternInPlace(interp, &string);
     string = &_Py_ID(effective_ids);
     assert(_PyUnicode_CheckConsistency(string, 1));
     _PyUnicode_InternInPlace(interp, &string);
@@ -987,6 +1026,9 @@ _PyUnicode_InitStaticStrings(PyInterpret
     string = &_Py_ID(endpos);
     assert(_PyUnicode_CheckConsistency(string, 1));
     _PyUnicode_InternInPlace(interp, &string);
+    string = &_Py_ID(entrypoint);
+    assert(_PyUnicode_CheckConsistency(string, 1));
+    _PyUnicode_InternInPlace(interp, &string);
     string = &_Py_ID(env);
     assert(_PyUnicode_CheckConsistency(string, 1));
     _PyUnicode_InternInPlace(interp, &string);
@@ -1017,6 +1059,9 @@ _PyUnicode_InitStaticStrings(PyInterpret
     string = &_Py_ID(extend);
     assert(_PyUnicode_CheckConsistency(string, 1));
     _PyUnicode_InternInPlace(interp, &string);
+    string = &_Py_ID(extra_tokens);
+    assert(_PyUnicode_CheckConsistency(string, 1));
+    _PyUnicode_InternInPlace(interp, &string);
     string = &_Py_ID(facility);
     assert(_PyUnicode_CheckConsistency(string, 1));
     _PyUnicode_InternInPlace(interp, &string);
@@ -1194,6 +1239,9 @@ _PyUnicode_InitStaticStrings(PyInterpret
     string = &_Py_ID(inf);
     assert(_PyUnicode_CheckConsistency(string, 1));
     _PyUnicode_InternInPlace(interp, &string);
+    string = &_Py_ID(infer_variance);
+    assert(_PyUnicode_CheckConsistency(string, 1));
+    _PyUnicode_InternInPlace(interp, &string);
     string = &_Py_ID(inheritable);
     assert(_PyUnicode_CheckConsistency(string, 1));
     _PyUnicode_InternInPlace(interp, &string);
@@ -1230,6 +1278,9 @@ _PyUnicode_InitStaticStrings(PyInterpret
     string = &_Py_ID(intersection);
     assert(_PyUnicode_CheckConsistency(string, 1));
     _PyUnicode_InternInPlace(interp, &string);
+    string = &_Py_ID(is_running);
+    assert(_PyUnicode_CheckConsistency(string, 1));
+    _PyUnicode_InternInPlace(interp, &string);
     string = &_Py_ID(isatty);
     assert(_PyUnicode_CheckConsistency(string, 1));
     _PyUnicode_InternInPlace(interp, &string);
@@ -1395,6 +1446,9 @@ _PyUnicode_InitStaticStrings(PyInterpret
     string = &_Py_ID(metaclass);
     assert(_PyUnicode_CheckConsistency(string, 1));
     _PyUnicode_InternInPlace(interp, &string);
+    string = &_Py_ID(metadata);
+    assert(_PyUnicode_CheckConsistency(string, 1));
+    _PyUnicode_InternInPlace(interp, &string);
     string = &_Py_ID(method);
     assert(_PyUnicode_CheckConsistency(string, 1));
     _PyUnicode_InternInPlace(interp, &string);
@@ -1467,6 +1521,9 @@ _PyUnicode_InitStaticStrings(PyInterpret
     string = &_Py_ID(next);
     assert(_PyUnicode_CheckConsistency(string, 1));
     _PyUnicode_InternInPlace(interp, &string);
+    string = &_Py_ID(nlocals);
+    assert(_PyUnicode_CheckConsistency(string, 1));
+    _PyUnicode_InternInPlace(interp, &string);
     string = &_Py_ID(node_depth);
     assert(_PyUnicode_CheckConsistency(string, 1));
     _PyUnicode_InternInPlace(interp, &string);
@@ -1536,6 +1593,9 @@ _PyUnicode_InitStaticStrings(PyInterpret
     string = &_Py_ID(order);
     assert(_PyUnicode_CheckConsistency(string, 1));
     _PyUnicode_InternInPlace(interp, &string);
+    string = &_Py_ID(origin);
+    assert(_PyUnicode_CheckConsistency(string, 1));
+    _PyUnicode_InternInPlace(interp, &string);
     string = &_Py_ID(out_fd);
     assert(_PyUnicode_CheckConsistency(string, 1));
     _PyUnicode_InternInPlace(interp, &string);
@@ -1671,6 +1731,9 @@ _PyUnicode_InitStaticStrings(PyInterpret
     string = &_Py_ID(rel_tol);
     assert(_PyUnicode_CheckConsistency(string, 1));
     _PyUnicode_InternInPlace(interp, &string);
+    string = &_Py_ID(release);
+    assert(_PyUnicode_CheckConsistency(string, 1));
+    _PyUnicode_InternInPlace(interp, &string);
     string = &_Py_ID(reload);
     assert(_PyUnicode_CheckConsistency(string, 1));
     _PyUnicode_InternInPlace(interp, &string);
@@ -1824,6 +1887,9 @@ _PyUnicode_InitStaticStrings(PyInterpret
     string = &_Py_ID(step);
     assert(_PyUnicode_CheckConsistency(string, 1));
     _PyUnicode_InternInPlace(interp, &string);
+    string = &_Py_ID(steps);
+    assert(_PyUnicode_CheckConsistency(string, 1));
+    _PyUnicode_InternInPlace(interp, &string);
     string = &_Py_ID(store_name);
     assert(_PyUnicode_CheckConsistency(string, 1));
     _PyUnicode_InternInPlace(interp, &string);
@@ -1932,6 +1998,9 @@ _PyUnicode_InitStaticStrings(PyInterpret
     string = &_Py_ID(type);
     assert(_PyUnicode_CheckConsistency(string, 1));
     _PyUnicode_InternInPlace(interp, &string);
+    string = &_Py_ID(type_params);
+    assert(_PyUnicode_CheckConsistency(string, 1));
+    _PyUnicode_InternInPlace(interp, &string);
     string = &_Py_ID(tz);
     assert(_PyUnicode_CheckConsistency(string, 1));
     _PyUnicode_InternInPlace(interp, &string);
diff -pruN 3.12.0~a7-1/Include/moduleobject.h 3.12.0~b1-1/Include/moduleobject.h
--- 3.12.0~a7-1/Include/moduleobject.h	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Include/moduleobject.h	2023-05-22 12:07:36.000000000 +0000
@@ -78,11 +78,17 @@ struct PyModuleDef_Slot {
 
 #define Py_mod_create 1
 #define Py_mod_exec 2
+#define Py_mod_multiple_interpreters 3
 
 #ifndef Py_LIMITED_API
-#define _Py_mod_LAST_SLOT 2
+#define _Py_mod_LAST_SLOT 3
 #endif
 
+/* for Py_mod_multiple_interpreters: */
+#define Py_MOD_MULTIPLE_INTERPRETERS_NOT_SUPPORTED ((void *)0)
+#define Py_MOD_MULTIPLE_INTERPRETERS_SUPPORTED ((void *)1)
+#define Py_MOD_PER_INTERPRETER_GIL_SUPPORTED ((void *)2)
+
 #endif /* New in 3.5 */
 
 struct PyModuleDef {
diff -pruN 3.12.0~a7-1/Include/object.h 3.12.0~b1-1/Include/object.h
--- 3.12.0~a7-1/Include/object.h	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Include/object.h	2023-05-22 12:07:36.000000000 +0000
@@ -78,12 +78,76 @@ whose size is determined when the object
 /* PyObject_HEAD defines the initial segment of every PyObject. */
 #define PyObject_HEAD                   PyObject ob_base;
 
-#define PyObject_HEAD_INIT(type)        \
-    { _PyObject_EXTRA_INIT              \
-    1, (type) },
+/*
+Immortalization:
+
+The following indicates the immortalization strategy depending on the amount
+of available bits in the reference count field. All strategies are backwards
+compatible but the specific reference count value or immortalization check
+might change depending on the specializations for the underlying system.
+
+Proper deallocation of immortal instances requires distinguishing between
+statically allocated immortal instances vs those promoted by the runtime to be
+immortal. The latter should be the only instances that require
+cleanup during runtime finalization.
+*/
+
+#if SIZEOF_VOID_P > 4
+/*
+In 64+ bit systems, an object will be marked as immortal by setting all of the
+lower 32 bits of the reference count field, which is equal to: 0xFFFFFFFF
+
+Using the lower 32 bits makes the value backwards compatible by allowing
+C-Extensions without the updated checks in Py_INCREF and Py_DECREF to safely
+increase and decrease the objects reference count. The object would lose its
+immortality, but the execution would still be correct.
+
+Reference count increases will use saturated arithmetic, taking advantage of
+having all the lower 32 bits set, which will avoid the reference count to go
+beyond the refcount limit. Immortality checks for reference count decreases will
+be done by checking the bit sign flag in the lower 32 bits.
+*/
+#define _Py_IMMORTAL_REFCNT UINT_MAX
+
+#else
+/*
+In 32 bit systems, an object will be marked as immortal by setting all of the
+lower 30 bits of the reference count field, which is equal to: 0x3FFFFFFF
 
-#define PyVarObject_HEAD_INIT(type, size)       \
-    { PyObject_HEAD_INIT(type) (size) },
+Using the lower 30 bits makes the value backwards compatible by allowing
+C-Extensions without the updated checks in Py_INCREF and Py_DECREF to safely
+increase and decrease the objects reference count. The object would lose its
+immortality, but the execution would still be correct.
+
+Reference count increases and decreases will first go through an immortality
+check by comparing the reference count field to the immortality reference count.
+*/
+#define _Py_IMMORTAL_REFCNT (UINT_MAX >> 2)
+#endif
+
+// Make all internal uses of PyObject_HEAD_INIT immortal while preserving the
+// C-API expectation that the refcnt will be set to 1.
+#ifdef Py_BUILD_CORE
+#define PyObject_HEAD_INIT(type)    \
+    {                               \
+        _PyObject_EXTRA_INIT        \
+        { _Py_IMMORTAL_REFCNT },    \
+        (type)                      \
+    },
+#else
+#define PyObject_HEAD_INIT(type) \
+    {                            \
+        _PyObject_EXTRA_INIT     \
+        { 1 },                   \
+        (type)                   \
+    },
+#endif /* Py_BUILD_CORE */
+
+#define PyVarObject_HEAD_INIT(type, size) \
+    {                                     \
+        PyObject_HEAD_INIT(type)          \
+        (size)                            \
+    },
 
 /* PyObject_VAR_HEAD defines the initial segment of all variable-size
  * container objects.  These end with a declaration of an array with 1
@@ -101,7 +165,12 @@ whose size is determined when the object
  */
 struct _object {
     _PyObject_HEAD_EXTRA
-    Py_ssize_t ob_refcnt;
+    union {
+       Py_ssize_t ob_refcnt;
+#if SIZEOF_VOID_P > 4
+       PY_UINT32_T ob_refcnt_split[2];
+#endif
+    };
     PyTypeObject *ob_type;
 };
 
@@ -152,6 +221,15 @@ static inline Py_ssize_t Py_SIZE(PyObjec
 #  define Py_SIZE(ob) Py_SIZE(_PyObject_CAST(ob))
 #endif
 
+static inline Py_ALWAYS_INLINE int _Py_IsImmortal(PyObject *op)
+{
+#if SIZEOF_VOID_P > 4
+    return _Py_CAST(PY_INT32_T, op->ob_refcnt) < 0;
+#else
+    return op->ob_refcnt == _Py_IMMORTAL_REFCNT;
+#endif
+}
+#define _Py_IsImmortal(op) _Py_IsImmortal(_PyObject_CAST(op))
 
 static inline int Py_IS_TYPE(PyObject *ob, PyTypeObject *type) {
     return Py_TYPE(ob) == type;
@@ -162,6 +240,13 @@ static inline int Py_IS_TYPE(PyObject *o
 
 
 static inline void Py_SET_REFCNT(PyObject *ob, Py_ssize_t refcnt) {
+    // This immortal check is for code that is unaware of immortal objects.
+    // The runtime tracks these objects and we should avoid as much
+    // as possible having extensions inadvertently change the refcnt
+    // of an immortalized object.
+    if (_Py_IsImmortal(ob)) {
+        return;
+    }
     ob->ob_refcnt = refcnt;
 }
 #if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000
@@ -270,6 +355,8 @@ PyAPI_FUNC(PyObject *) PyType_GetQualNam
 #endif
 #if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x030C0000
 PyAPI_FUNC(PyObject *) PyType_FromMetaclass(PyTypeObject*, PyObject*, PyType_Spec*, PyObject*);
+PyAPI_FUNC(void *) PyObject_GetTypeData(PyObject *obj, PyTypeObject *cls);
+PyAPI_FUNC(Py_ssize_t) PyType_GetTypeDataSize(PyTypeObject *cls);
 #endif
 
 /* Generic type check */
@@ -436,6 +523,9 @@ given type object has a specified featur
 // subject itself (rather than a mapped attribute on it):
 #define _Py_TPFLAGS_MATCH_SELF (1UL << 22)
 
+/* Items (ob_size*tp_itemsize) are found at the end of an instance's memory */
+#define Py_TPFLAGS_ITEMS_AT_END (1UL << 23)
+
 /* These flags are used to determine if a type is a subclass. */
 #define Py_TPFLAGS_LONG_SUBCLASS        (1UL << 24)
 #define Py_TPFLAGS_LIST_SUBCLASS        (1UL << 25)
@@ -524,19 +614,33 @@ PyAPI_FUNC(void) Py_DecRef(PyObject *);
 PyAPI_FUNC(void) _Py_IncRef(PyObject *);
 PyAPI_FUNC(void) _Py_DecRef(PyObject *);
 
-static inline void Py_INCREF(PyObject *op)
+static inline Py_ALWAYS_INLINE void Py_INCREF(PyObject *op)
 {
 #if defined(Py_REF_DEBUG) && defined(Py_LIMITED_API) && Py_LIMITED_API+0 >= 0x030A0000
     // Stable ABI for Python 3.10 built in debug mode.
     _Py_IncRef(op);
 #else
-    _Py_INCREF_STAT_INC();
     // Non-limited C API and limited C API for Python 3.9 and older access
     // directly PyObject.ob_refcnt.
+#if SIZEOF_VOID_P > 4
+    // Portable saturated add, branching on the carry flag and set low bits
+    PY_UINT32_T cur_refcnt = op->ob_refcnt_split[PY_BIG_ENDIAN];
+    PY_UINT32_T new_refcnt = cur_refcnt + 1;
+    if (new_refcnt == 0) {
+        return;
+    }
+    op->ob_refcnt_split[PY_BIG_ENDIAN] = new_refcnt;
+#else
+    // Explicitly check immortality against the immortal value
+    if (_Py_IsImmortal(op)) {
+        return;
+    }
+    op->ob_refcnt++;
+#endif
+    _Py_INCREF_STAT_INC();
 #ifdef Py_REF_DEBUG
     _Py_INC_REFTOTAL();
-#endif  // Py_REF_DEBUG
-    op->ob_refcnt++;
+#endif
 #endif
 }
 #if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000
@@ -553,6 +657,9 @@ static inline void Py_DECREF(PyObject *o
 #elif defined(Py_REF_DEBUG)
 static inline void Py_DECREF(const char *filename, int lineno, PyObject *op)
 {
+    if (_Py_IsImmortal(op)) {
+        return;
+    }
     _Py_DECREF_STAT_INC();
     _Py_DEC_REFTOTAL();
     if (--op->ob_refcnt != 0) {
@@ -567,11 +674,14 @@ static inline void Py_DECREF(const char
 #define Py_DECREF(op) Py_DECREF(__FILE__, __LINE__, _PyObject_CAST(op))
 
 #else
-static inline void Py_DECREF(PyObject *op)
+static inline Py_ALWAYS_INLINE void Py_DECREF(PyObject *op)
 {
-    _Py_DECREF_STAT_INC();
     // Non-limited C API and limited C API for Python 3.9 and older access
     // directly PyObject.ob_refcnt.
+    if (_Py_IsImmortal(op)) {
+        return;
+    }
+    _Py_DECREF_STAT_INC();
     if (--op->ob_refcnt == 0) {
         _Py_Dealloc(op);
     }
@@ -721,7 +831,7 @@ PyAPI_FUNC(int) Py_IsNone(PyObject *x);
 #define Py_IsNone(x) Py_Is((x), Py_None)
 
 /* Macro for returning Py_None from a function */
-#define Py_RETURN_NONE return Py_NewRef(Py_None)
+#define Py_RETURN_NONE return Py_None
 
 /*
 Py_NotImplemented is a singleton used to signal that an operation is
@@ -731,7 +841,7 @@ PyAPI_DATA(PyObject) _Py_NotImplementedS
 #define Py_NotImplemented (&_Py_NotImplementedStruct)
 
 /* Macro for returning Py_NotImplemented from a function */
-#define Py_RETURN_NOTIMPLEMENTED return Py_NewRef(Py_NotImplemented)
+#define Py_RETURN_NOTIMPLEMENTED return Py_NotImplemented
 
 /* Rich comparison opcodes */
 #define Py_LT 0
diff -pruN 3.12.0~a7-1/Include/opcode.h 3.12.0~b1-1/Include/opcode.h
--- 3.12.0~a7-1/Include/opcode.h	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Include/opcode.h	2023-05-22 12:07:36.000000000 +0000
@@ -13,10 +13,12 @@ extern "C" {
 #define PUSH_NULL                                2
 #define INTERPRETER_EXIT                         3
 #define END_FOR                                  4
+#define END_SEND                                 5
 #define NOP                                      9
 #define UNARY_NEGATIVE                          11
 #define UNARY_NOT                               12
 #define UNARY_INVERT                            15
+#define RESERVED                                17
 #define BINARY_SUBSCR                           25
 #define BINARY_SLICE                            26
 #define STORE_SLICE                             27
@@ -43,6 +45,7 @@ extern "C" {
 #define RETURN_GENERATOR                        75
 #define RETURN_VALUE                            83
 #define SETUP_ANNOTATIONS                       85
+#define LOAD_LOCALS                             87
 #define POP_EXCEPT                              89
 #define HAVE_ARGUMENT                           90
 #define STORE_NAME                              90
@@ -93,12 +96,13 @@ extern "C" {
 #define STORE_DEREF                            138
 #define DELETE_DEREF                           139
 #define JUMP_BACKWARD                          140
+#define LOAD_SUPER_ATTR                        141
 #define CALL_FUNCTION_EX                       142
+#define LOAD_FAST_AND_CLEAR                    143
 #define EXTENDED_ARG                           144
 #define LIST_APPEND                            145
 #define SET_ADD                                146
 #define MAP_ADD                                147
-#define LOAD_CLASSDEREF                        148
 #define COPY_FREE_VARS                         149
 #define YIELD_VALUE                            150
 #define RESUME                                 151
@@ -114,6 +118,27 @@ extern "C" {
 #define KW_NAMES                               172
 #define CALL_INTRINSIC_1                       173
 #define CALL_INTRINSIC_2                       174
+#define LOAD_FROM_DICT_OR_GLOBALS              175
+#define LOAD_FROM_DICT_OR_DEREF                176
+#define MIN_INSTRUMENTED_OPCODE                237
+#define INSTRUMENTED_LOAD_SUPER_ATTR           237
+#define INSTRUMENTED_POP_JUMP_IF_NONE          238
+#define INSTRUMENTED_POP_JUMP_IF_NOT_NONE      239
+#define INSTRUMENTED_RESUME                    240
+#define INSTRUMENTED_CALL                      241
+#define INSTRUMENTED_RETURN_VALUE              242
+#define INSTRUMENTED_YIELD_VALUE               243
+#define INSTRUMENTED_CALL_FUNCTION_EX          244
+#define INSTRUMENTED_JUMP_FORWARD              245
+#define INSTRUMENTED_JUMP_BACKWARD             246
+#define INSTRUMENTED_RETURN_CONST              247
+#define INSTRUMENTED_FOR_ITER                  248
+#define INSTRUMENTED_POP_JUMP_IF_FALSE         249
+#define INSTRUMENTED_POP_JUMP_IF_TRUE          250
+#define INSTRUMENTED_END_FOR                   251
+#define INSTRUMENTED_END_SEND                  252
+#define INSTRUMENTED_INSTRUCTION               253
+#define INSTRUMENTED_LINE                      254
 #define MIN_PSEUDO_OPCODE                      256
 #define SETUP_FINALLY                          256
 #define SETUP_CLEANUP                          257
@@ -122,75 +147,84 @@ extern "C" {
 #define JUMP                                   260
 #define JUMP_NO_INTERRUPT                      261
 #define LOAD_METHOD                            262
-#define MAX_PSEUDO_OPCODE                      262
-#define BINARY_OP_ADD_FLOAT                      5
-#define BINARY_OP_ADD_INT                        6
-#define BINARY_OP_ADD_UNICODE                    7
-#define BINARY_OP_INPLACE_ADD_UNICODE            8
-#define BINARY_OP_MULTIPLY_FLOAT                10
-#define BINARY_OP_MULTIPLY_INT                  13
-#define BINARY_OP_SUBTRACT_FLOAT                14
-#define BINARY_OP_SUBTRACT_INT                  16
-#define BINARY_SUBSCR_DICT                      17
-#define BINARY_SUBSCR_GETITEM                   18
-#define BINARY_SUBSCR_LIST_INT                  19
-#define BINARY_SUBSCR_TUPLE_INT                 20
-#define CALL_PY_EXACT_ARGS                      21
-#define CALL_PY_WITH_DEFAULTS                   22
-#define CALL_BOUND_METHOD_EXACT_ARGS            23
-#define CALL_BUILTIN_CLASS                      24
-#define CALL_BUILTIN_FAST_WITH_KEYWORDS         28
-#define CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS  29
-#define CALL_NO_KW_BUILTIN_FAST                 34
-#define CALL_NO_KW_BUILTIN_O                    38
-#define CALL_NO_KW_ISINSTANCE                   39
-#define CALL_NO_KW_LEN                          40
-#define CALL_NO_KW_LIST_APPEND                  41
-#define CALL_NO_KW_METHOD_DESCRIPTOR_FAST       42
-#define CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS     43
-#define CALL_NO_KW_METHOD_DESCRIPTOR_O          44
-#define CALL_NO_KW_STR_1                        45
-#define CALL_NO_KW_TUPLE_1                      46
-#define CALL_NO_KW_TYPE_1                       47
-#define COMPARE_OP_FLOAT                        48
-#define COMPARE_OP_INT                          56
-#define COMPARE_OP_STR                          57
-#define FOR_ITER_LIST                           58
-#define FOR_ITER_TUPLE                          59
-#define FOR_ITER_RANGE                          62
-#define FOR_ITER_GEN                            63
-#define LOAD_ATTR_CLASS                         64
-#define LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN       65
-#define LOAD_ATTR_INSTANCE_VALUE                66
-#define LOAD_ATTR_MODULE                        67
-#define LOAD_ATTR_PROPERTY                      70
-#define LOAD_ATTR_SLOT                          72
-#define LOAD_ATTR_WITH_HINT                     73
-#define LOAD_ATTR_METHOD_LAZY_DICT              76
-#define LOAD_ATTR_METHOD_NO_DICT                77
-#define LOAD_ATTR_METHOD_WITH_VALUES            78
-#define LOAD_CONST__LOAD_FAST                   79
-#define LOAD_FAST__LOAD_CONST                   80
-#define LOAD_FAST__LOAD_FAST                    81
-#define LOAD_GLOBAL_BUILTIN                     82
-#define LOAD_GLOBAL_MODULE                      84
-#define STORE_ATTR_INSTANCE_VALUE               86
-#define STORE_ATTR_SLOT                         87
-#define STORE_ATTR_WITH_HINT                    88
-#define STORE_FAST__LOAD_FAST                  111
-#define STORE_FAST__STORE_FAST                 112
-#define STORE_SUBSCR_DICT                      113
-#define STORE_SUBSCR_LIST_INT                  141
-#define UNPACK_SEQUENCE_LIST                   143
-#define UNPACK_SEQUENCE_TUPLE                  153
-#define UNPACK_SEQUENCE_TWO_TUPLE              154
-#define SEND_GEN                               158
-#define DO_TRACING                             255
+#define LOAD_SUPER_METHOD                      263
+#define LOAD_ZERO_SUPER_METHOD                 264
+#define LOAD_ZERO_SUPER_ATTR                   265
+#define STORE_FAST_MAYBE_NULL                  266
+#define MAX_PSEUDO_OPCODE                      266
+#define BINARY_OP_ADD_FLOAT                      6
+#define BINARY_OP_ADD_INT                        7
+#define BINARY_OP_ADD_UNICODE                    8
+#define BINARY_OP_INPLACE_ADD_UNICODE           10
+#define BINARY_OP_MULTIPLY_FLOAT                13
+#define BINARY_OP_MULTIPLY_INT                  14
+#define BINARY_OP_SUBTRACT_FLOAT                16
+#define BINARY_OP_SUBTRACT_INT                  18
+#define BINARY_SUBSCR_DICT                      19
+#define BINARY_SUBSCR_GETITEM                   20
+#define BINARY_SUBSCR_LIST_INT                  21
+#define BINARY_SUBSCR_TUPLE_INT                 22
+#define CALL_PY_EXACT_ARGS                      23
+#define CALL_PY_WITH_DEFAULTS                   24
+#define CALL_BOUND_METHOD_EXACT_ARGS            28
+#define CALL_BUILTIN_CLASS                      29
+#define CALL_BUILTIN_FAST_WITH_KEYWORDS         34
+#define CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS  38
+#define CALL_NO_KW_BUILTIN_FAST                 39
+#define CALL_NO_KW_BUILTIN_O                    40
+#define CALL_NO_KW_ISINSTANCE                   41
+#define CALL_NO_KW_LEN                          42
+#define CALL_NO_KW_LIST_APPEND                  43
+#define CALL_NO_KW_METHOD_DESCRIPTOR_FAST       44
+#define CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS     45
+#define CALL_NO_KW_METHOD_DESCRIPTOR_O          46
+#define CALL_NO_KW_STR_1                        47
+#define CALL_NO_KW_TUPLE_1                      48
+#define CALL_NO_KW_TYPE_1                       56
+#define COMPARE_OP_FLOAT                        57
+#define COMPARE_OP_INT                          58
+#define COMPARE_OP_STR                          59
+#define FOR_ITER_LIST                           62
+#define FOR_ITER_TUPLE                          63
+#define FOR_ITER_RANGE                          64
+#define FOR_ITER_GEN                            65
+#define LOAD_SUPER_ATTR_ATTR                    66
+#define LOAD_SUPER_ATTR_METHOD                  67
+#define LOAD_ATTR_CLASS                         70
+#define LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN       72
+#define LOAD_ATTR_INSTANCE_VALUE                73
+#define LOAD_ATTR_MODULE                        76
+#define LOAD_ATTR_PROPERTY                      77
+#define LOAD_ATTR_SLOT                          78
+#define LOAD_ATTR_WITH_HINT                     79
+#define LOAD_ATTR_METHOD_LAZY_DICT              80
+#define LOAD_ATTR_METHOD_NO_DICT                81
+#define LOAD_ATTR_METHOD_WITH_VALUES            82
+#define LOAD_CONST__LOAD_FAST                   84
+#define LOAD_FAST__LOAD_CONST                   86
+#define LOAD_FAST__LOAD_FAST                    88
+#define LOAD_GLOBAL_BUILTIN                    111
+#define LOAD_GLOBAL_MODULE                     112
+#define STORE_ATTR_INSTANCE_VALUE              113
+#define STORE_ATTR_SLOT                        148
+#define STORE_ATTR_WITH_HINT                   153
+#define STORE_FAST__LOAD_FAST                  154
+#define STORE_FAST__STORE_FAST                 158
+#define STORE_SUBSCR_DICT                      159
+#define STORE_SUBSCR_LIST_INT                  160
+#define UNPACK_SEQUENCE_LIST                   161
+#define UNPACK_SEQUENCE_TUPLE                  166
+#define UNPACK_SEQUENCE_TWO_TUPLE              167
+#define SEND_GEN                               168
 
 #define HAS_ARG(op) ((((op) >= HAVE_ARGUMENT) && (!IS_PSEUDO_OPCODE(op)))\
     || ((op) == JUMP) \
     || ((op) == JUMP_NO_INTERRUPT) \
     || ((op) == LOAD_METHOD) \
+    || ((op) == LOAD_SUPER_METHOD) \
+    || ((op) == LOAD_ZERO_SUPER_METHOD) \
+    || ((op) == LOAD_ZERO_SUPER_ATTR) \
+    || ((op) == STORE_FAST_MAYBE_NULL) \
     )
 
 #define HAS_CONST(op) (false\
diff -pruN 3.12.0~a7-1/Include/patchlevel.h 3.12.0~b1-1/Include/patchlevel.h
--- 3.12.0~a7-1/Include/patchlevel.h	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Include/patchlevel.h	2023-05-22 12:07:36.000000000 +0000
@@ -19,11 +19,11 @@
 #define PY_MAJOR_VERSION        3
 #define PY_MINOR_VERSION        12
 #define PY_MICRO_VERSION        0
-#define PY_RELEASE_LEVEL        PY_RELEASE_LEVEL_ALPHA
-#define PY_RELEASE_SERIAL       7
+#define PY_RELEASE_LEVEL        PY_RELEASE_LEVEL_BETA
+#define PY_RELEASE_SERIAL       1
 
 /* Version as a string */
-#define PY_VERSION              "3.12.0a7"
+#define PY_VERSION              "3.12.0b1"
 /*--end constants--*/
 
 /* Version as a single 4-byte hex number, e.g. 0x010502B2 == 1.5.2b2.
diff -pruN 3.12.0~a7-1/Include/pybuffer.h 3.12.0~b1-1/Include/pybuffer.h
--- 3.12.0~a7-1/Include/pybuffer.h	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Include/pybuffer.h	2023-05-22 12:07:36.000000000 +0000
@@ -104,7 +104,7 @@ PyAPI_FUNC(void) PyBuffer_Release(Py_buf
 /* Maximum number of dimensions */
 #define PyBUF_MAX_NDIM 64
 
-/* Flags for getting buffers */
+/* Flags for getting buffers. Keep these in sync with inspect.BufferFlags. */
 #define PyBUF_SIMPLE 0
 #define PyBUF_WRITABLE 0x0001
 
diff -pruN 3.12.0~a7-1/Include/pymacro.h 3.12.0~b1-1/Include/pymacro.h
--- 3.12.0~a7-1/Include/pymacro.h	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Include/pymacro.h	2023-05-22 12:07:36.000000000 +0000
@@ -3,20 +3,23 @@
 
 // gh-91782: On FreeBSD 12, if the _POSIX_C_SOURCE and _XOPEN_SOURCE macros are
 // defined, <sys/cdefs.h> disables C11 support and <assert.h> does not define
-// the static_assert() macro. Define the static_assert() macro in Python until
-// <sys/cdefs.h> suports C11:
+// the static_assert() macro.
 // https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=255290
-#if defined(__FreeBSD__) && !defined(static_assert)
-#  define static_assert _Static_assert
-#endif
-
-// static_assert is defined in glibc from version 2.16. Before it requires
-// compiler support (gcc >= 4.6) and is called _Static_assert.
-// In C++ 11 static_assert is a keyword, redefining is undefined behaviour.
-#if (defined(__GLIBC__) \
-     && (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 16)) \
-     && !(defined(__cplusplus) && __cplusplus >= 201103L) \
-     && !defined(static_assert))
+//
+// macOS <= 10.10 doesn't define static_assert in assert.h at all despite
+// having C11 compiler support.
+//
+// static_assert is defined in glibc from version 2.16. Compiler support for
+// the C11 _Static_assert keyword is in gcc >= 4.6.
+//
+// MSVC makes static_assert a keyword in C11-17, contrary to the standards.
+//
+// In C++11 and C2x, static_assert is a keyword, redefining is undefined
+// behaviour. So only define if building as C (if __STDC_VERSION__ is defined),
+// not C++, and only for C11-17.
+#if !defined(static_assert) && (defined(__GNUC__) || defined(__clang__)) \
+     && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L \
+     && __STDC_VERSION__ <= 201710L
 #  define static_assert _Static_assert
 #endif
 
diff -pruN 3.12.0~a7-1/Include/pymath.h 3.12.0~b1-1/Include/pymath.h
--- 3.12.0~a7-1/Include/pymath.h	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Include/pymath.h	2023-05-22 12:07:36.000000000 +0000
@@ -39,27 +39,24 @@
 // Return 1 if float or double arg is neither infinite nor NAN, else 0.
 #define Py_IS_FINITE(X) isfinite(X)
 
-/* HUGE_VAL is supposed to expand to a positive double infinity.  Python
- * uses Py_HUGE_VAL instead because some platforms are broken in this
- * respect.  We used to embed code in pyport.h to try to worm around that,
- * but different platforms are broken in conflicting ways.  If you're on
- * a platform where HUGE_VAL is defined incorrectly, fiddle your Python
- * config to #define Py_HUGE_VAL to something that works on your platform.
+// Py_INFINITY: Value that evaluates to a positive double infinity.
+#ifndef Py_INFINITY
+#  define Py_INFINITY ((double)INFINITY)
+#endif
+
+/* Py_HUGE_VAL should always be the same as Py_INFINITY.  But historically
+ * this was not reliable and Python did not require IEEE floats and C99
+ * conformity.  Prefer Py_INFINITY for new code.
  */
 #ifndef Py_HUGE_VAL
 #  define Py_HUGE_VAL HUGE_VAL
 #endif
 
-// Py_NAN: Value that evaluates to a quiet Not-a-Number (NaN).
+/* Py_NAN: Value that evaluates to a quiet Not-a-Number (NaN).  The sign is
+ * undefined and normally not relevant, but e.g. fixed for float("nan").
+ */
 #if !defined(Py_NAN)
-#  if _Py__has_builtin(__builtin_nan)
-     // Built-in implementation of the ISO C99 function nan(): quiet NaN.
-#    define Py_NAN (__builtin_nan(""))
-#else
-     // Use C99 NAN constant: quiet Not-A-Number.
-     // NAN is a float, Py_NAN is a double: cast to double.
 #    define Py_NAN ((double)NAN)
-#  endif
 #endif
 
 #endif /* Py_PYMATH_H */
diff -pruN 3.12.0~a7-1/Include/pyport.h 3.12.0~b1-1/Include/pyport.h
--- 3.12.0~a7-1/Include/pyport.h	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Include/pyport.h	2023-05-22 12:07:36.000000000 +0000
@@ -184,7 +184,6 @@ typedef Py_ssize_t Py_ssize_clean_t;
 #  define Py_LOCAL_INLINE(type) static inline type
 #endif
 
-// bpo-28126: Py_MEMCPY is kept for backwards compatibility,
 #if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000
 #  define Py_MEMCPY memcpy
 #endif
@@ -663,6 +662,27 @@ extern char * _getpty(int *, int, mode_t
 #  define WITH_THREAD
 #endif
 
+#ifdef WITH_THREAD
+#  ifdef Py_BUILD_CORE
+#    ifdef HAVE_THREAD_LOCAL
+#      error "HAVE_THREAD_LOCAL is already defined"
+#    endif
+#    define HAVE_THREAD_LOCAL 1
+#    ifdef thread_local
+#      define _Py_thread_local thread_local
+#    elif __STDC_VERSION__ >= 201112L && !defined(__STDC_NO_THREADS__)
+#      define _Py_thread_local _Thread_local
+#    elif defined(_MSC_VER)  /* AKA NT_THREADS */
+#      define _Py_thread_local __declspec(thread)
+#    elif defined(__GNUC__)  /* includes clang */
+#      define _Py_thread_local __thread
+#    else
+       // fall back to the PyThread_tss_*() API, or ignore.
+#      undef HAVE_THREAD_LOCAL
+#    endif
+#  endif
+#endif
+
 /* Check that ALT_SOABI is consistent with Py_TRACE_REFS:
    ./configure --with-trace-refs should must be used to define Py_TRACE_REFS */
 #if defined(ALT_SOABI) && defined(Py_TRACE_REFS)
@@ -745,4 +765,15 @@ extern char * _getpty(int *, int, mode_t
 #undef __bool__
 #endif
 
+// Make sure we have maximum alignment, even if the current compiler
+// does not support max_align_t. Note that:
+// - Autoconf reports alignment of unknown types to 0.
+// - 'long double' has maximum alignment on *most* platforms,
+//   looks like the best we can do for pre-C11 compilers.
+// - The value is tested, see test_alignof_max_align_t
+#if !defined(ALIGNOF_MAX_ALIGN_T) || ALIGNOF_MAX_ALIGN_T == 0
+#   undef ALIGNOF_MAX_ALIGN_T
+#   define ALIGNOF_MAX_ALIGN_T _Alignof(long double)
+#endif
+
 #endif /* Py_PYPORT_H */
diff -pruN 3.12.0~a7-1/Include/pystats.h 3.12.0~b1-1/Include/pystats.h
--- 3.12.0~a7-1/Include/pystats.h	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Include/pystats.h	2023-05-22 12:07:36.000000000 +0000
@@ -72,8 +72,6 @@ typedef struct _object_stats {
     uint64_t type_cache_collisions;
 } ObjectStats;
 
-#
-
 typedef struct _stats {
     OpcodeStats opcode_stats[256];
     CallStats call_stats;
diff -pruN 3.12.0~a7-1/Include/sysmodule.h 3.12.0~b1-1/Include/sysmodule.h
--- 3.12.0~a7-1/Include/sysmodule.h	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Include/sysmodule.h	2023-05-22 12:07:36.000000000 +0000
@@ -29,6 +29,19 @@ Py_DEPRECATED(3.11) PyAPI_FUNC(int) PySy
 Py_DEPRECATED(3.11) PyAPI_FUNC(void) PySys_AddXOption(const wchar_t *);
 PyAPI_FUNC(PyObject *) PySys_GetXOptions(void);
 
+#if !defined(Py_LIMITED_API)
+typedef struct {
+    FILE* perf_map;
+    PyThread_type_lock map_lock;
+} PerfMapState;
+
+PyAPI_FUNC(int) PyUnstable_PerfMapState_Init(void);
+
+PyAPI_FUNC(int) PyUnstable_WritePerfMapEntry(const void *code_addr, unsigned int code_size, const char *entry_name);
+
+PyAPI_FUNC(void) PyUnstable_PerfMapState_Fini(void);
+#endif
+
 #ifndef Py_LIMITED_API
 #  define Py_CPYTHON_SYSMODULE_H
 #  include "cpython/sysmodule.h"
diff -pruN 3.12.0~a7-1/Include/tracemalloc.h 3.12.0~b1-1/Include/tracemalloc.h
--- 3.12.0~a7-1/Include/tracemalloc.h	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Include/tracemalloc.h	2023-05-22 12:07:36.000000000 +0000
@@ -33,6 +33,40 @@ PyAPI_FUNC(int) PyTraceMalloc_Untrack(
 PyAPI_FUNC(PyObject*) _PyTraceMalloc_GetTraceback(
     unsigned int domain,
     uintptr_t ptr);
+
+/* Return non-zero if tracemalloc is tracing */
+PyAPI_FUNC(int) _PyTraceMalloc_IsTracing(void);
+
+/* Clear the tracemalloc traces */
+PyAPI_FUNC(void) _PyTraceMalloc_ClearTraces(void);
+
+/* Clear the tracemalloc traces */
+PyAPI_FUNC(PyObject *) _PyTraceMalloc_GetTraces(void);
+
+/* Clear tracemalloc traceback for an object */
+PyAPI_FUNC(PyObject *) _PyTraceMalloc_GetObjectTraceback(PyObject *obj);
+
+/* Initialize tracemalloc */
+PyAPI_FUNC(int) _PyTraceMalloc_Init(void);
+
+/* Start tracemalloc */
+PyAPI_FUNC(int) _PyTraceMalloc_Start(int max_nframe);
+
+/* Stop tracemalloc */
+PyAPI_FUNC(void) _PyTraceMalloc_Stop(void);
+
+/* Get the tracemalloc traceback limit */
+PyAPI_FUNC(int) _PyTraceMalloc_GetTracebackLimit(void);
+
+/* Get the memory usage of tracemalloc in bytes */
+PyAPI_FUNC(size_t) _PyTraceMalloc_GetMemory(void);
+
+/* Get the current size and peak size of traced memory blocks as a 2-tuple */
+PyAPI_FUNC(PyObject *) _PyTraceMalloc_GetTracedMemory(void);
+
+/* Set the peak size of traced memory blocks to the current size */
+PyAPI_FUNC(void) _PyTraceMalloc_ResetPeak(void);
+
 #endif
 
 #endif /* !Py_TRACEMALLOC_H */
diff -pruN 3.12.0~a7-1/Include/unicodeobject.h 3.12.0~b1-1/Include/unicodeobject.h
--- 3.12.0~a7-1/Include/unicodeobject.h	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Include/unicodeobject.h	2023-05-22 12:07:36.000000000 +0000
@@ -626,7 +626,7 @@ PyAPI_FUNC(PyObject*) PyUnicode_AsLatin1
 
 /* --- ASCII Codecs -------------------------------------------------------
 
-   Only 7-bit ASCII data is excepted. All other codes generate errors.
+   Only 7-bit ASCII data is expected. All other codes generate errors.
 
 */
 
diff -pruN 3.12.0~a7-1/Lib/_collections_abc.py 3.12.0~b1-1/Lib/_collections_abc.py
--- 3.12.0~a7-1/Lib/_collections_abc.py	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Lib/_collections_abc.py	2023-05-22 12:07:36.000000000 +0000
@@ -49,7 +49,7 @@ __all__ = ["Awaitable", "Coroutine",
            "Mapping", "MutableMapping",
            "MappingView", "KeysView", "ItemsView", "ValuesView",
            "Sequence", "MutableSequence",
-           "ByteString",
+           "ByteString", "Buffer",
            ]
 
 # This module has been renamed from collections.abc to _collections_abc to
@@ -439,6 +439,21 @@ class Collection(Sized, Iterable, Contai
         return NotImplemented
 
 
+class Buffer(metaclass=ABCMeta):
+
+    __slots__ = ()
+
+    @abstractmethod
+    def __buffer__(self, flags: int, /) -> memoryview:
+        raise NotImplementedError
+
+    @classmethod
+    def __subclasshook__(cls, C):
+        if cls is Buffer:
+            return _check_methods(C, "__buffer__")
+        return NotImplemented
+
+
 class _CallableGenericAlias(GenericAlias):
     """ Represent `Callable[argtypes, resulttype]`.
 
@@ -1056,8 +1071,27 @@ Sequence.register(str)
 Sequence.register(range)
 Sequence.register(memoryview)
 
+class _DeprecateByteStringMeta(ABCMeta):
+    def __new__(cls, name, bases, namespace, **kwargs):
+        if name != "ByteString":
+            import warnings
+
+            warnings._deprecated(
+                "collections.abc.ByteString",
+                remove=(3, 14),
+            )
+        return super().__new__(cls, name, bases, namespace, **kwargs)
+
+    def __instancecheck__(cls, instance):
+        import warnings
+
+        warnings._deprecated(
+            "collections.abc.ByteString",
+            remove=(3, 14),
+        )
+        return super().__instancecheck__(instance)
 
-class ByteString(Sequence):
+class ByteString(Sequence, metaclass=_DeprecateByteStringMeta):
     """This unifies bytes and bytearray.
 
     XXX Should add all their methods.
diff -pruN 3.12.0~a7-1/Lib/_pydatetime.py 3.12.0~b1-1/Lib/_pydatetime.py
--- 3.12.0~a7-1/Lib/_pydatetime.py	1970-01-01 00:00:00.000000000 +0000
+++ 3.12.0~b1-1/Lib/_pydatetime.py	2023-05-22 12:07:36.000000000 +0000
@@ -0,0 +1,2647 @@
+"""Concrete date/time and related types.
+
+See http://www.iana.org/time-zones/repository/tz-link.html for
+time zone and DST data sources.
+"""
+
+__all__ = ("date", "datetime", "time", "timedelta", "timezone", "tzinfo",
+           "MINYEAR", "MAXYEAR", "UTC")
+
+
+import time as _time
+import math as _math
+import sys
+from operator import index as _index
+
+def _cmp(x, y):
+    return 0 if x == y else 1 if x > y else -1
+
+def _get_class_module(self):
+    module_name = self.__class__.__module__
+    if module_name == '_pydatetime':
+        return 'datetime'
+    else:
+        return module_name
+
+MINYEAR = 1
+MAXYEAR = 9999
+_MAXORDINAL = 3652059  # date.max.toordinal()
+
+# Utility functions, adapted from Python's Demo/classes/Dates.py, which
+# also assumes the current Gregorian calendar indefinitely extended in
+# both directions.  Difference:  Dates.py calls January 1 of year 0 day
+# number 1.  The code here calls January 1 of year 1 day number 1.  This is
+# to match the definition of the "proleptic Gregorian" calendar in Dershowitz
+# and Reingold's "Calendrical Calculations", where it's the base calendar
+# for all computations.  See the book for algorithms for converting between
+# proleptic Gregorian ordinals and many other calendar systems.
+
+# -1 is a placeholder for indexing purposes.
+_DAYS_IN_MONTH = [-1, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
+
+_DAYS_BEFORE_MONTH = [-1]  # -1 is a placeholder for indexing purposes.
+dbm = 0
+for dim in _DAYS_IN_MONTH[1:]:
+    _DAYS_BEFORE_MONTH.append(dbm)
+    dbm += dim
+del dbm, dim
+
+def _is_leap(year):
+    "year -> 1 if leap year, else 0."
+    return year % 4 == 0 and (year % 100 != 0 or year % 400 == 0)
+
+def _days_before_year(year):
+    "year -> number of days before January 1st of year."
+    y = year - 1
+    return y*365 + y//4 - y//100 + y//400
+
+def _days_in_month(year, month):
+    "year, month -> number of days in that month in that year."
+    assert 1 <= month <= 12, month
+    if month == 2 and _is_leap(year):
+        return 29
+    return _DAYS_IN_MONTH[month]
+
+def _days_before_month(year, month):
+    "year, month -> number of days in year preceding first day of month."
+    assert 1 <= month <= 12, 'month must be in 1..12'
+    return _DAYS_BEFORE_MONTH[month] + (month > 2 and _is_leap(year))
+
+def _ymd2ord(year, month, day):
+    "year, month, day -> ordinal, considering 01-Jan-0001 as day 1."
+    assert 1 <= month <= 12, 'month must be in 1..12'
+    dim = _days_in_month(year, month)
+    assert 1 <= day <= dim, ('day must be in 1..%d' % dim)
+    return (_days_before_year(year) +
+            _days_before_month(year, month) +
+            day)
+
+_DI400Y = _days_before_year(401)    # number of days in 400 years
+_DI100Y = _days_before_year(101)    #    "    "   "   " 100   "
+_DI4Y   = _days_before_year(5)      #    "    "   "   "   4   "
+
+# A 4-year cycle has an extra leap day over what we'd get from pasting
+# together 4 single years.
+assert _DI4Y == 4 * 365 + 1
+
+# Similarly, a 400-year cycle has an extra leap day over what we'd get from
+# pasting together 4 100-year cycles.
+assert _DI400Y == 4 * _DI100Y + 1
+
+# OTOH, a 100-year cycle has one fewer leap day than we'd get from
+# pasting together 25 4-year cycles.
+assert _DI100Y == 25 * _DI4Y - 1
+
+def _ord2ymd(n):
+    "ordinal -> (year, month, day), considering 01-Jan-0001 as day 1."
+
+    # n is a 1-based index, starting at 1-Jan-1.  The pattern of leap years
+    # repeats exactly every 400 years.  The basic strategy is to find the
+    # closest 400-year boundary at or before n, then work with the offset
+    # from that boundary to n.  Life is much clearer if we subtract 1 from
+    # n first -- then the values of n at 400-year boundaries are exactly
+    # those divisible by _DI400Y:
+    #
+    #     D  M   Y            n              n-1
+    #     -- --- ----        ----------     ----------------
+    #     31 Dec -400        -_DI400Y       -_DI400Y -1
+    #      1 Jan -399         -_DI400Y +1   -_DI400Y      400-year boundary
+    #     ...
+    #     30 Dec  000        -1             -2
+    #     31 Dec  000         0             -1
+    #      1 Jan  001         1              0            400-year boundary
+    #      2 Jan  001         2              1
+    #      3 Jan  001         3              2
+    #     ...
+    #     31 Dec  400         _DI400Y        _DI400Y -1
+    #      1 Jan  401         _DI400Y +1     _DI400Y      400-year boundary
+    n -= 1
+    n400, n = divmod(n, _DI400Y)
+    year = n400 * 400 + 1   # ..., -399, 1, 401, ...
+
+    # Now n is the (non-negative) offset, in days, from January 1 of year, to
+    # the desired date.  Now compute how many 100-year cycles precede n.
+    # Note that it's possible for n100 to equal 4!  In that case 4 full
+    # 100-year cycles precede the desired day, which implies the desired
+    # day is December 31 at the end of a 400-year cycle.
+    n100, n = divmod(n, _DI100Y)
+
+    # Now compute how many 4-year cycles precede it.
+    n4, n = divmod(n, _DI4Y)
+
+    # And now how many single years.  Again n1 can be 4, and again meaning
+    # that the desired day is December 31 at the end of the 4-year cycle.
+    n1, n = divmod(n, 365)
+
+    year += n100 * 100 + n4 * 4 + n1
+    if n1 == 4 or n100 == 4:
+        assert n == 0
+        return year-1, 12, 31
+
+    # Now the year is correct, and n is the offset from January 1.  We find
+    # the month via an estimate that's either exact or one too large.
+    leapyear = n1 == 3 and (n4 != 24 or n100 == 3)
+    assert leapyear == _is_leap(year)
+    month = (n + 50) >> 5
+    preceding = _DAYS_BEFORE_MONTH[month] + (month > 2 and leapyear)
+    if preceding > n:  # estimate is too large
+        month -= 1
+        preceding -= _DAYS_IN_MONTH[month] + (month == 2 and leapyear)
+    n -= preceding
+    assert 0 <= n < _days_in_month(year, month)
+
+    # Now the year and month are correct, and n is the offset from the
+    # start of that month:  we're done!
+    return year, month, n+1
+
+# Month and day names.  For localized versions, see the calendar module.
+_MONTHNAMES = [None, "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+                     "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
+_DAYNAMES = [None, "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]
+
+
+def _build_struct_time(y, m, d, hh, mm, ss, dstflag):
+    wday = (_ymd2ord(y, m, d) + 6) % 7
+    dnum = _days_before_month(y, m) + d
+    return _time.struct_time((y, m, d, hh, mm, ss, wday, dnum, dstflag))
+
+def _format_time(hh, mm, ss, us, timespec='auto'):
+    specs = {
+        'hours': '{:02d}',
+        'minutes': '{:02d}:{:02d}',
+        'seconds': '{:02d}:{:02d}:{:02d}',
+        'milliseconds': '{:02d}:{:02d}:{:02d}.{:03d}',
+        'microseconds': '{:02d}:{:02d}:{:02d}.{:06d}'
+    }
+
+    if timespec == 'auto':
+        # Skip trailing microseconds when us==0.
+        timespec = 'microseconds' if us else 'seconds'
+    elif timespec == 'milliseconds':
+        us //= 1000
+    try:
+        fmt = specs[timespec]
+    except KeyError:
+        raise ValueError('Unknown timespec value')
+    else:
+        return fmt.format(hh, mm, ss, us)
+
+def _format_offset(off, sep=':'):
+    s = ''
+    if off is not None:
+        if off.days < 0:
+            sign = "-"
+            off = -off
+        else:
+            sign = "+"
+        hh, mm = divmod(off, timedelta(hours=1))
+        mm, ss = divmod(mm, timedelta(minutes=1))
+        s += "%s%02d%s%02d" % (sign, hh, sep, mm)
+        if ss or ss.microseconds:
+            s += "%s%02d" % (sep, ss.seconds)
+
+            if ss.microseconds:
+                s += '.%06d' % ss.microseconds
+    return s
+
+# Correctly substitute for %z and %Z escapes in strftime formats.
+def _wrap_strftime(object, format, timetuple):
+    # Don't call utcoffset() or tzname() unless actually needed.
+    freplace = None  # the string to use for %f
+    zreplace = None  # the string to use for %z
+    colonzreplace = None  # the string to use for %:z
+    Zreplace = None  # the string to use for %Z
+
+    # Scan format for %z, %:z and %Z escapes, replacing as needed.
+    newformat = []
+    push = newformat.append
+    i, n = 0, len(format)
+    while i < n:
+        ch = format[i]
+        i += 1
+        if ch == '%':
+            if i < n:
+                ch = format[i]
+                i += 1
+                if ch == 'f':
+                    if freplace is None:
+                        freplace = '%06d' % getattr(object,
+                                                    'microsecond', 0)
+                    newformat.append(freplace)
+                elif ch == 'z':
+                    if zreplace is None:
+                        if hasattr(object, "utcoffset"):
+                            zreplace = _format_offset(object.utcoffset(), sep="")
+                        else:
+                            zreplace = ""
+                    assert '%' not in zreplace
+                    newformat.append(zreplace)
+                elif ch == ':':
+                    if i < n:
+                        ch2 = format[i]
+                        i += 1
+                        if ch2 == 'z':
+                            if colonzreplace is None:
+                                if hasattr(object, "utcoffset"):
+                                    colonzreplace = _format_offset(object.utcoffset(), sep=":")
+                                else:
+                                    colonzreplace = ""
+                            assert '%' not in colonzreplace
+                            newformat.append(colonzreplace)
+                        else:
+                            push('%')
+                            push(ch)
+                            push(ch2)
+                elif ch == 'Z':
+                    if Zreplace is None:
+                        Zreplace = ""
+                        if hasattr(object, "tzname"):
+                            s = object.tzname()
+                            if s is not None:
+                                # strftime is going to have at this: escape %
+                                Zreplace = s.replace('%', '%%')
+                    newformat.append(Zreplace)
+                else:
+                    push('%')
+                    push(ch)
+            else:
+                push('%')
+        else:
+            push(ch)
+    newformat = "".join(newformat)
+    return _time.strftime(newformat, timetuple)
+
+# Helpers for parsing the result of isoformat()
+def _is_ascii_digit(c):
+    return c in "0123456789"
+
+def _find_isoformat_datetime_separator(dtstr):
+    # See the comment in _datetimemodule.c:_find_isoformat_datetime_separator
+    len_dtstr = len(dtstr)
+    if len_dtstr == 7:
+        return 7
+
+    assert len_dtstr > 7
+    date_separator = "-"
+    week_indicator = "W"
+
+    if dtstr[4] == date_separator:
+        if dtstr[5] == week_indicator:
+            if len_dtstr < 8:
+                raise ValueError("Invalid ISO string")
+            if len_dtstr > 8 and dtstr[8] == date_separator:
+                if len_dtstr == 9:
+                    raise ValueError("Invalid ISO string")
+                if len_dtstr > 10 and _is_ascii_digit(dtstr[10]):
+                    # This is as far as we need to resolve the ambiguity for
+                    # the moment - if we have YYYY-Www-##, the separator is
+                    # either a hyphen at 8 or a number at 10.
+                    #
+                    # We'll assume it's a hyphen at 8 because it's way more
+                    # likely that someone will use a hyphen as a separator than
+                    # a number, but at this point it's really best effort
+                    # because this is an extension of the spec anyway.
+                    # TODO(pganssle): Document this
+                    return 8
+                return 10
+            else:
+                # YYYY-Www (8)
+                return 8
+        else:
+            # YYYY-MM-DD (10)
+            return 10
+    else:
+        if dtstr[4] == week_indicator:
+            # YYYYWww (7) or YYYYWwwd (8)
+            idx = 7
+            while idx < len_dtstr:
+                if not _is_ascii_digit(dtstr[idx]):
+                    break
+                idx += 1
+
+            if idx < 9:
+                return idx
+
+            if idx % 2 == 0:
+                # If the index of the last number is even, it's YYYYWwwd
+                return 7
+            else:
+                return 8
+        else:
+            # YYYYMMDD (8)
+            return 8
+
+
+def _parse_isoformat_date(dtstr):
+    # It is assumed that this is an ASCII-only string of lengths 7, 8 or 10,
+    # see the comment on Modules/_datetimemodule.c:_find_isoformat_datetime_separator
+    assert len(dtstr) in (7, 8, 10)
+    year = int(dtstr[0:4])
+    has_sep = dtstr[4] == '-'
+
+    pos = 4 + has_sep
+    if dtstr[pos:pos + 1] == "W":
+        # YYYY-?Www-?D?
+        pos += 1
+        weekno = int(dtstr[pos:pos + 2])
+        pos += 2
+
+        dayno = 1
+        if len(dtstr) > pos:
+            if (dtstr[pos:pos + 1] == '-') != has_sep:
+                raise ValueError("Inconsistent use of dash separator")
+
+            pos += has_sep
+
+            dayno = int(dtstr[pos:pos + 1])
+
+        return list(_isoweek_to_gregorian(year, weekno, dayno))
+    else:
+        month = int(dtstr[pos:pos + 2])
+        pos += 2
+        if (dtstr[pos:pos + 1] == "-") != has_sep:
+            raise ValueError("Inconsistent use of dash separator")
+
+        pos += has_sep
+        day = int(dtstr[pos:pos + 2])
+
+        return [year, month, day]
+
+
+_FRACTION_CORRECTION = [100000, 10000, 1000, 100, 10]
+
+
+def _parse_hh_mm_ss_ff(tstr):
+    # Parses things of the form HH[:?MM[:?SS[{.,}fff[fff]]]]
+    len_str = len(tstr)
+
+    time_comps = [0, 0, 0, 0]
+    pos = 0
+    for comp in range(0, 3):
+        if (len_str - pos) < 2:
+            raise ValueError("Incomplete time component")
+
+        time_comps[comp] = int(tstr[pos:pos+2])
+
+        pos += 2
+        next_char = tstr[pos:pos+1]
+
+        if comp == 0:
+            has_sep = next_char == ':'
+
+        if not next_char or comp >= 2:
+            break
+
+        if has_sep and next_char != ':':
+            raise ValueError("Invalid time separator: %c" % next_char)
+
+        pos += has_sep
+
+    if pos < len_str:
+        if tstr[pos] not in '.,':
+            raise ValueError("Invalid microsecond component")
+        else:
+            pos += 1
+
+            len_remainder = len_str - pos
+
+            if len_remainder >= 6:
+                to_parse = 6
+            else:
+                to_parse = len_remainder
+
+            time_comps[3] = int(tstr[pos:(pos+to_parse)])
+            if to_parse < 6:
+                time_comps[3] *= _FRACTION_CORRECTION[to_parse-1]
+            if (len_remainder > to_parse
+                    and not all(map(_is_ascii_digit, tstr[(pos+to_parse):]))):
+                raise ValueError("Non-digit values in unparsed fraction")
+
+    return time_comps
+
+def _parse_isoformat_time(tstr):
+    # Format supported is HH[:MM[:SS[.fff[fff]]]][+HH:MM[:SS[.ffffff]]]
+    len_str = len(tstr)
+    if len_str < 2:
+        raise ValueError("Isoformat time too short")
+
+    # This is equivalent to re.search('[+-Z]', tstr), but faster
+    tz_pos = (tstr.find('-') + 1 or tstr.find('+') + 1 or tstr.find('Z') + 1)
+    timestr = tstr[:tz_pos-1] if tz_pos > 0 else tstr
+
+    time_comps = _parse_hh_mm_ss_ff(timestr)
+
+    tzi = None
+    if tz_pos == len_str and tstr[-1] == 'Z':
+        tzi = timezone.utc
+    elif tz_pos > 0:
+        tzstr = tstr[tz_pos:]
+
+        # Valid time zone strings are:
+        # HH                  len: 2
+        # HHMM                len: 4
+        # HH:MM               len: 5
+        # HHMMSS              len: 6
+        # HHMMSS.f+           len: 7+
+        # HH:MM:SS            len: 8
+        # HH:MM:SS.f+         len: 10+
+
+        if len(tzstr) in (0, 1, 3):
+            raise ValueError("Malformed time zone string")
+
+        tz_comps = _parse_hh_mm_ss_ff(tzstr)
+
+        if all(x == 0 for x in tz_comps):
+            tzi = timezone.utc
+        else:
+            tzsign = -1 if tstr[tz_pos - 1] == '-' else 1
+
+            td = timedelta(hours=tz_comps[0], minutes=tz_comps[1],
+                           seconds=tz_comps[2], microseconds=tz_comps[3])
+
+            tzi = timezone(tzsign * td)
+
+    time_comps.append(tzi)
+
+    return time_comps
+
+# tuple[int, int, int] -> tuple[int, int, int] version of date.fromisocalendar
+def _isoweek_to_gregorian(year, week, day):
+    # Year is bounded this way because 9999-12-31 is (9999, 52, 5)
+    if not MINYEAR <= year <= MAXYEAR:
+        raise ValueError(f"Year is out of range: {year}")
+
+    if not 0 < week < 53:
+        out_of_range = True
+
+        if week == 53:
+            # ISO years have 53 weeks in them on years starting with a
+            # Thursday and leap years starting on a Wednesday
+            first_weekday = _ymd2ord(year, 1, 1) % 7
+            if (first_weekday == 4 or (first_weekday == 3 and
+                                       _is_leap(year))):
+                out_of_range = False
+
+        if out_of_range:
+            raise ValueError(f"Invalid week: {week}")
+
+    if not 0 < day < 8:
+        raise ValueError(f"Invalid weekday: {day} (range is [1, 7])")
+
+    # Now compute the offset from (Y, 1, 1) in days:
+    day_offset = (week - 1) * 7 + (day - 1)
+
+    # Calculate the ordinal day for monday, week 1
+    day_1 = _isoweek1monday(year)
+    ord_day = day_1 + day_offset
+
+    return _ord2ymd(ord_day)
+
+
+# Just raise TypeError if the arg isn't None or a string.
+def _check_tzname(name):
+    if name is not None and not isinstance(name, str):
+        raise TypeError("tzinfo.tzname() must return None or string, "
+                        "not '%s'" % type(name))
+
+# name is the offset-producing method, "utcoffset" or "dst".
+# offset is what it returned.
+# If offset isn't None or timedelta, raises TypeError.
+# If offset is None, returns None.
+# Else offset is checked for being in range.
+# If it is, its integer value is returned.  Else ValueError is raised.
+def _check_utc_offset(name, offset):
+    assert name in ("utcoffset", "dst")
+    if offset is None:
+        return
+    if not isinstance(offset, timedelta):
+        raise TypeError("tzinfo.%s() must return None "
+                        "or timedelta, not '%s'" % (name, type(offset)))
+    if not -timedelta(1) < offset < timedelta(1):
+        raise ValueError("%s()=%s, must be strictly between "
+                         "-timedelta(hours=24) and timedelta(hours=24)" %
+                         (name, offset))
+
+def _check_date_fields(year, month, day):
+    year = _index(year)
+    month = _index(month)
+    day = _index(day)
+    if not MINYEAR <= year <= MAXYEAR:
+        raise ValueError('year must be in %d..%d' % (MINYEAR, MAXYEAR), year)
+    if not 1 <= month <= 12:
+        raise ValueError('month must be in 1..12', month)
+    dim = _days_in_month(year, month)
+    if not 1 <= day <= dim:
+        raise ValueError('day must be in 1..%d' % dim, day)
+    return year, month, day
+
+def _check_time_fields(hour, minute, second, microsecond, fold):
+    hour = _index(hour)
+    minute = _index(minute)
+    second = _index(second)
+    microsecond = _index(microsecond)
+    if not 0 <= hour <= 23:
+        raise ValueError('hour must be in 0..23', hour)
+    if not 0 <= minute <= 59:
+        raise ValueError('minute must be in 0..59', minute)
+    if not 0 <= second <= 59:
+        raise ValueError('second must be in 0..59', second)
+    if not 0 <= microsecond <= 999999:
+        raise ValueError('microsecond must be in 0..999999', microsecond)
+    if fold not in (0, 1):
+        raise ValueError('fold must be either 0 or 1', fold)
+    return hour, minute, second, microsecond, fold
+
+def _check_tzinfo_arg(tz):
+    if tz is not None and not isinstance(tz, tzinfo):
+        raise TypeError("tzinfo argument must be None or of a tzinfo subclass")
+
+def _cmperror(x, y):
+    raise TypeError("can't compare '%s' to '%s'" % (
+                    type(x).__name__, type(y).__name__))
+
+def _divide_and_round(a, b):
+    """divide a by b and round result to the nearest integer
+
+    When the ratio is exactly half-way between two integers,
+    the even integer is returned.
+    """
+    # Based on the reference implementation for divmod_near
+    # in Objects/longobject.c.
+    q, r = divmod(a, b)
+    # round up if either r / b > 0.5, or r / b == 0.5 and q is odd.
+    # The expression r / b > 0.5 is equivalent to 2 * r > b if b is
+    # positive, 2 * r < b if b negative.
+    r *= 2
+    greater_than_half = r > b if b > 0 else r < b
+    if greater_than_half or r == b and q % 2 == 1:
+        q += 1
+
+    return q
+
+
+class timedelta:
+    """Represent the difference between two datetime objects.
+
+    Supported operators:
+
+    - add, subtract timedelta
+    - unary plus, minus, abs
+    - compare to timedelta
+    - multiply, divide by int
+
+    In addition, datetime supports subtraction of two datetime objects
+    returning a timedelta, and addition or subtraction of a datetime
+    and a timedelta giving a datetime.
+
+    Representation: (days, seconds, microseconds).
+    """
+    # The representation of (days, seconds, microseconds) was chosen
+    # arbitrarily; the exact rationale originally specified in the docstring
+    # was "Because I felt like it."
+
+    __slots__ = '_days', '_seconds', '_microseconds', '_hashcode'
+
+    def __new__(cls, days=0, seconds=0, microseconds=0,
+                milliseconds=0, minutes=0, hours=0, weeks=0):
+        # Doing this efficiently and accurately in C is going to be difficult
+        # and error-prone, due to ubiquitous overflow possibilities, and that
+        # C double doesn't have enough bits of precision to represent
+        # microseconds over 10K years faithfully.  The code here tries to make
+        # explicit where go-fast assumptions can be relied on, in order to
+        # guide the C implementation; it's way more convoluted than speed-
+        # ignoring auto-overflow-to-long idiomatic Python could be.
+
+        # XXX Check that all inputs are ints or floats.
+
+        # Final values, all integer.
+        # s and us fit in 32-bit signed ints; d isn't bounded.
+        d = s = us = 0
+
+        # Normalize everything to days, seconds, microseconds.
+        days += weeks*7
+        seconds += minutes*60 + hours*3600
+        microseconds += milliseconds*1000
+
+        # Get rid of all fractions, and normalize s and us.
+        # Take a deep breath <wink>.
+        if isinstance(days, float):
+            dayfrac, days = _math.modf(days)
+            daysecondsfrac, daysecondswhole = _math.modf(dayfrac * (24.*3600.))
+            assert daysecondswhole == int(daysecondswhole)  # can't overflow
+            s = int(daysecondswhole)
+            assert days == int(days)
+            d = int(days)
+        else:
+            daysecondsfrac = 0.0
+            d = days
+        assert isinstance(daysecondsfrac, float)
+        assert abs(daysecondsfrac) <= 1.0
+        assert isinstance(d, int)
+        assert abs(s) <= 24 * 3600
+        # days isn't referenced again before redefinition
+
+        if isinstance(seconds, float):
+            secondsfrac, seconds = _math.modf(seconds)
+            assert seconds == int(seconds)
+            seconds = int(seconds)
+            secondsfrac += daysecondsfrac
+            assert abs(secondsfrac) <= 2.0
+        else:
+            secondsfrac = daysecondsfrac
+        # daysecondsfrac isn't referenced again
+        assert isinstance(secondsfrac, float)
+        assert abs(secondsfrac) <= 2.0
+
+        assert isinstance(seconds, int)
+        days, seconds = divmod(seconds, 24*3600)
+        d += days
+        s += int(seconds)    # can't overflow
+        assert isinstance(s, int)
+        assert abs(s) <= 2 * 24 * 3600
+        # seconds isn't referenced again before redefinition
+
+        usdouble = secondsfrac * 1e6
+        assert abs(usdouble) < 2.1e6    # exact value not critical
+        # secondsfrac isn't referenced again
+
+        if isinstance(microseconds, float):
+            microseconds = round(microseconds + usdouble)
+            seconds, microseconds = divmod(microseconds, 1000000)
+            days, seconds = divmod(seconds, 24*3600)
+            d += days
+            s += seconds
+        else:
+            microseconds = int(microseconds)
+            seconds, microseconds = divmod(microseconds, 1000000)
+            days, seconds = divmod(seconds, 24*3600)
+            d += days
+            s += seconds
+            microseconds = round(microseconds + usdouble)
+        assert isinstance(s, int)
+        assert isinstance(microseconds, int)
+        assert abs(s) <= 3 * 24 * 3600
+        assert abs(microseconds) < 3.1e6
+
+        # Just a little bit of carrying possible for microseconds and seconds.
+        seconds, us = divmod(microseconds, 1000000)
+        s += seconds
+        days, s = divmod(s, 24*3600)
+        d += days
+
+        assert isinstance(d, int)
+        assert isinstance(s, int) and 0 <= s < 24*3600
+        assert isinstance(us, int) and 0 <= us < 1000000
+
+        if abs(d) > 999999999:
+            raise OverflowError("timedelta # of days is too large: %d" % d)
+
+        self = object.__new__(cls)
+        self._days = d
+        self._seconds = s
+        self._microseconds = us
+        self._hashcode = -1
+        return self
+
+    def __repr__(self):
+        args = []
+        if self._days:
+            args.append("days=%d" % self._days)
+        if self._seconds:
+            args.append("seconds=%d" % self._seconds)
+        if self._microseconds:
+            args.append("microseconds=%d" % self._microseconds)
+        if not args:
+            args.append('0')
+        return "%s.%s(%s)" % (_get_class_module(self),
+                              self.__class__.__qualname__,
+                              ', '.join(args))
+
+    def __str__(self):
+        mm, ss = divmod(self._seconds, 60)
+        hh, mm = divmod(mm, 60)
+        s = "%d:%02d:%02d" % (hh, mm, ss)
+        if self._days:
+            def plural(n):
+                return n, abs(n) != 1 and "s" or ""
+            s = ("%d day%s, " % plural(self._days)) + s
+        if self._microseconds:
+            s = s + ".%06d" % self._microseconds
+        return s
+
+    def total_seconds(self):
+        """Total seconds in the duration."""
+        return ((self.days * 86400 + self.seconds) * 10**6 +
+                self.microseconds) / 10**6
+
+    # Read-only field accessors
+    @property
+    def days(self):
+        """days"""
+        return self._days
+
+    @property
+    def seconds(self):
+        """seconds"""
+        return self._seconds
+
+    @property
+    def microseconds(self):
+        """microseconds"""
+        return self._microseconds
+
+    def __add__(self, other):
+        if isinstance(other, timedelta):
+            # for CPython compatibility, we cannot use
+            # our __class__ here, but need a real timedelta
+            return timedelta(self._days + other._days,
+                             self._seconds + other._seconds,
+                             self._microseconds + other._microseconds)
+        return NotImplemented
+
+    __radd__ = __add__
+
+    def __sub__(self, other):
+        if isinstance(other, timedelta):
+            # for CPython compatibility, we cannot use
+            # our __class__ here, but need a real timedelta
+            return timedelta(self._days - other._days,
+                             self._seconds - other._seconds,
+                             self._microseconds - other._microseconds)
+        return NotImplemented
+
+    def __rsub__(self, other):
+        if isinstance(other, timedelta):
+            return -self + other
+        return NotImplemented
+
+    def __neg__(self):
+        # for CPython compatibility, we cannot use
+        # our __class__ here, but need a real timedelta
+        return timedelta(-self._days,
+                         -self._seconds,
+                         -self._microseconds)
+
+    def __pos__(self):
+        return self
+
+    def __abs__(self):
+        if self._days < 0:
+            return -self
+        else:
+            return self
+
+    def __mul__(self, other):
+        if isinstance(other, int):
+            # for CPython compatibility, we cannot use
+            # our __class__ here, but need a real timedelta
+            return timedelta(self._days * other,
+                             self._seconds * other,
+                             self._microseconds * other)
+        if isinstance(other, float):
+            usec = self._to_microseconds()
+            a, b = other.as_integer_ratio()
+            return timedelta(0, 0, _divide_and_round(usec * a, b))
+        return NotImplemented
+
+    __rmul__ = __mul__
+
+    def _to_microseconds(self):
+        return ((self._days * (24*3600) + self._seconds) * 1000000 +
+                self._microseconds)
+
+    def __floordiv__(self, other):
+        if not isinstance(other, (int, timedelta)):
+            return NotImplemented
+        usec = self._to_microseconds()
+        if isinstance(other, timedelta):
+            return usec // other._to_microseconds()
+        if isinstance(other, int):
+            return timedelta(0, 0, usec // other)
+
+    def __truediv__(self, other):
+        if not isinstance(other, (int, float, timedelta)):
+            return NotImplemented
+        usec = self._to_microseconds()
+        if isinstance(other, timedelta):
+            return usec / other._to_microseconds()
+        if isinstance(other, int):
+            return timedelta(0, 0, _divide_and_round(usec, other))
+        if isinstance(other, float):
+            a, b = other.as_integer_ratio()
+            return timedelta(0, 0, _divide_and_round(b * usec, a))
+
+    def __mod__(self, other):
+        if isinstance(other, timedelta):
+            r = self._to_microseconds() % other._to_microseconds()
+            return timedelta(0, 0, r)
+        return NotImplemented
+
+    def __divmod__(self, other):
+        if isinstance(other, timedelta):
+            q, r = divmod(self._to_microseconds(),
+                          other._to_microseconds())
+            return q, timedelta(0, 0, r)
+        return NotImplemented
+
+    # Comparisons of timedelta objects with other.
+
+    def __eq__(self, other):
+        if isinstance(other, timedelta):
+            return self._cmp(other) == 0
+        else:
+            return NotImplemented
+
+    def __le__(self, other):
+        if isinstance(other, timedelta):
+            return self._cmp(other) <= 0
+        else:
+            return NotImplemented
+
+    def __lt__(self, other):
+        if isinstance(other, timedelta):
+            return self._cmp(other) < 0
+        else:
+            return NotImplemented
+
+    def __ge__(self, other):
+        if isinstance(other, timedelta):
+            return self._cmp(other) >= 0
+        else:
+            return NotImplemented
+
+    def __gt__(self, other):
+        if isinstance(other, timedelta):
+            return self._cmp(other) > 0
+        else:
+            return NotImplemented
+
+    def _cmp(self, other):
+        assert isinstance(other, timedelta)
+        return _cmp(self._getstate(), other._getstate())
+
+    def __hash__(self):
+        if self._hashcode == -1:
+            self._hashcode = hash(self._getstate())
+        return self._hashcode
+
+    def __bool__(self):
+        return (self._days != 0 or
+                self._seconds != 0 or
+                self._microseconds != 0)
+
+    # Pickle support.
+
+    def _getstate(self):
+        return (self._days, self._seconds, self._microseconds)
+
+    def __reduce__(self):
+        return (self.__class__, self._getstate())
+
+timedelta.min = timedelta(-999999999)
+timedelta.max = timedelta(days=999999999, hours=23, minutes=59, seconds=59,
+                          microseconds=999999)
+timedelta.resolution = timedelta(microseconds=1)
+
+class date:
+    """Concrete date type.
+
+    Constructors:
+
+    __new__()
+    fromtimestamp()
+    today()
+    fromordinal()
+
+    Operators:
+
+    __repr__, __str__
+    __eq__, __le__, __lt__, __ge__, __gt__, __hash__
+    __add__, __radd__, __sub__ (add/radd only with timedelta arg)
+
+    Methods:
+
+    timetuple()
+    toordinal()
+    weekday()
+    isoweekday(), isocalendar(), isoformat()
+    ctime()
+    strftime()
+
+    Properties (readonly):
+    year, month, day
+    """
+    __slots__ = '_year', '_month', '_day', '_hashcode'
+
+    def __new__(cls, year, month=None, day=None):
+        """Constructor.
+
+        Arguments:
+
+        year, month, day (required, base 1)
+        """
+        if (month is None and
+            isinstance(year, (bytes, str)) and len(year) == 4 and
+            1 <= ord(year[2:3]) <= 12):
+            # Pickle support
+            if isinstance(year, str):
+                try:
+                    year = year.encode('latin1')
+                except UnicodeEncodeError:
+                    # More informative error message.
+                    raise ValueError(
+                        "Failed to encode latin1 string when unpickling "
+                        "a date object. "
+                        "pickle.load(data, encoding='latin1') is assumed.")
+            self = object.__new__(cls)
+            self.__setstate(year)
+            self._hashcode = -1
+            return self
+        year, month, day = _check_date_fields(year, month, day)
+        self = object.__new__(cls)
+        self._year = year
+        self._month = month
+        self._day = day
+        self._hashcode = -1
+        return self
+
+    # Additional constructors
+
+    @classmethod
+    def fromtimestamp(cls, t):
+        "Construct a date from a POSIX timestamp (like time.time())."
+        y, m, d, hh, mm, ss, weekday, jday, dst = _time.localtime(t)
+        return cls(y, m, d)
+
+    @classmethod
+    def today(cls):
+        "Construct a date from time.time()."
+        t = _time.time()
+        return cls.fromtimestamp(t)
+
+    @classmethod
+    def fromordinal(cls, n):
+        """Construct a date from a proleptic Gregorian ordinal.
+
+        January 1 of year 1 is day 1.  Only the year, month and day are
+        non-zero in the result.
+        """
+        y, m, d = _ord2ymd(n)
+        return cls(y, m, d)
+
+    @classmethod
+    def fromisoformat(cls, date_string):
+        """Construct a date from a string in ISO 8601 format."""
+        if not isinstance(date_string, str):
+            raise TypeError('fromisoformat: argument must be str')
+
+        if len(date_string) not in (7, 8, 10):
+            raise ValueError(f'Invalid isoformat string: {date_string!r}')
+
+        try:
+            return cls(*_parse_isoformat_date(date_string))
+        except Exception:
+            raise ValueError(f'Invalid isoformat string: {date_string!r}')
+
+    @classmethod
+    def fromisocalendar(cls, year, week, day):
+        """Construct a date from the ISO year, week number and weekday.
+
+        This is the inverse of the date.isocalendar() function"""
+        return cls(*_isoweek_to_gregorian(year, week, day))
+
+    # Conversions to string
+
+    def __repr__(self):
+        """Convert to formal string, for repr().
+
+        >>> dt = datetime(2010, 1, 1)
+        >>> repr(dt)
+        'datetime.datetime(2010, 1, 1, 0, 0)'
+
+        >>> dt = datetime(2010, 1, 1, tzinfo=timezone.utc)
+        >>> repr(dt)
+        'datetime.datetime(2010, 1, 1, 0, 0, tzinfo=datetime.timezone.utc)'
+        """
+        return "%s.%s(%d, %d, %d)" % (_get_class_module(self),
+                                      self.__class__.__qualname__,
+                                      self._year,
+                                      self._month,
+                                      self._day)
+    # XXX These shouldn't depend on time.localtime(), because that
+    # clips the usable dates to [1970 .. 2038).  At least ctime() is
+    # easily done without using strftime() -- that's better too because
+    # strftime("%c", ...) is locale specific.
+
+
+    def ctime(self):
+        "Return ctime() style string."
+        weekday = self.toordinal() % 7 or 7
+        return "%s %s %2d 00:00:00 %04d" % (
+            _DAYNAMES[weekday],
+            _MONTHNAMES[self._month],
+            self._day, self._year)
+
+    def strftime(self, format):
+        """
+        Format using strftime().
+
+        Example: "%d/%m/%Y, %H:%M:%S"
+        """
+        return _wrap_strftime(self, format, self.timetuple())
+
+    def __format__(self, fmt):
+        if not isinstance(fmt, str):
+            raise TypeError("must be str, not %s" % type(fmt).__name__)
+        if len(fmt) != 0:
+            return self.strftime(fmt)
+        return str(self)
+
+    def isoformat(self):
+        """Return the date formatted according to ISO.
+
+        This is 'YYYY-MM-DD'.
+
+        References:
+        - http://www.w3.org/TR/NOTE-datetime
+        - http://www.cl.cam.ac.uk/~mgk25/iso-time.html
+        """
+        return "%04d-%02d-%02d" % (self._year, self._month, self._day)
+
+    __str__ = isoformat
+
+    # Read-only field accessors
+    @property
+    def year(self):
+        """year (1-9999)"""
+        return self._year
+
+    @property
+    def month(self):
+        """month (1-12)"""
+        return self._month
+
+    @property
+    def day(self):
+        """day (1-31)"""
+        return self._day
+
+    # Standard conversions, __eq__, __le__, __lt__, __ge__, __gt__,
+    # __hash__ (and helpers)
+
+    def timetuple(self):
+        "Return local time tuple compatible with time.localtime()."
+        return _build_struct_time(self._year, self._month, self._day,
+                                  0, 0, 0, -1)
+
+    def toordinal(self):
+        """Return proleptic Gregorian ordinal for the year, month and day.
+
+        January 1 of year 1 is day 1.  Only the year, month and day values
+        contribute to the result.
+        """
+        return _ymd2ord(self._year, self._month, self._day)
+
+    def replace(self, year=None, month=None, day=None):
+        """Return a new date with new values for the specified fields."""
+        if year is None:
+            year = self._year
+        if month is None:
+            month = self._month
+        if day is None:
+            day = self._day
+        return type(self)(year, month, day)
+
+    # Comparisons of date objects with other.
+
+    def __eq__(self, other):
+        if isinstance(other, date):
+            return self._cmp(other) == 0
+        return NotImplemented
+
+    def __le__(self, other):
+        if isinstance(other, date):
+            return self._cmp(other) <= 0
+        return NotImplemented
+
+    def __lt__(self, other):
+        if isinstance(other, date):
+            return self._cmp(other) < 0
+        return NotImplemented
+
+    def __ge__(self, other):
+        if isinstance(other, date):
+            return self._cmp(other) >= 0
+        return NotImplemented
+
+    def __gt__(self, other):
+        if isinstance(other, date):
+            return self._cmp(other) > 0
+        return NotImplemented
+
+    def _cmp(self, other):
+        assert isinstance(other, date)
+        y, m, d = self._year, self._month, self._day
+        y2, m2, d2 = other._year, other._month, other._day
+        return _cmp((y, m, d), (y2, m2, d2))
+
+    def __hash__(self):
+        "Hash."
+        if self._hashcode == -1:
+            self._hashcode = hash(self._getstate())
+        return self._hashcode
+
+    # Computations
+
+    def __add__(self, other):
+        "Add a date to a timedelta."
+        if isinstance(other, timedelta):
+            o = self.toordinal() + other.days
+            if 0 < o <= _MAXORDINAL:
+                return type(self).fromordinal(o)
+            raise OverflowError("result out of range")
+        return NotImplemented
+
+    __radd__ = __add__
+
+    def __sub__(self, other):
+        """Subtract two dates, or a date and a timedelta."""
+        if isinstance(other, timedelta):
+            return self + timedelta(-other.days)
+        if isinstance(other, date):
+            days1 = self.toordinal()
+            days2 = other.toordinal()
+            return timedelta(days1 - days2)
+        return NotImplemented
+
+    def weekday(self):
+        "Return day of the week, where Monday == 0 ... Sunday == 6."
+        return (self.toordinal() + 6) % 7
+
+    # Day-of-the-week and week-of-the-year, according to ISO
+
+    def isoweekday(self):
+        "Return day of the week, where Monday == 1 ... Sunday == 7."
+        # 1-Jan-0001 is a Monday
+        return self.toordinal() % 7 or 7
+
+    def isocalendar(self):
+        """Return a named tuple containing ISO year, week number, and weekday.
+
+        The first ISO week of the year is the (Mon-Sun) week
+        containing the year's first Thursday; everything else derives
+        from that.
+
+        The first week is 1; Monday is 1 ... Sunday is 7.
+
+        ISO calendar algorithm taken from
+        http://www.phys.uu.nl/~vgent/calendar/isocalendar.htm
+        (used with permission)
+        """
+        year = self._year
+        week1monday = _isoweek1monday(year)
+        today = _ymd2ord(self._year, self._month, self._day)
+        # Internally, week and day have origin 0
+        week, day = divmod(today - week1monday, 7)
+        if week < 0:
+            year -= 1
+            week1monday = _isoweek1monday(year)
+            week, day = divmod(today - week1monday, 7)
+        elif week >= 52:
+            if today >= _isoweek1monday(year+1):
+                year += 1
+                week = 0
+        return _IsoCalendarDate(year, week+1, day+1)
+
+    # Pickle support.
+
+    def _getstate(self):
+        yhi, ylo = divmod(self._year, 256)
+        return bytes([yhi, ylo, self._month, self._day]),
+
+    def __setstate(self, string):
+        yhi, ylo, self._month, self._day = string
+        self._year = yhi * 256 + ylo
+
+    def __reduce__(self):
+        return (self.__class__, self._getstate())
+
+_date_class = date  # so functions w/ args named "date" can get at the class
+
+date.min = date(1, 1, 1)
+date.max = date(9999, 12, 31)
+date.resolution = timedelta(days=1)
+
+
+class tzinfo:
+    """Abstract base class for time zone info classes.
+
+    Subclasses must override the name(), utcoffset() and dst() methods.
+    """
+    __slots__ = ()
+
+    def tzname(self, dt):
+        "datetime -> string name of time zone."
+        raise NotImplementedError("tzinfo subclass must override tzname()")
+
+    def utcoffset(self, dt):
+        "datetime -> timedelta, positive for east of UTC, negative for west of UTC"
+        raise NotImplementedError("tzinfo subclass must override utcoffset()")
+
+    def dst(self, dt):
+        """datetime -> DST offset as timedelta, positive for east of UTC.
+
+        Return 0 if DST not in effect.  utcoffset() must include the DST
+        offset.
+        """
+        raise NotImplementedError("tzinfo subclass must override dst()")
+
+    def fromutc(self, dt):
+        "datetime in UTC -> datetime in local time."
+
+        if not isinstance(dt, datetime):
+            raise TypeError("fromutc() requires a datetime argument")
+        if dt.tzinfo is not self:
+            raise ValueError("dt.tzinfo is not self")
+
+        dtoff = dt.utcoffset()
+        if dtoff is None:
+            raise ValueError("fromutc() requires a non-None utcoffset() "
+                             "result")
+
+        # See the long comment block at the end of this file for an
+        # explanation of this algorithm.
+        dtdst = dt.dst()
+        if dtdst is None:
+            raise ValueError("fromutc() requires a non-None dst() result")
+        delta = dtoff - dtdst
+        if delta:
+            dt += delta
+            dtdst = dt.dst()
+            if dtdst is None:
+                raise ValueError("fromutc(): dt.dst gave inconsistent "
+                                 "results; cannot convert")
+        return dt + dtdst
+
+    # Pickle support.
+
+    def __reduce__(self):
+        getinitargs = getattr(self, "__getinitargs__", None)
+        if getinitargs:
+            args = getinitargs()
+        else:
+            args = ()
+        return (self.__class__, args, self.__getstate__())
+
+
+class IsoCalendarDate(tuple):
+
+    def __new__(cls, year, week, weekday, /):
+        return super().__new__(cls, (year, week, weekday))
+
+    @property
+    def year(self):
+        return self[0]
+
+    @property
+    def week(self):
+        return self[1]
+
+    @property
+    def weekday(self):
+        return self[2]
+
+    def __reduce__(self):
+        # This code is intended to pickle the object without making the
+        # class public. See https://bugs.python.org/msg352381
+        return (tuple, (tuple(self),))
+
+    def __repr__(self):
+        return (f'{self.__class__.__name__}'
+                f'(year={self[0]}, week={self[1]}, weekday={self[2]})')
+
+
+_IsoCalendarDate = IsoCalendarDate
+del IsoCalendarDate
+_tzinfo_class = tzinfo
+
+class time:
+    """Time with time zone.
+
+    Constructors:
+
+    __new__()
+
+    Operators:
+
+    __repr__, __str__
+    __eq__, __le__, __lt__, __ge__, __gt__, __hash__
+
+    Methods:
+
+    strftime()
+    isoformat()
+    utcoffset()
+    tzname()
+    dst()
+
+    Properties (readonly):
+    hour, minute, second, microsecond, tzinfo, fold
+    """
+    __slots__ = '_hour', '_minute', '_second', '_microsecond', '_tzinfo', '_hashcode', '_fold'
+
+    def __new__(cls, hour=0, minute=0, second=0, microsecond=0, tzinfo=None, *, fold=0):
+        """Constructor.
+
+        Arguments:
+
+        hour, minute (required)
+        second, microsecond (default to zero)
+        tzinfo (default to None)
+        fold (keyword only, default to zero)
+        """
+        if (isinstance(hour, (bytes, str)) and len(hour) == 6 and
+            ord(hour[0:1])&0x7F < 24):
+            # Pickle support
+            if isinstance(hour, str):
+                try:
+                    hour = hour.encode('latin1')
+                except UnicodeEncodeError:
+                    # More informative error message.
+                    raise ValueError(
+                        "Failed to encode latin1 string when unpickling "
+                        "a time object. "
+                        "pickle.load(data, encoding='latin1') is assumed.")
+            self = object.__new__(cls)
+            self.__setstate(hour, minute or None)
+            self._hashcode = -1
+            return self
+        hour, minute, second, microsecond, fold = _check_time_fields(
+            hour, minute, second, microsecond, fold)
+        _check_tzinfo_arg(tzinfo)
+        self = object.__new__(cls)
+        self._hour = hour
+        self._minute = minute
+        self._second = second
+        self._microsecond = microsecond
+        self._tzinfo = tzinfo
+        self._hashcode = -1
+        self._fold = fold
+        return self
+
+    # Read-only field accessors
+    @property
+    def hour(self):
+        """hour (0-23)"""
+        return self._hour
+
+    @property
+    def minute(self):
+        """minute (0-59)"""
+        return self._minute
+
+    @property
+    def second(self):
+        """second (0-59)"""
+        return self._second
+
+    @property
+    def microsecond(self):
+        """microsecond (0-999999)"""
+        return self._microsecond
+
+    @property
+    def tzinfo(self):
+        """timezone info object"""
+        return self._tzinfo
+
+    @property
+    def fold(self):
+        return self._fold
+
+    # Standard conversions, __hash__ (and helpers)
+
+    # Comparisons of time objects with other.
+
+    def __eq__(self, other):
+        if isinstance(other, time):
+            return self._cmp(other, allow_mixed=True) == 0
+        else:
+            return NotImplemented
+
+    def __le__(self, other):
+        if isinstance(other, time):
+            return self._cmp(other) <= 0
+        else:
+            return NotImplemented
+
+    def __lt__(self, other):
+        if isinstance(other, time):
+            return self._cmp(other) < 0
+        else:
+            return NotImplemented
+
+    def __ge__(self, other):
+        if isinstance(other, time):
+            return self._cmp(other) >= 0
+        else:
+            return NotImplemented
+
+    def __gt__(self, other):
+        if isinstance(other, time):
+            return self._cmp(other) > 0
+        else:
+            return NotImplemented
+
+    def _cmp(self, other, allow_mixed=False):
+        assert isinstance(other, time)
+        mytz = self._tzinfo
+        ottz = other._tzinfo
+        myoff = otoff = None
+
+        if mytz is ottz:
+            base_compare = True
+        else:
+            myoff = self.utcoffset()
+            otoff = other.utcoffset()
+            base_compare = myoff == otoff
+
+        if base_compare:
+            return _cmp((self._hour, self._minute, self._second,
+                         self._microsecond),
+                        (other._hour, other._minute, other._second,
+                         other._microsecond))
+        if myoff is None or otoff is None:
+            if allow_mixed:
+                return 2 # arbitrary non-zero value
+            else:
+                raise TypeError("cannot compare naive and aware times")
+        myhhmm = self._hour * 60 + self._minute - myoff//timedelta(minutes=1)
+        othhmm = other._hour * 60 + other._minute - otoff//timedelta(minutes=1)
+        return _cmp((myhhmm, self._second, self._microsecond),
+                    (othhmm, other._second, other._microsecond))
+
+    def __hash__(self):
+        """Hash."""
+        if self._hashcode == -1:
+            if self.fold:
+                t = self.replace(fold=0)
+            else:
+                t = self
+            tzoff = t.utcoffset()
+            if not tzoff:  # zero or None
+                self._hashcode = hash(t._getstate()[0])
+            else:
+                h, m = divmod(timedelta(hours=self.hour, minutes=self.minute) - tzoff,
+                              timedelta(hours=1))
+                assert not m % timedelta(minutes=1), "whole minute"
+                m //= timedelta(minutes=1)
+                if 0 <= h < 24:
+                    self._hashcode = hash(time(h, m, self.second, self.microsecond))
+                else:
+                    self._hashcode = hash((h, m, self.second, self.microsecond))
+        return self._hashcode
+
+    # Conversion to string
+
+    def _tzstr(self):
+        """Return formatted timezone offset (+xx:xx) or an empty string."""
+        off = self.utcoffset()
+        return _format_offset(off)
+
+    def __repr__(self):
+        """Convert to formal string, for repr()."""
+        if self._microsecond != 0:
+            s = ", %d, %d" % (self._second, self._microsecond)
+        elif self._second != 0:
+            s = ", %d" % self._second
+        else:
+            s = ""
+        s= "%s.%s(%d, %d%s)" % (_get_class_module(self),
+                                self.__class__.__qualname__,
+                                self._hour, self._minute, s)
+        if self._tzinfo is not None:
+            assert s[-1:] == ")"
+            s = s[:-1] + ", tzinfo=%r" % self._tzinfo + ")"
+        if self._fold:
+            assert s[-1:] == ")"
+            s = s[:-1] + ", fold=1)"
+        return s
+
+    def isoformat(self, timespec='auto'):
+        """Return the time formatted according to ISO.
+
+        The full format is 'HH:MM:SS.mmmmmm+zz:zz'. By default, the fractional
+        part is omitted if self.microsecond == 0.
+
+        The optional argument timespec specifies the number of additional
+        terms of the time to include. Valid options are 'auto', 'hours',
+        'minutes', 'seconds', 'milliseconds' and 'microseconds'.
+        """
+        s = _format_time(self._hour, self._minute, self._second,
+                          self._microsecond, timespec)
+        tz = self._tzstr()
+        if tz:
+            s += tz
+        return s
+
+    __str__ = isoformat
+
+    @classmethod
+    def fromisoformat(cls, time_string):
+        """Construct a time from a string in one of the ISO 8601 formats."""
+        if not isinstance(time_string, str):
+            raise TypeError('fromisoformat: argument must be str')
+
+        # The spec actually requires that time-only ISO 8601 strings start with
+        # T, but the extended format allows this to be omitted as long as there
+        # is no ambiguity with date strings.
+        time_string = time_string.removeprefix('T')
+
+        try:
+            return cls(*_parse_isoformat_time(time_string))
+        except Exception:
+            raise ValueError(f'Invalid isoformat string: {time_string!r}')
+
+    def strftime(self, format):
+        """Format using strftime().  The date part of the timestamp passed
+        to underlying strftime should not be used.
+        """
+        # The year must be >= 1000 else Python's strftime implementation
+        # can raise a bogus exception.
+        timetuple = (1900, 1, 1,
+                     self._hour, self._minute, self._second,
+                     0, 1, -1)
+        return _wrap_strftime(self, format, timetuple)
+
+    def __format__(self, fmt):
+        if not isinstance(fmt, str):
+            raise TypeError("must be str, not %s" % type(fmt).__name__)
+        if len(fmt) != 0:
+            return self.strftime(fmt)
+        return str(self)
+
+    # Timezone functions
+
+    def utcoffset(self):
+        """Return the timezone offset as timedelta, positive east of UTC
+         (negative west of UTC)."""
+        if self._tzinfo is None:
+            return None
+        offset = self._tzinfo.utcoffset(None)
+        _check_utc_offset("utcoffset", offset)
+        return offset
+
+    def tzname(self):
+        """Return the timezone name.
+
+        Note that the name is 100% informational -- there's no requirement that
+        it mean anything in particular. For example, "GMT", "UTC", "-500",
+        "-5:00", "EDT", "US/Eastern", "America/New York" are all valid replies.
+        """
+        if self._tzinfo is None:
+            return None
+        name = self._tzinfo.tzname(None)
+        _check_tzname(name)
+        return name
+
+    def dst(self):
+        """Return 0 if DST is not in effect, or the DST offset (as timedelta
+        positive eastward) if DST is in effect.
+
+        This is purely informational; the DST offset has already been added to
+        the UTC offset returned by utcoffset() if applicable, so there's no
+        need to consult dst() unless you're interested in displaying the DST
+        info.
+        """
+        if self._tzinfo is None:
+            return None
+        offset = self._tzinfo.dst(None)
+        _check_utc_offset("dst", offset)
+        return offset
+
+    def replace(self, hour=None, minute=None, second=None, microsecond=None,
+                tzinfo=True, *, fold=None):
+        """Return a new time with new values for the specified fields."""
+        if hour is None:
+            hour = self.hour
+        if minute is None:
+            minute = self.minute
+        if second is None:
+            second = self.second
+        if microsecond is None:
+            microsecond = self.microsecond
+        if tzinfo is True:
+            tzinfo = self.tzinfo
+        if fold is None:
+            fold = self._fold
+        return type(self)(hour, minute, second, microsecond, tzinfo, fold=fold)
+
+    # Pickle support.
+
+    def _getstate(self, protocol=3):
+        us2, us3 = divmod(self._microsecond, 256)
+        us1, us2 = divmod(us2, 256)
+        h = self._hour
+        if self._fold and protocol > 3:
+            h += 128
+        basestate = bytes([h, self._minute, self._second,
+                           us1, us2, us3])
+        if self._tzinfo is None:
+            return (basestate,)
+        else:
+            return (basestate, self._tzinfo)
+
+    def __setstate(self, string, tzinfo):
+        if tzinfo is not None and not isinstance(tzinfo, _tzinfo_class):
+            raise TypeError("bad tzinfo state arg")
+        h, self._minute, self._second, us1, us2, us3 = string
+        if h > 127:
+            self._fold = 1
+            self._hour = h - 128
+        else:
+            self._fold = 0
+            self._hour = h
+        self._microsecond = (((us1 << 8) | us2) << 8) | us3
+        self._tzinfo = tzinfo
+
+    def __reduce_ex__(self, protocol):
+        return (self.__class__, self._getstate(protocol))
+
+    def __reduce__(self):
+        return self.__reduce_ex__(2)
+
+_time_class = time  # so functions w/ args named "time" can get at the class
+
+time.min = time(0, 0, 0)
+time.max = time(23, 59, 59, 999999)
+time.resolution = timedelta(microseconds=1)
+
+
+class datetime(date):
+    """datetime(year, month, day[, hour[, minute[, second[, microsecond[,tzinfo]]]]])
+
+    The year, month and day arguments are required. tzinfo may be None, or an
+    instance of a tzinfo subclass. The remaining arguments may be ints.
+    """
+    __slots__ = date.__slots__ + time.__slots__
+
+    def __new__(cls, year, month=None, day=None, hour=0, minute=0, second=0,
+                microsecond=0, tzinfo=None, *, fold=0):
+        if (isinstance(year, (bytes, str)) and len(year) == 10 and
+            1 <= ord(year[2:3])&0x7F <= 12):
+            # Pickle support
+            if isinstance(year, str):
+                try:
+                    year = bytes(year, 'latin1')
+                except UnicodeEncodeError:
+                    # More informative error message.
+                    raise ValueError(
+                        "Failed to encode latin1 string when unpickling "
+                        "a datetime object. "
+                        "pickle.load(data, encoding='latin1') is assumed.")
+            self = object.__new__(cls)
+            self.__setstate(year, month)
+            self._hashcode = -1
+            return self
+        year, month, day = _check_date_fields(year, month, day)
+        hour, minute, second, microsecond, fold = _check_time_fields(
+            hour, minute, second, microsecond, fold)
+        _check_tzinfo_arg(tzinfo)
+        self = object.__new__(cls)
+        self._year = year
+        self._month = month
+        self._day = day
+        self._hour = hour
+        self._minute = minute
+        self._second = second
+        self._microsecond = microsecond
+        self._tzinfo = tzinfo
+        self._hashcode = -1
+        self._fold = fold
+        return self
+
+    # Read-only field accessors
+    @property
+    def hour(self):
+        """hour (0-23)"""
+        return self._hour
+
+    @property
+    def minute(self):
+        """minute (0-59)"""
+        return self._minute
+
+    @property
+    def second(self):
+        """second (0-59)"""
+        return self._second
+
+    @property
+    def microsecond(self):
+        """microsecond (0-999999)"""
+        return self._microsecond
+
+    @property
+    def tzinfo(self):
+        """timezone info object"""
+        return self._tzinfo
+
+    @property
+    def fold(self):
+        return self._fold
+
+    @classmethod
+    def _fromtimestamp(cls, t, utc, tz):
+        """Construct a datetime from a POSIX timestamp (like time.time()).
+
+        A timezone info object may be passed in as well.
+        """
+        frac, t = _math.modf(t)
+        us = round(frac * 1e6)
+        if us >= 1000000:
+            t += 1
+            us -= 1000000
+        elif us < 0:
+            t -= 1
+            us += 1000000
+
+        converter = _time.gmtime if utc else _time.localtime
+        y, m, d, hh, mm, ss, weekday, jday, dst = converter(t)
+        ss = min(ss, 59)    # clamp out leap seconds if the platform has them
+        result = cls(y, m, d, hh, mm, ss, us, tz)
+        if tz is None and not utc:
+            # As of version 2015f max fold in IANA database is
+            # 23 hours at 1969-09-30 13:00:00 in Kwajalein.
+            # Let's probe 24 hours in the past to detect a transition:
+            max_fold_seconds = 24 * 3600
+
+            # On Windows localtime_s throws an OSError for negative values,
+            # thus we can't perform fold detection for values of time less
+            # than the max time fold. See comments in _datetimemodule's
+            # version of this method for more details.
+            if t < max_fold_seconds and sys.platform.startswith("win"):
+                return result
+
+            y, m, d, hh, mm, ss = converter(t - max_fold_seconds)[:6]
+            probe1 = cls(y, m, d, hh, mm, ss, us, tz)
+            trans = result - probe1 - timedelta(0, max_fold_seconds)
+            if trans.days < 0:
+                y, m, d, hh, mm, ss = converter(t + trans // timedelta(0, 1))[:6]
+                probe2 = cls(y, m, d, hh, mm, ss, us, tz)
+                if probe2 == result:
+                    result._fold = 1
+        elif tz is not None:
+            result = tz.fromutc(result)
+        return result
+
+    @classmethod
+    def fromtimestamp(cls, timestamp, tz=None):
+        """Construct a datetime from a POSIX timestamp (like time.time()).
+
+        A timezone info object may be passed in as well.
+        """
+        _check_tzinfo_arg(tz)
+
+        return cls._fromtimestamp(timestamp, tz is not None, tz)
+
+    @classmethod
+    def utcfromtimestamp(cls, t):
+        """Construct a naive UTC datetime from a POSIX timestamp."""
+        import warnings
+        warnings.warn("datetime.utcfromtimestamp() is deprecated and scheduled "
+                      "for removal in a future version. Use timezone-aware "
+                      "objects to represent datetimes in UTC: "
+                      "datetime.fromtimestamp(t, datetime.UTC).",
+                      DeprecationWarning,
+                      stacklevel=2)
+        return cls._fromtimestamp(t, True, None)
+
+    @classmethod
+    def now(cls, tz=None):
+        "Construct a datetime from time.time() and optional time zone info."
+        t = _time.time()
+        return cls.fromtimestamp(t, tz)
+
+    @classmethod
+    def utcnow(cls):
+        "Construct a UTC datetime from time.time()."
+        import warnings
+        warnings.warn("datetime.utcnow() is deprecated and scheduled for "
+                      "removal in a future version. Instead, Use timezone-aware "
+                      "objects to represent datetimes in UTC: "
+                      "datetime.now(datetime.UTC).",
+                      DeprecationWarning,
+                      stacklevel=2)
+        t = _time.time()
+        return cls._fromtimestamp(t, True, None)
+
+    @classmethod
+    def combine(cls, date, time, tzinfo=True):
+        "Construct a datetime from a given date and a given time."
+        if not isinstance(date, _date_class):
+            raise TypeError("date argument must be a date instance")
+        if not isinstance(time, _time_class):
+            raise TypeError("time argument must be a time instance")
+        if tzinfo is True:
+            tzinfo = time.tzinfo
+        return cls(date.year, date.month, date.day,
+                   time.hour, time.minute, time.second, time.microsecond,
+                   tzinfo, fold=time.fold)
+
+    @classmethod
+    def fromisoformat(cls, date_string):
+        """Construct a datetime from a string in one of the ISO 8601 formats."""
+        if not isinstance(date_string, str):
+            raise TypeError('fromisoformat: argument must be str')
+
+        if len(date_string) < 7:
+            raise ValueError(f'Invalid isoformat string: {date_string!r}')
+
+        # Split this at the separator
+        try:
+            separator_location = _find_isoformat_datetime_separator(date_string)
+            dstr = date_string[0:separator_location]
+            tstr = date_string[(separator_location+1):]
+
+            date_components = _parse_isoformat_date(dstr)
+        except ValueError:
+            raise ValueError(
+                f'Invalid isoformat string: {date_string!r}') from None
+
+        if tstr:
+            try:
+                time_components = _parse_isoformat_time(tstr)
+            except ValueError:
+                raise ValueError(
+                    f'Invalid isoformat string: {date_string!r}') from None
+        else:
+            time_components = [0, 0, 0, 0, None]
+
+        return cls(*(date_components + time_components))
+
+    def timetuple(self):
+        "Return local time tuple compatible with time.localtime()."
+        dst = self.dst()
+        if dst is None:
+            dst = -1
+        elif dst:
+            dst = 1
+        else:
+            dst = 0
+        return _build_struct_time(self.year, self.month, self.day,
+                                  self.hour, self.minute, self.second,
+                                  dst)
+
+    def _mktime(self):
+        """Return integer POSIX timestamp."""
+        epoch = datetime(1970, 1, 1)
+        max_fold_seconds = 24 * 3600
+        t = (self - epoch) // timedelta(0, 1)
+        def local(u):
+            y, m, d, hh, mm, ss = _time.localtime(u)[:6]
+            return (datetime(y, m, d, hh, mm, ss) - epoch) // timedelta(0, 1)
+
+        # Our goal is to solve t = local(u) for u.
+        a = local(t) - t
+        u1 = t - a
+        t1 = local(u1)
+        if t1 == t:
+            # We found one solution, but it may not be the one we need.
+            # Look for an earlier solution (if `fold` is 0), or a
+            # later one (if `fold` is 1).
+            u2 = u1 + (-max_fold_seconds, max_fold_seconds)[self.fold]
+            b = local(u2) - u2
+            if a == b:
+                return u1
+        else:
+            b = t1 - u1
+            assert a != b
+        u2 = t - b
+        t2 = local(u2)
+        if t2 == t:
+            return u2
+        if t1 == t:
+            return u1
+        # We have found both offsets a and b, but neither t - a nor t - b is
+        # a solution.  This means t is in the gap.
+        return (max, min)[self.fold](u1, u2)
+
+
+    def timestamp(self):
+        "Return POSIX timestamp as float"
+        if self._tzinfo is None:
+            s = self._mktime()
+            return s + self.microsecond / 1e6
+        else:
+            return (self - _EPOCH).total_seconds()
+
+    def utctimetuple(self):
+        "Return UTC time tuple compatible with time.gmtime()."
+        offset = self.utcoffset()
+        if offset:
+            self -= offset
+        y, m, d = self.year, self.month, self.day
+        hh, mm, ss = self.hour, self.minute, self.second
+        return _build_struct_time(y, m, d, hh, mm, ss, 0)
+
+    def date(self):
+        "Return the date part."
+        return date(self._year, self._month, self._day)
+
+    def time(self):
+        "Return the time part, with tzinfo None."
+        return time(self.hour, self.minute, self.second, self.microsecond, fold=self.fold)
+
+    def timetz(self):
+        "Return the time part, with same tzinfo."
+        return time(self.hour, self.minute, self.second, self.microsecond,
+                    self._tzinfo, fold=self.fold)
+
+    def replace(self, year=None, month=None, day=None, hour=None,
+                minute=None, second=None, microsecond=None, tzinfo=True,
+                *, fold=None):
+        """Return a new datetime with new values for the specified fields."""
+        if year is None:
+            year = self.year
+        if month is None:
+            month = self.month
+        if day is None:
+            day = self.day
+        if hour is None:
+            hour = self.hour
+        if minute is None:
+            minute = self.minute
+        if second is None:
+            second = self.second
+        if microsecond is None:
+            microsecond = self.microsecond
+        if tzinfo is True:
+            tzinfo = self.tzinfo
+        if fold is None:
+            fold = self.fold
+        return type(self)(year, month, day, hour, minute, second,
+                          microsecond, tzinfo, fold=fold)
+
+    def _local_timezone(self):
+        if self.tzinfo is None:
+            ts = self._mktime()
+            # Detect gap
+            ts2 = self.replace(fold=1-self.fold)._mktime()
+            if ts2 != ts: # This happens in a gap or a fold
+                if (ts2 > ts) == self.fold:
+                    ts = ts2
+        else:
+            ts = (self - _EPOCH) // timedelta(seconds=1)
+        localtm = _time.localtime(ts)
+        local = datetime(*localtm[:6])
+        # Extract TZ data
+        gmtoff = localtm.tm_gmtoff
+        zone = localtm.tm_zone
+        return timezone(timedelta(seconds=gmtoff), zone)
+
+    def astimezone(self, tz=None):
+        if tz is None:
+            tz = self._local_timezone()
+        elif not isinstance(tz, tzinfo):
+            raise TypeError("tz argument must be an instance of tzinfo")
+
+        mytz = self.tzinfo
+        if mytz is None:
+            mytz = self._local_timezone()
+            myoffset = mytz.utcoffset(self)
+        else:
+            myoffset = mytz.utcoffset(self)
+            if myoffset is None:
+                mytz = self.replace(tzinfo=None)._local_timezone()
+                myoffset = mytz.utcoffset(self)
+
+        if tz is mytz:
+            return self
+
+        # Convert self to UTC, and attach the new time zone object.
+        utc = (self - myoffset).replace(tzinfo=tz)
+
+        # Convert from UTC to tz's local time.
+        return tz.fromutc(utc)
+
+    # Ways to produce a string.
+
+    def ctime(self):
+        "Return ctime() style string."
+        weekday = self.toordinal() % 7 or 7
+        return "%s %s %2d %02d:%02d:%02d %04d" % (
+            _DAYNAMES[weekday],
+            _MONTHNAMES[self._month],
+            self._day,
+            self._hour, self._minute, self._second,
+            self._year)
+
+    def isoformat(self, sep='T', timespec='auto'):
+        """Return the time formatted according to ISO.
+
+        The full format looks like 'YYYY-MM-DD HH:MM:SS.mmmmmm'.
+        By default, the fractional part is omitted if self.microsecond == 0.
+
+        If self.tzinfo is not None, the UTC offset is also attached, giving
+        giving a full format of 'YYYY-MM-DD HH:MM:SS.mmmmmm+HH:MM'.
+
+        Optional argument sep specifies the separator between date and
+        time, default 'T'.
+
+        The optional argument timespec specifies the number of additional
+        terms of the time to include. Valid options are 'auto', 'hours',
+        'minutes', 'seconds', 'milliseconds' and 'microseconds'.
+        """
+        s = ("%04d-%02d-%02d%c" % (self._year, self._month, self._day, sep) +
+             _format_time(self._hour, self._minute, self._second,
+                          self._microsecond, timespec))
+
+        off = self.utcoffset()
+        tz = _format_offset(off)
+        if tz:
+            s += tz
+
+        return s
+
+    def __repr__(self):
+        """Convert to formal string, for repr()."""
+        L = [self._year, self._month, self._day,  # These are never zero
+             self._hour, self._minute, self._second, self._microsecond]
+        if L[-1] == 0:
+            del L[-1]
+        if L[-1] == 0:
+            del L[-1]
+        s = "%s.%s(%s)" % (_get_class_module(self),
+                           self.__class__.__qualname__,
+                           ", ".join(map(str, L)))
+        if self._tzinfo is not None:
+            assert s[-1:] == ")"
+            s = s[:-1] + ", tzinfo=%r" % self._tzinfo + ")"
+        if self._fold:
+            assert s[-1:] == ")"
+            s = s[:-1] + ", fold=1)"
+        return s
+
+    def __str__(self):
+        "Convert to string, for str()."
+        return self.isoformat(sep=' ')
+
+    @classmethod
+    def strptime(cls, date_string, format):
+        'string, format -> new datetime parsed from a string (like time.strptime()).'
+        import _strptime
+        return _strptime._strptime_datetime(cls, date_string, format)
+
+    def utcoffset(self):
+        """Return the timezone offset as timedelta positive east of UTC (negative west of
+        UTC)."""
+        if self._tzinfo is None:
+            return None
+        offset = self._tzinfo.utcoffset(self)
+        _check_utc_offset("utcoffset", offset)
+        return offset
+
+    def tzname(self):
+        """Return the timezone name.
+
+        Note that the name is 100% informational -- there's no requirement that
+        it mean anything in particular. For example, "GMT", "UTC", "-500",
+        "-5:00", "EDT", "US/Eastern", "America/New York" are all valid replies.
+        """
+        if self._tzinfo is None:
+            return None
+        name = self._tzinfo.tzname(self)
+        _check_tzname(name)
+        return name
+
+    def dst(self):
+        """Return 0 if DST is not in effect, or the DST offset (as timedelta
+        positive eastward) if DST is in effect.
+
+        This is purely informational; the DST offset has already been added to
+        the UTC offset returned by utcoffset() if applicable, so there's no
+        need to consult dst() unless you're interested in displaying the DST
+        info.
+        """
+        if self._tzinfo is None:
+            return None
+        offset = self._tzinfo.dst(self)
+        _check_utc_offset("dst", offset)
+        return offset
+
+    # Comparisons of datetime objects with other.
+
+    def __eq__(self, other):
+        if isinstance(other, datetime):
+            return self._cmp(other, allow_mixed=True) == 0
+        elif not isinstance(other, date):
+            return NotImplemented
+        else:
+            return False
+
+    def __le__(self, other):
+        if isinstance(other, datetime):
+            return self._cmp(other) <= 0
+        elif not isinstance(other, date):
+            return NotImplemented
+        else:
+            _cmperror(self, other)
+
+    def __lt__(self, other):
+        if isinstance(other, datetime):
+            return self._cmp(other) < 0
+        elif not isinstance(other, date):
+            return NotImplemented
+        else:
+            _cmperror(self, other)
+
+    def __ge__(self, other):
+        if isinstance(other, datetime):
+            return self._cmp(other) >= 0
+        elif not isinstance(other, date):
+            return NotImplemented
+        else:
+            _cmperror(self, other)
+
+    def __gt__(self, other):
+        if isinstance(other, datetime):
+            return self._cmp(other) > 0
+        elif not isinstance(other, date):
+            return NotImplemented
+        else:
+            _cmperror(self, other)
+
+    def _cmp(self, other, allow_mixed=False):
+        assert isinstance(other, datetime)
+        mytz = self._tzinfo
+        ottz = other._tzinfo
+        myoff = otoff = None
+
+        if mytz is ottz:
+            base_compare = True
+        else:
+            myoff = self.utcoffset()
+            otoff = other.utcoffset()
+            # Assume that allow_mixed means that we are called from __eq__
+            if allow_mixed:
+                if myoff != self.replace(fold=not self.fold).utcoffset():
+                    return 2
+                if otoff != other.replace(fold=not other.fold).utcoffset():
+                    return 2
+            base_compare = myoff == otoff
+
+        if base_compare:
+            return _cmp((self._year, self._month, self._day,
+                         self._hour, self._minute, self._second,
+                         self._microsecond),
+                        (other._year, other._month, other._day,
+                         other._hour, other._minute, other._second,
+                         other._microsecond))
+        if myoff is None or otoff is None:
+            if allow_mixed:
+                return 2 # arbitrary non-zero value
+            else:
+                raise TypeError("cannot compare naive and aware datetimes")
+        # XXX What follows could be done more efficiently...
+        diff = self - other     # this will take offsets into account
+        if diff.days < 0:
+            return -1
+        return diff and 1 or 0
+
+    def __add__(self, other):
+        "Add a datetime and a timedelta."
+        if not isinstance(other, timedelta):
+            return NotImplemented
+        delta = timedelta(self.toordinal(),
+                          hours=self._hour,
+                          minutes=self._minute,
+                          seconds=self._second,
+                          microseconds=self._microsecond)
+        delta += other
+        hour, rem = divmod(delta.seconds, 3600)
+        minute, second = divmod(rem, 60)
+        if 0 < delta.days <= _MAXORDINAL:
+            return type(self).combine(date.fromordinal(delta.days),
+                                      time(hour, minute, second,
+                                           delta.microseconds,
+                                           tzinfo=self._tzinfo))
+        raise OverflowError("result out of range")
+
+    __radd__ = __add__
+
+    def __sub__(self, other):
+        "Subtract two datetimes, or a datetime and a timedelta."
+        if not isinstance(other, datetime):
+            if isinstance(other, timedelta):
+                return self + -other
+            return NotImplemented
+
+        days1 = self.toordinal()
+        days2 = other.toordinal()
+        secs1 = self._second + self._minute * 60 + self._hour * 3600
+        secs2 = other._second + other._minute * 60 + other._hour * 3600
+        base = timedelta(days1 - days2,
+                         secs1 - secs2,
+                         self._microsecond - other._microsecond)
+        if self._tzinfo is other._tzinfo:
+            return base
+        myoff = self.utcoffset()
+        otoff = other.utcoffset()
+        if myoff == otoff:
+            return base
+        if myoff is None or otoff is None:
+            raise TypeError("cannot mix naive and timezone-aware time")
+        return base + otoff - myoff
+
+    def __hash__(self):
+        if self._hashcode == -1:
+            if self.fold:
+                t = self.replace(fold=0)
+            else:
+                t = self
+            tzoff = t.utcoffset()
+            if tzoff is None:
+                self._hashcode = hash(t._getstate()[0])
+            else:
+                days = _ymd2ord(self.year, self.month, self.day)
+                seconds = self.hour * 3600 + self.minute * 60 + self.second
+                self._hashcode = hash(timedelta(days, seconds, self.microsecond) - tzoff)
+        return self._hashcode
+
+    # Pickle support.
+
+    def _getstate(self, protocol=3):
+        yhi, ylo = divmod(self._year, 256)
+        us2, us3 = divmod(self._microsecond, 256)
+        us1, us2 = divmod(us2, 256)
+        m = self._month
+        if self._fold and protocol > 3:
+            m += 128
+        basestate = bytes([yhi, ylo, m, self._day,
+                           self._hour, self._minute, self._second,
+                           us1, us2, us3])
+        if self._tzinfo is None:
+            return (basestate,)
+        else:
+            return (basestate, self._tzinfo)
+
+    def __setstate(self, string, tzinfo):
+        if tzinfo is not None and not isinstance(tzinfo, _tzinfo_class):
+            raise TypeError("bad tzinfo state arg")
+        (yhi, ylo, m, self._day, self._hour,
+         self._minute, self._second, us1, us2, us3) = string
+        if m > 127:
+            self._fold = 1
+            self._month = m - 128
+        else:
+            self._fold = 0
+            self._month = m
+        self._year = yhi * 256 + ylo
+        self._microsecond = (((us1 << 8) | us2) << 8) | us3
+        self._tzinfo = tzinfo
+
+    def __reduce_ex__(self, protocol):
+        return (self.__class__, self._getstate(protocol))
+
+    def __reduce__(self):
+        return self.__reduce_ex__(2)
+
+
+datetime.min = datetime(1, 1, 1)
+datetime.max = datetime(9999, 12, 31, 23, 59, 59, 999999)
+datetime.resolution = timedelta(microseconds=1)
+
+
+def _isoweek1monday(year):
+    # Helper to calculate the day number of the Monday starting week 1
+    # XXX This could be done more efficiently
+    THURSDAY = 3
+    firstday = _ymd2ord(year, 1, 1)
+    firstweekday = (firstday + 6) % 7  # See weekday() above
+    week1monday = firstday - firstweekday
+    if firstweekday > THURSDAY:
+        week1monday += 7
+    return week1monday
+
+
+class timezone(tzinfo):
+    __slots__ = '_offset', '_name'
+
+    # Sentinel value to disallow None
+    _Omitted = object()
+    def __new__(cls, offset, name=_Omitted):
+        if not isinstance(offset, timedelta):
+            raise TypeError("offset must be a timedelta")
+        if name is cls._Omitted:
+            if not offset:
+                return cls.utc
+            name = None
+        elif not isinstance(name, str):
+            raise TypeError("name must be a string")
+        if not cls._minoffset <= offset <= cls._maxoffset:
+            raise ValueError("offset must be a timedelta "
+                             "strictly between -timedelta(hours=24) and "
+                             "timedelta(hours=24).")
+        return cls._create(offset, name)
+
+    @classmethod
+    def _create(cls, offset, name=None):
+        self = tzinfo.__new__(cls)
+        self._offset = offset
+        self._name = name
+        return self
+
+    def __getinitargs__(self):
+        """pickle support"""
+        if self._name is None:
+            return (self._offset,)
+        return (self._offset, self._name)
+
+    def __eq__(self, other):
+        if isinstance(other, timezone):
+            return self._offset == other._offset
+        return NotImplemented
+
+    def __hash__(self):
+        return hash(self._offset)
+
+    def __repr__(self):
+        """Convert to formal string, for repr().
+
+        >>> tz = timezone.utc
+        >>> repr(tz)
+        'datetime.timezone.utc'
+        >>> tz = timezone(timedelta(hours=-5), 'EST')
+        >>> repr(tz)
+        "datetime.timezone(datetime.timedelta(-1, 68400), 'EST')"
+        """
+        if self is self.utc:
+            return 'datetime.timezone.utc'
+        if self._name is None:
+            return "%s.%s(%r)" % (_get_class_module(self),
+                                  self.__class__.__qualname__,
+                                  self._offset)
+        return "%s.%s(%r, %r)" % (_get_class_module(self),
+                                  self.__class__.__qualname__,
+                                  self._offset, self._name)
+
+    def __str__(self):
+        return self.tzname(None)
+
+    def utcoffset(self, dt):
+        if isinstance(dt, datetime) or dt is None:
+            return self._offset
+        raise TypeError("utcoffset() argument must be a datetime instance"
+                        " or None")
+
+    def tzname(self, dt):
+        if isinstance(dt, datetime) or dt is None:
+            if self._name is None:
+                return self._name_from_offset(self._offset)
+            return self._name
+        raise TypeError("tzname() argument must be a datetime instance"
+                        " or None")
+
+    def dst(self, dt):
+        if isinstance(dt, datetime) or dt is None:
+            return None
+        raise TypeError("dst() argument must be a datetime instance"
+                        " or None")
+
+    def fromutc(self, dt):
+        if isinstance(dt, datetime):
+            if dt.tzinfo is not self:
+                raise ValueError("fromutc: dt.tzinfo "
+                                 "is not self")
+            return dt + self._offset
+        raise TypeError("fromutc() argument must be a datetime instance"
+                        " or None")
+
+    _maxoffset = timedelta(hours=24, microseconds=-1)
+    _minoffset = -_maxoffset
+
+    @staticmethod
+    def _name_from_offset(delta):
+        if not delta:
+            return 'UTC'
+        if delta < timedelta(0):
+            sign = '-'
+            delta = -delta
+        else:
+            sign = '+'
+        hours, rest = divmod(delta, timedelta(hours=1))
+        minutes, rest = divmod(rest, timedelta(minutes=1))
+        seconds = rest.seconds
+        microseconds = rest.microseconds
+        if microseconds:
+            return (f'UTC{sign}{hours:02d}:{minutes:02d}:{seconds:02d}'
+                    f'.{microseconds:06d}')
+        if seconds:
+            return f'UTC{sign}{hours:02d}:{minutes:02d}:{seconds:02d}'
+        return f'UTC{sign}{hours:02d}:{minutes:02d}'
+
+UTC = timezone.utc = timezone._create(timedelta(0))
+
+# bpo-37642: These attributes are rounded to the nearest minute for backwards
+# compatibility, even though the constructor will accept a wider range of
+# values. This may change in the future.
+timezone.min = timezone._create(-timedelta(hours=23, minutes=59))
+timezone.max = timezone._create(timedelta(hours=23, minutes=59))
+_EPOCH = datetime(1970, 1, 1, tzinfo=timezone.utc)
+
+# Some time zone algebra.  For a datetime x, let
+#     x.n = x stripped of its timezone -- its naive time.
+#     x.o = x.utcoffset(), and assuming that doesn't raise an exception or
+#           return None
+#     x.d = x.dst(), and assuming that doesn't raise an exception or
+#           return None
+#     x.s = x's standard offset, x.o - x.d
+#
+# Now some derived rules, where k is a duration (timedelta).
+#
+# 1. x.o = x.s + x.d
+#    This follows from the definition of x.s.
+#
+# 2. If x and y have the same tzinfo member, x.s = y.s.
+#    This is actually a requirement, an assumption we need to make about
+#    sane tzinfo classes.
+#
+# 3. The naive UTC time corresponding to x is x.n - x.o.
+#    This is again a requirement for a sane tzinfo class.
+#
+# 4. (x+k).s = x.s
+#    This follows from #2, and that datetime.timetz+timedelta preserves tzinfo.
+#
+# 5. (x+k).n = x.n + k
+#    Again follows from how arithmetic is defined.
+#
+# Now we can explain tz.fromutc(x).  Let's assume it's an interesting case
+# (meaning that the various tzinfo methods exist, and don't blow up or return
+# None when called).
+#
+# The function wants to return a datetime y with timezone tz, equivalent to x.
+# x is already in UTC.
+#
+# By #3, we want
+#
+#     y.n - y.o = x.n                             [1]
+#
+# The algorithm starts by attaching tz to x.n, and calling that y.  So
+# x.n = y.n at the start.  Then it wants to add a duration k to y, so that [1]
+# becomes true; in effect, we want to solve [2] for k:
+#
+#    (y+k).n - (y+k).o = x.n                      [2]
+#
+# By #1, this is the same as
+#
+#    (y+k).n - ((y+k).s + (y+k).d) = x.n          [3]
+#
+# By #5, (y+k).n = y.n + k, which equals x.n + k because x.n=y.n at the start.
+# Substituting that into [3],
+#
+#    x.n + k - (y+k).s - (y+k).d = x.n; the x.n terms cancel, leaving
+#    k - (y+k).s - (y+k).d = 0; rearranging,
+#    k = (y+k).s - (y+k).d; by #4, (y+k).s == y.s, so
+#    k = y.s - (y+k).d
+#
+# On the RHS, (y+k).d can't be computed directly, but y.s can be, and we
+# approximate k by ignoring the (y+k).d term at first.  Note that k can't be
+# very large, since all offset-returning methods return a duration of magnitude
+# less than 24 hours.  For that reason, if y is firmly in std time, (y+k).d must
+# be 0, so ignoring it has no consequence then.
+#
+# In any case, the new value is
+#
+#     z = y + y.s                                 [4]
+#
+# It's helpful to step back at look at [4] from a higher level:  it's simply
+# mapping from UTC to tz's standard time.
+#
+# At this point, if
+#
+#     z.n - z.o = x.n                             [5]
+#
+# we have an equivalent time, and are almost done.  The insecurity here is
+# at the start of daylight time.  Picture US Eastern for concreteness.  The wall
+# time jumps from 1:59 to 3:00, and wall hours of the form 2:MM don't make good
+# sense then.  The docs ask that an Eastern tzinfo class consider such a time to
+# be EDT (because it's "after 2"), which is a redundant spelling of 1:MM EST
+# on the day DST starts.  We want to return the 1:MM EST spelling because that's
+# the only spelling that makes sense on the local wall clock.
+#
+# In fact, if [5] holds at this point, we do have the standard-time spelling,
+# but that takes a bit of proof.  We first prove a stronger result.  What's the
+# difference between the LHS and RHS of [5]?  Let
+#
+#     diff = x.n - (z.n - z.o)                    [6]
+#
+# Now
+#     z.n =                       by [4]
+#     (y + y.s).n =               by #5
+#     y.n + y.s =                 since y.n = x.n
+#     x.n + y.s =                 since z and y are have the same tzinfo member,
+#                                     y.s = z.s by #2
+#     x.n + z.s
+#
+# Plugging that back into [6] gives
+#
+#     diff =
+#     x.n - ((x.n + z.s) - z.o) =     expanding
+#     x.n - x.n - z.s + z.o =         cancelling
+#     - z.s + z.o =                   by #2
+#     z.d
+#
+# So diff = z.d.
+#
+# If [5] is true now, diff = 0, so z.d = 0 too, and we have the standard-time
+# spelling we wanted in the endcase described above.  We're done.  Contrarily,
+# if z.d = 0, then we have a UTC equivalent, and are also done.
+#
+# If [5] is not true now, diff = z.d != 0, and z.d is the offset we need to
+# add to z (in effect, z is in tz's standard time, and we need to shift the
+# local clock into tz's daylight time).
+#
+# Let
+#
+#     z' = z + z.d = z + diff                     [7]
+#
+# and we can again ask whether
+#
+#     z'.n - z'.o = x.n                           [8]
+#
+# If so, we're done.  If not, the tzinfo class is insane, according to the
+# assumptions we've made.  This also requires a bit of proof.  As before, let's
+# compute the difference between the LHS and RHS of [8] (and skipping some of
+# the justifications for the kinds of substitutions we've done several times
+# already):
+#
+#     diff' = x.n - (z'.n - z'.o) =           replacing z'.n via [7]
+#             x.n  - (z.n + diff - z'.o) =    replacing diff via [6]
+#             x.n - (z.n + x.n - (z.n - z.o) - z'.o) =
+#             x.n - z.n - x.n + z.n - z.o + z'.o =    cancel x.n
+#             - z.n + z.n - z.o + z'.o =              cancel z.n
+#             - z.o + z'.o =                      #1 twice
+#             -z.s - z.d + z'.s + z'.d =          z and z' have same tzinfo
+#             z'.d - z.d
+#
+# So z' is UTC-equivalent to x iff z'.d = z.d at this point.  If they are equal,
+# we've found the UTC-equivalent so are done.  In fact, we stop with [7] and
+# return z', not bothering to compute z'.d.
+#
+# How could z.d and z'd differ?  z' = z + z.d [7], so merely moving z' by
+# a dst() offset, and starting *from* a time already in DST (we know z.d != 0),
+# would have to change the result dst() returns:  we start in DST, and moving
+# a little further into it takes us out of DST.
+#
+# There isn't a sane case where this can happen.  The closest it gets is at
+# the end of DST, where there's an hour in UTC with no spelling in a hybrid
+# tzinfo class.  In US Eastern, that's 5:MM UTC = 0:MM EST = 1:MM EDT.  During
+# that hour, on an Eastern clock 1:MM is taken as being in standard time (6:MM
+# UTC) because the docs insist on that, but 0:MM is taken as being in daylight
+# time (4:MM UTC).  There is no local time mapping to 5:MM UTC.  The local
+# clock jumps from 1:59 back to 1:00 again, and repeats the 1:MM hour in
+# standard time.  Since that's what the local clock *does*, we want to map both
+# UTC hours 5:MM and 6:MM to 1:MM Eastern.  The result is ambiguous
+# in local time, but so it goes -- it's the way the local clock works.
+#
+# When x = 5:MM UTC is the input to this algorithm, x.o=0, y.o=-5 and y.d=0,
+# so z=0:MM.  z.d=60 (minutes) then, so [5] doesn't hold and we keep going.
+# z' = z + z.d = 1:MM then, and z'.d=0, and z'.d - z.d = -60 != 0 so [8]
+# (correctly) concludes that z' is not UTC-equivalent to x.
+#
+# Because we know z.d said z was in daylight time (else [5] would have held and
+# we would have stopped then), and we know z.d != z'.d (else [8] would have held
+# and we have stopped then), and there are only 2 possible values dst() can
+# return in Eastern, it follows that z'.d must be 0 (which it is in the example,
+# but the reasoning doesn't depend on the example -- it depends on there being
+# two possible dst() outcomes, one zero and the other non-zero).  Therefore
+# z' must be in standard time, and is the spelling we want in this case.
+#
+# Note again that z' is not UTC-equivalent as far as the hybrid tzinfo class is
+# concerned (because it takes z' as being in standard time rather than the
+# daylight time we intend here), but returning it gives the real-life "local
+# clock repeats an hour" behavior when mapping the "unspellable" UTC hour into
+# tz.
+#
+# When the input is 6:MM, z=1:MM and z.d=0, and we stop at once, again with
+# the 1:MM standard time spelling we want.
+#
+# So how can this break?  One of the assumptions must be violated.  Two
+# possibilities:
+#
+# 1) [2] effectively says that y.s is invariant across all y belong to a given
+#    time zone.  This isn't true if, for political reasons or continental drift,
+#    a region decides to change its base offset from UTC.
+#
+# 2) There may be versions of "double daylight" time where the tail end of
+#    the analysis gives up a step too early.  I haven't thought about that
+#    enough to say.
+#
+# In any case, it's clear that the default fromutc() is strong enough to handle
+# "almost all" time zones:  so long as the standard offset is invariant, it
+# doesn't matter if daylight time transition points change from year to year, or
+# if daylight time is skipped in some years; it doesn't matter how large or
+# small dst() may get within its bounds; and it doesn't even matter if some
+# perverse time zone returns a negative dst()).  So a breaking case must be
+# pretty bizarre, and a tzinfo subclass can override fromutc() if it is.
diff -pruN 3.12.0~a7-1/Lib/_strptime.py 3.12.0~b1-1/Lib/_strptime.py
--- 3.12.0~a7-1/Lib/_strptime.py	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Lib/_strptime.py	2023-05-22 12:07:36.000000000 +0000
@@ -290,22 +290,6 @@ def _calc_julian_from_U_or_W(year, week_
         return 1 + days_to_week + day_of_week
 
 
-def _calc_julian_from_V(iso_year, iso_week, iso_weekday):
-    """Calculate the Julian day based on the ISO 8601 year, week, and weekday.
-    ISO weeks start on Mondays, with week 01 being the week containing 4 Jan.
-    ISO week days range from 1 (Monday) to 7 (Sunday).
-    """
-    correction = datetime_date(iso_year, 1, 4).isoweekday() + 3
-    ordinal = (iso_week * 7) + iso_weekday - correction
-    # ordinal may be negative or 0 now, which means the date is in the previous
-    # calendar year
-    if ordinal < 1:
-        ordinal += datetime_date(iso_year, 1, 1).toordinal()
-        iso_year -= 1
-        ordinal -= datetime_date(iso_year, 1, 1).toordinal()
-    return iso_year, ordinal
-
-
 def _strptime(data_string, format="%a %b %d %H:%M:%S %Y"):
     """Return a 2-tuple consisting of a time struct and an int containing
     the number of microseconds based on the input string and the
@@ -483,7 +467,8 @@ def _strptime(data_string, format="%a %b
                     else:
                         tz = value
                         break
-    # Deal with the cases where ambiguities arize
+
+    # Deal with the cases where ambiguities arise
     # don't assume default values for ISO week/year
     if year is None and iso_year is not None:
         if iso_week is None or weekday is None:
@@ -511,7 +496,6 @@ def _strptime(data_string, format="%a %b
     elif year is None:
         year = 1900
 
-
     # If we know the week of the year and what day of that week, we can figure
     # out the Julian day of the year.
     if julian is None and weekday is not None:
@@ -520,7 +504,10 @@ def _strptime(data_string, format="%a %b
             julian = _calc_julian_from_U_or_W(year, week_of_year, weekday,
                                                 week_starts_Mon)
         elif iso_year is not None and iso_week is not None:
-            year, julian = _calc_julian_from_V(iso_year, iso_week, weekday + 1)
+            datetime_result = datetime_date.fromisocalendar(iso_year, iso_week, weekday + 1)
+            year = datetime_result.year
+            month = datetime_result.month
+            day = datetime_result.day
         if julian is not None and julian <= 0:
             year -= 1
             yday = 366 if calendar.isleap(year) else 365
diff -pruN 3.12.0~a7-1/Lib/abc.py 3.12.0~b1-1/Lib/abc.py
--- 3.12.0~a7-1/Lib/abc.py	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Lib/abc.py	2023-05-22 12:07:36.000000000 +0000
@@ -18,7 +18,7 @@ def abstractmethod(funcobj):
 
         class C(metaclass=ABCMeta):
             @abstractmethod
-            def my_abstract_method(self, ...):
+            def my_abstract_method(self, arg1, arg2, argN):
                 ...
     """
     funcobj.__isabstractmethod__ = True
diff -pruN 3.12.0~a7-1/Lib/argparse.py 3.12.0~b1-1/Lib/argparse.py
--- 3.12.0~a7-1/Lib/argparse.py	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Lib/argparse.py	2023-05-22 12:07:36.000000000 +0000
@@ -345,21 +345,22 @@ class HelpFormatter(object):
                 def get_lines(parts, indent, prefix=None):
                     lines = []
                     line = []
+                    indent_length = len(indent)
                     if prefix is not None:
                         line_len = len(prefix) - 1
                     else:
-                        line_len = len(indent) - 1
+                        line_len = indent_length - 1
                     for part in parts:
                         if line_len + 1 + len(part) > text_width and line:
                             lines.append(indent + ' '.join(line))
                             line = []
-                            line_len = len(indent) - 1
+                            line_len = indent_length - 1
                         line.append(part)
                         line_len += len(part) + 1
                     if line:
                         lines.append(indent + ' '.join(line))
                     if prefix is not None:
-                        lines[0] = lines[0][len(indent):]
+                        lines[0] = lines[0][indent_length:]
                     return lines
 
                 # if prog is short, follow it with optionals or positionals
@@ -882,16 +883,19 @@ class Action(_AttributeHolder):
         raise NotImplementedError(_('.__call__() not defined'))
 
 
+# FIXME: remove together with `BooleanOptionalAction` deprecated arguments.
+_deprecated_default = object()
+
 class BooleanOptionalAction(Action):
     def __init__(self,
                  option_strings,
                  dest,
                  default=None,
-                 type=None,
-                 choices=None,
+                 type=_deprecated_default,
+                 choices=_deprecated_default,
                  required=False,
                  help=None,
-                 metavar=None):
+                 metavar=_deprecated_default):
 
         _option_strings = []
         for option_string in option_strings:
@@ -901,6 +905,24 @@ class BooleanOptionalAction(Action):
                 option_string = '--no-' + option_string[2:]
                 _option_strings.append(option_string)
 
+        # We need `_deprecated` special value to ban explicit arguments that
+        # match default value. Like:
+        #   parser.add_argument('-f', action=BooleanOptionalAction, type=int)
+        for field_name in ('type', 'choices', 'metavar'):
+            if locals()[field_name] is not _deprecated_default:
+                warnings._deprecated(
+                    field_name,
+                    "{name!r} is deprecated as of Python 3.12 and will be "
+                    "removed in Python {remove}.",
+                    remove=(3, 14))
+
+        if type is _deprecated_default:
+            type = None
+        if choices is _deprecated_default:
+            choices = None
+        if metavar is _deprecated_default:
+            metavar = None
+
         super().__init__(
             option_strings=_option_strings,
             dest=dest,
@@ -2605,9 +2627,11 @@ class ArgumentParser(_AttributeHolder, _
 
     def _print_message(self, message, file=None):
         if message:
-            if file is None:
-                file = _sys.stderr
-            file.write(message)
+            file = file or _sys.stderr
+            try:
+                file.write(message)
+            except (AttributeError, OSError):
+                pass
 
     # ===============
     # Exiting methods
diff -pruN 3.12.0~a7-1/Lib/ast.py 3.12.0~b1-1/Lib/ast.py
--- 3.12.0~a7-1/Lib/ast.py	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Lib/ast.py	2023-05-22 12:07:36.000000000 +0000
@@ -25,6 +25,7 @@
     :license: Python License.
 """
 import sys
+import re
 from _ast import *
 from contextlib import contextmanager, nullcontext
 from enum import IntEnum, auto, _simple_enum
@@ -293,9 +294,7 @@ def get_docstring(node, clean=True):
     if not(node.body and isinstance(node.body[0], Expr)):
         return None
     node = node.body[0].value
-    if isinstance(node, Str):
-        text = node.s
-    elif isinstance(node, Constant) and isinstance(node.value, str):
+    if isinstance(node, Constant) and isinstance(node.value, str):
         text = node.value
     else:
         return None
@@ -305,28 +304,17 @@ def get_docstring(node, clean=True):
     return text
 
 
-def _splitlines_no_ff(source):
+_line_pattern = re.compile(r"(.*?(?:\r\n|\n|\r|$))")
+def _splitlines_no_ff(source, maxlines=None):
     """Split a string into lines ignoring form feed and other chars.
 
     This mimics how the Python parser splits source code.
     """
-    idx = 0
     lines = []
-    next_line = ''
-    while idx < len(source):
-        c = source[idx]
-        next_line += c
-        idx += 1
-        # Keep \r\n together
-        if c == '\r' and idx < len(source) and source[idx] == '\n':
-            next_line += '\n'
-            idx += 1
-        if c in '\r\n':
-            lines.append(next_line)
-            next_line = ''
-
-    if next_line:
-        lines.append(next_line)
+    for lineno, match in enumerate(_line_pattern.finditer(source), 1):
+        if maxlines is not None and lineno > maxlines:
+            break
+        lines.append(match[0])
     return lines
 
 
@@ -360,7 +348,7 @@ def get_source_segment(source, node, *,
     except AttributeError:
         return None
 
-    lines = _splitlines_no_ff(source)
+    lines = _splitlines_no_ff(source, maxlines=end_lineno+1)
     if end_lineno == lineno:
         return lines[lineno].encode()[col_offset:end_col_offset].decode()
 
@@ -509,20 +497,52 @@ class NodeTransformer(NodeVisitor):
         return node
 
 
+_DEPRECATED_VALUE_ALIAS_MESSAGE = (
+    "{name} is deprecated and will be removed in Python {remove}; use value instead"
+)
+_DEPRECATED_CLASS_MESSAGE = (
+    "{name} is deprecated and will be removed in Python {remove}; "
+    "use ast.Constant instead"
+)
+
+
 # If the ast module is loaded more than once, only add deprecated methods once
 if not hasattr(Constant, 'n'):
     # The following code is for backward compatibility.
     # It will be removed in future.
 
-    def _getter(self):
+    def _n_getter(self):
         """Deprecated. Use value instead."""
+        import warnings
+        warnings._deprecated(
+            "Attribute n", message=_DEPRECATED_VALUE_ALIAS_MESSAGE, remove=(3, 14)
+        )
         return self.value
 
-    def _setter(self, value):
+    def _n_setter(self, value):
+        import warnings
+        warnings._deprecated(
+            "Attribute n", message=_DEPRECATED_VALUE_ALIAS_MESSAGE, remove=(3, 14)
+        )
         self.value = value
 
-    Constant.n = property(_getter, _setter)
-    Constant.s = property(_getter, _setter)
+    def _s_getter(self):
+        """Deprecated. Use value instead."""
+        import warnings
+        warnings._deprecated(
+            "Attribute s", message=_DEPRECATED_VALUE_ALIAS_MESSAGE, remove=(3, 14)
+        )
+        return self.value
+
+    def _s_setter(self, value):
+        import warnings
+        warnings._deprecated(
+            "Attribute s", message=_DEPRECATED_VALUE_ALIAS_MESSAGE, remove=(3, 14)
+        )
+        self.value = value
+
+    Constant.n = property(_n_getter, _n_setter)
+    Constant.s = property(_s_getter, _s_setter)
 
 class _ABC(type):
 
@@ -530,6 +550,13 @@ class _ABC(type):
         cls.__doc__ = """Deprecated AST node class. Use ast.Constant instead"""
 
     def __instancecheck__(cls, inst):
+        if cls in _const_types:
+            import warnings
+            warnings._deprecated(
+                f"ast.{cls.__qualname__}",
+                message=_DEPRECATED_CLASS_MESSAGE,
+                remove=(3, 14)
+            )
         if not isinstance(inst, Constant):
             return False
         if cls in _const_types:
@@ -553,6 +580,10 @@ def _new(cls, *args, **kwargs):
         if pos < len(args):
             raise TypeError(f"{cls.__name__} got multiple values for argument {key!r}")
     if cls in _const_types:
+        import warnings
+        warnings._deprecated(
+            f"ast.{cls.__qualname__}", message=_DEPRECATED_CLASS_MESSAGE, remove=(3, 14)
+        )
         return Constant(*args, **kwargs)
     return Constant.__new__(cls, *args, **kwargs)
 
@@ -575,10 +606,19 @@ class Ellipsis(Constant, metaclass=_ABC)
     _fields = ()
 
     def __new__(cls, *args, **kwargs):
-        if cls is Ellipsis:
+        if cls is _ast_Ellipsis:
+            import warnings
+            warnings._deprecated(
+                "ast.Ellipsis", message=_DEPRECATED_CLASS_MESSAGE, remove=(3, 14)
+            )
             return Constant(..., *args, **kwargs)
         return Constant.__new__(cls, *args, **kwargs)
 
+# Keep another reference to Ellipsis in the global namespace
+# so it can be referenced in Ellipsis.__new__
+# (The original "Ellipsis" name is removed from the global namespace later on)
+_ast_Ellipsis = Ellipsis
+
 _const_types = {
     Num: (int, float, complex),
     Str: (str,),
@@ -1011,6 +1051,7 @@ class _Unparser(NodeVisitor):
             self.fill("@")
             self.traverse(deco)
         self.fill("class " + node.name)
+        self._type_params_helper(node.type_params)
         with self.delimit_if("(", ")", condition = node.bases or node.keywords):
             comma = False
             for e in node.bases:
@@ -1042,6 +1083,7 @@ class _Unparser(NodeVisitor):
             self.traverse(deco)
         def_str = fill_suffix + " " + node.name
         self.fill(def_str)
+        self._type_params_helper(node.type_params)
         with self.delimit("(", ")"):
             self.traverse(node.args)
         if node.returns:
@@ -1050,6 +1092,30 @@ class _Unparser(NodeVisitor):
         with self.block(extra=self.get_type_comment(node)):
             self._write_docstring_and_traverse_body(node)
 
+    def _type_params_helper(self, type_params):
+        if type_params is not None and len(type_params) > 0:
+            with self.delimit("[", "]"):
+                self.interleave(lambda: self.write(", "), self.traverse, type_params)
+
+    def visit_TypeVar(self, node):
+        self.write(node.name)
+        if node.bound:
+            self.write(": ")
+            self.traverse(node.bound)
+
+    def visit_TypeVarTuple(self, node):
+        self.write("*" + node.name)
+
+    def visit_ParamSpec(self, node):
+        self.write("**" + node.name)
+
+    def visit_TypeAlias(self, node):
+        self.fill("type ")
+        self.traverse(node.name)
+        self._type_params_helper(node.type_params)
+        self.write(" = ")
+        self.traverse(node.value)
+
     def visit_For(self, node):
         self._for_helper("for ", node)
 
@@ -1709,6 +1775,22 @@ def unparse(ast_obj):
     return unparser.visit(ast_obj)
 
 
+_deprecated_globals = {
+    name: globals().pop(name)
+    for name in ('Num', 'Str', 'Bytes', 'NameConstant', 'Ellipsis')
+}
+
+def __getattr__(name):
+    if name in _deprecated_globals:
+        globals()[name] = value = _deprecated_globals[name]
+        import warnings
+        warnings._deprecated(
+            f"ast.{name}", message=_DEPRECATED_CLASS_MESSAGE, remove=(3, 14)
+        )
+        return value
+    raise AttributeError(f"module 'ast' has no attribute '{name}'")
+
+
 def main():
     import argparse
 
diff -pruN 3.12.0~a7-1/Lib/asyncio/base_tasks.py 3.12.0~b1-1/Lib/asyncio/base_tasks.py
--- 3.12.0~a7-1/Lib/asyncio/base_tasks.py	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Lib/asyncio/base_tasks.py	2023-05-22 12:07:36.000000000 +0000
@@ -15,11 +15,13 @@ def _task_repr_info(task):
 
     info.insert(1, 'name=%r' % task.get_name())
 
-    coro = coroutines._format_coroutine(task._coro)
-    info.insert(2, f'coro=<{coro}>')
-
     if task._fut_waiter is not None:
-        info.insert(3, f'wait_for={task._fut_waiter!r}')
+        info.insert(2, f'wait_for={task._fut_waiter!r}')
+
+    if task._coro:
+        coro = coroutines._format_coroutine(task._coro)
+        info.insert(2, f'coro=<{coro}>')
+
     return info
 
 
diff -pruN 3.12.0~a7-1/Lib/asyncio/selector_events.py 3.12.0~b1-1/Lib/asyncio/selector_events.py
--- 3.12.0~a7-1/Lib/asyncio/selector_events.py	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Lib/asyncio/selector_events.py	2023-05-22 12:07:36.000000000 +0000
@@ -794,6 +794,8 @@ class _SelectorTransport(transports._Flo
         self._buffer = collections.deque()
         self._conn_lost = 0  # Set when call to connection_lost scheduled.
         self._closing = False  # Set when close() called.
+        self._paused = False  # Set when pause_reading() called
+
         if self._server is not None:
             self._server._attach()
         loop._transports[self._sock_fd] = self
@@ -839,6 +841,25 @@ class _SelectorTransport(transports._Flo
     def is_closing(self):
         return self._closing
 
+    def is_reading(self):
+        return not self.is_closing() and not self._paused
+
+    def pause_reading(self):
+        if not self.is_reading():
+            return
+        self._paused = True
+        self._loop._remove_reader(self._sock_fd)
+        if self._loop.get_debug():
+            logger.debug("%r pauses reading", self)
+
+    def resume_reading(self):
+        if self._closing or not self._paused:
+            return
+        self._paused = False
+        self._add_reader(self._sock_fd, self._read_ready)
+        if self._loop.get_debug():
+            logger.debug("%r resumes reading", self)
+
     def close(self):
         if self._closing:
             return
@@ -898,9 +919,8 @@ class _SelectorTransport(transports._Flo
         return sum(map(len, self._buffer))
 
     def _add_reader(self, fd, callback, *args):
-        if self._closing:
+        if not self.is_reading():
             return
-
         self._loop._add_reader(fd, callback, *args)
 
 
@@ -915,7 +935,6 @@ class _SelectorSocketTransport(_Selector
         self._read_ready_cb = None
         super().__init__(loop, sock, protocol, extra, server)
         self._eof = False
-        self._paused = False
         self._empty_waiter = None
         if _HAS_SENDMSG:
             self._write_ready = self._write_sendmsg
@@ -943,25 +962,6 @@ class _SelectorSocketTransport(_Selector
 
         super().set_protocol(protocol)
 
-    def is_reading(self):
-        return not self._paused and not self._closing
-
-    def pause_reading(self):
-        if self._closing or self._paused:
-            return
-        self._paused = True
-        self._loop._remove_reader(self._sock_fd)
-        if self._loop.get_debug():
-            logger.debug("%r pauses reading", self)
-
-    def resume_reading(self):
-        if self._closing or not self._paused:
-            return
-        self._paused = False
-        self._add_reader(self._sock_fd, self._read_ready)
-        if self._loop.get_debug():
-            logger.debug("%r resumes reading", self)
-
     def _read_ready(self):
         self._read_ready_cb()
 
@@ -1176,6 +1176,9 @@ class _SelectorSocketTransport(_Selector
             return
         self._buffer.extend([memoryview(data) for data in list_of_data])
         self._write_ready()
+        # If the entire buffer couldn't be written, register a write handler
+        if self._buffer:
+            self._loop._add_writer(self._sock_fd, self._write_ready)
 
     def can_write_eof(self):
         return True
diff -pruN 3.12.0~a7-1/Lib/asyncio/sslproto.py 3.12.0~b1-1/Lib/asyncio/sslproto.py
--- 3.12.0~a7-1/Lib/asyncio/sslproto.py	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Lib/asyncio/sslproto.py	2023-05-22 12:07:36.000000000 +0000
@@ -244,7 +244,8 @@ class _SSLProtocolTransport(transports._
         called with None as its argument.
         """
         self._closed = True
-        self._ssl_protocol._abort()
+        if self._ssl_protocol is not None:
+            self._ssl_protocol._abort()
 
     def _force_close(self, exc):
         self._closed = True
diff -pruN 3.12.0~a7-1/Lib/asyncio/subprocess.py 3.12.0~b1-1/Lib/asyncio/subprocess.py
--- 3.12.0~a7-1/Lib/asyncio/subprocess.py	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Lib/asyncio/subprocess.py	2023-05-22 12:07:36.000000000 +0000
@@ -81,6 +81,9 @@ class SubprocessStreamProtocol(streams.F
                 self._stdin_closed.set_result(None)
             else:
                 self._stdin_closed.set_exception(exc)
+                # Since calling `wait_closed()` is not mandatory,
+                # we shouldn't log the traceback if this is not awaited.
+                self._stdin_closed._log_traceback = False
             return
         if fd == 1:
             reader = self.stdout
@@ -144,10 +147,11 @@ class Process:
 
     async def _feed_stdin(self, input):
         debug = self._loop.get_debug()
-        self.stdin.write(input)
-        if debug:
-            logger.debug(
-                '%r communicate: feed stdin (%s bytes)', self, len(input))
+        if input is not None:
+            self.stdin.write(input)
+            if debug:
+                logger.debug(
+                    '%r communicate: feed stdin (%s bytes)', self, len(input))
         try:
             await self.stdin.drain()
         except (BrokenPipeError, ConnectionResetError) as exc:
@@ -180,7 +184,7 @@ class Process:
         return output
 
     async def communicate(self, input=None):
-        if input is not None:
+        if self.stdin is not None:
             stdin = self._feed_stdin(input)
         else:
             stdin = self._noop()
diff -pruN 3.12.0~a7-1/Lib/asyncio/taskgroups.py 3.12.0~b1-1/Lib/asyncio/taskgroups.py
--- 3.12.0~a7-1/Lib/asyncio/taskgroups.py	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Lib/asyncio/taskgroups.py	2023-05-22 12:07:36.000000000 +0000
@@ -164,8 +164,14 @@ class TaskGroup:
         else:
             task = self._loop.create_task(coro, context=context)
         tasks._set_task_name(task, name)
-        task.add_done_callback(self._on_task_done)
-        self._tasks.add(task)
+        # optimization: Immediately call the done callback if the task is
+        # already done (e.g. if the coro was able to complete eagerly),
+        # and skip scheduling a done callback
+        if task.done():
+            self._on_task_done(task)
+        else:
+            self._tasks.add(task)
+            task.add_done_callback(self._on_task_done)
         return task
 
     # Since Python 3.8 Tasks propagate all exceptions correctly,
diff -pruN 3.12.0~a7-1/Lib/asyncio/tasks.py 3.12.0~b1-1/Lib/asyncio/tasks.py
--- 3.12.0~a7-1/Lib/asyncio/tasks.py	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Lib/asyncio/tasks.py	2023-05-22 12:07:36.000000000 +0000
@@ -6,6 +6,7 @@ __all__ = (
     'wait', 'wait_for', 'as_completed', 'sleep',
     'gather', 'shield', 'ensure_future', 'run_coroutine_threadsafe',
     'current_task', 'all_tasks',
+    'create_eager_task_factory', 'eager_task_factory',
     '_register_task', '_unregister_task', '_enter_task', '_leave_task',
 )
 
@@ -43,22 +44,26 @@ def all_tasks(loop=None):
     """Return a set of all tasks for the loop."""
     if loop is None:
         loop = events.get_running_loop()
-    # Looping over a WeakSet (_all_tasks) isn't safe as it can be updated from another
-    # thread while we do so. Therefore we cast it to list prior to filtering. The list
-    # cast itself requires iteration, so we repeat it several times ignoring
-    # RuntimeErrors (which are not very likely to occur). See issues 34970 and 36607 for
-    # details.
+    # capturing the set of eager tasks first, so if an eager task "graduates"
+    # to a regular task in another thread, we don't risk missing it.
+    eager_tasks = list(_eager_tasks)
+    # Looping over the WeakSet isn't safe as it can be updated from another
+    # thread, therefore we cast it to list prior to filtering. The list cast
+    # itself requires iteration, so we repeat it several times ignoring
+    # RuntimeErrors (which are not very likely to occur).
+    # See issues 34970 and 36607 for details.
+    scheduled_tasks = None
     i = 0
     while True:
         try:
-            tasks = list(_all_tasks)
+            scheduled_tasks = list(_scheduled_tasks)
         except RuntimeError:
             i += 1
             if i >= 1000:
                 raise
         else:
             break
-    return {t for t in tasks
+    return {t for t in itertools.chain(scheduled_tasks, eager_tasks)
             if futures._get_loop(t) is loop and not t.done()}
 
 
@@ -93,7 +98,8 @@ class Task(futures._PyFuture):  # Inheri
     # status is still pending
     _log_destroy_pending = True
 
-    def __init__(self, coro, *, loop=None, name=None, context=None):
+    def __init__(self, coro, *, loop=None, name=None, context=None,
+                 eager_start=False):
         super().__init__(loop=loop)
         if self._source_traceback:
             del self._source_traceback[-1]
@@ -117,8 +123,11 @@ class Task(futures._PyFuture):  # Inheri
         else:
             self._context = context
 
-        self._loop.call_soon(self.__step, context=self._context)
-        _register_task(self)
+        if eager_start and self._loop.is_running():
+            self.__eager_start()
+        else:
+            self._loop.call_soon(self.__step, context=self._context)
+            _register_task(self)
 
     def __del__(self):
         if self._state == futures._PENDING and self._log_destroy_pending:
@@ -250,6 +259,25 @@ class Task(futures._PyFuture):  # Inheri
             self._num_cancels_requested -= 1
         return self._num_cancels_requested
 
+    def __eager_start(self):
+        prev_task = _swap_current_task(self._loop, self)
+        try:
+            _register_eager_task(self)
+            try:
+                self._context.run(self.__step_run_and_handle_result, None)
+            finally:
+                _unregister_eager_task(self)
+        finally:
+            try:
+                curtask = _swap_current_task(self._loop, prev_task)
+                assert curtask is self
+            finally:
+                if self.done():
+                    self._coro = None
+                    self = None  # Needed to break cycles when an exception occurs.
+                else:
+                    _register_task(self)
+
     def __step(self, exc=None):
         if self.done():
             raise exceptions.InvalidStateError(
@@ -258,11 +286,17 @@ class Task(futures._PyFuture):  # Inheri
             if not isinstance(exc, exceptions.CancelledError):
                 exc = self._make_cancelled_error()
             self._must_cancel = False
-        coro = self._coro
         self._fut_waiter = None
 
         _enter_task(self._loop, self)
-        # Call either coro.throw(exc) or coro.send(None).
+        try:
+            self.__step_run_and_handle_result(exc)
+        finally:
+            _leave_task(self._loop, self)
+            self = None  # Needed to break cycles when an exception occurs.
+
+    def __step_run_and_handle_result(self, exc):
+        coro = self._coro
         try:
             if exc is None:
                 # We use the `send` method directly, because coroutines
@@ -334,7 +368,6 @@ class Task(futures._PyFuture):  # Inheri
                 self._loop.call_soon(
                     self.__step, new_exc, context=self._context)
         finally:
-            _leave_task(self._loop, self)
             self = None  # Needed to break cycles when an exception occurs.
 
     def __wakeup(self, future):
@@ -780,6 +813,7 @@ def gather(*coros_or_futures, return_exc
     children = []
     nfuts = 0
     nfinished = 0
+    done_futs = []
     loop = None
     outer = None  # bpo-46672
     for arg in coros_or_futures:
@@ -796,7 +830,10 @@ def gather(*coros_or_futures, return_exc
 
             nfuts += 1
             arg_to_fut[arg] = fut
-            fut.add_done_callback(_done_callback)
+            if fut.done():
+                done_futs.append(fut)
+            else:
+                fut.add_done_callback(_done_callback)
 
         else:
             # There's a duplicate Future object in coros_or_futures.
@@ -805,6 +842,13 @@ def gather(*coros_or_futures, return_exc
         children.append(fut)
 
     outer = _GatheringFuture(children, loop=loop)
+    # Run done callbacks after GatheringFuture created so any post-processing
+    # can be performed at this point
+    # optimization: in the special case that *all* futures finished eagerly,
+    # this will effectively complete the gather eagerly, with the last
+    # callback setting the result (or exception) on outer before returning it
+    for fut in done_futs:
+        _done_callback(fut)
     return outer
 
 
@@ -897,8 +941,40 @@ def run_coroutine_threadsafe(coro, loop)
     return future
 
 
-# WeakSet containing all alive tasks.
-_all_tasks = weakref.WeakSet()
+def create_eager_task_factory(custom_task_constructor):
+    """Create a function suitable for use as a task factory on an event-loop.
+
+	    Example usage:
+
+	        loop.set_task_factory(
+	            asyncio.create_eager_task_factory(my_task_constructor))
+
+	    Now, tasks created will be started immediately (rather than being first
+	    scheduled to an event loop). The constructor argument can be any callable
+	    that returns a Task-compatible object and has a signature compatible
+	    with `Task.__init__`; it must have the `eager_start` keyword argument.
+
+	    Most applications will use `Task` for `custom_task_constructor` and in
+        this case there's no need to call `create_eager_task_factory()`
+        directly. Instead the  global `eager_task_factory` instance can be
+        used. E.g. `loop.set_task_factory(asyncio.eager_task_factory)`.
+	    """
+
+    def factory(loop, coro, *, name=None, context=None):
+        return custom_task_constructor(
+            coro, loop=loop, name=name, context=context, eager_start=True)
+
+    return factory
+
+
+eager_task_factory = create_eager_task_factory(Task)
+
+
+# Collectively these two sets hold references to the complete set of active
+# tasks. Eagerly executed tasks use a faster regular set as an optimization
+# but may graduate to a WeakSet if the task blocks on IO.
+_scheduled_tasks = weakref.WeakSet()
+_eager_tasks = set()
 
 # Dictionary containing tasks that are currently active in
 # all running event loops.  {EventLoop: Task}
@@ -906,8 +982,13 @@ _current_tasks = {}
 
 
 def _register_task(task):
-    """Register a new task in asyncio as executed by loop."""
-    _all_tasks.add(task)
+    """Register an asyncio Task scheduled to run on an event loop."""
+    _scheduled_tasks.add(task)
+
+
+def _register_eager_task(task):
+    """Register an asyncio Task about to be eagerly executed."""
+    _eager_tasks.add(task)
 
 
 def _enter_task(loop, task):
@@ -926,28 +1007,49 @@ def _leave_task(loop, task):
     del _current_tasks[loop]
 
 
+def _swap_current_task(loop, task):
+    prev_task = _current_tasks.get(loop)
+    if task is None:
+        del _current_tasks[loop]
+    else:
+        _current_tasks[loop] = task
+    return prev_task
+
+
 def _unregister_task(task):
-    """Unregister a task."""
-    _all_tasks.discard(task)
+    """Unregister a completed, scheduled Task."""
+    _scheduled_tasks.discard(task)
+
+
+def _unregister_eager_task(task):
+    """Unregister a task which finished its first eager step."""
+    _eager_tasks.discard(task)
 
 
 _py_current_task = current_task
 _py_register_task = _register_task
+_py_register_eager_task = _register_eager_task
 _py_unregister_task = _unregister_task
+_py_unregister_eager_task = _unregister_eager_task
 _py_enter_task = _enter_task
 _py_leave_task = _leave_task
+_py_swap_current_task = _swap_current_task
 
 
 try:
-    from _asyncio import (_register_task, _unregister_task,
-                          _enter_task, _leave_task,
-                          _all_tasks, _current_tasks,
+    from _asyncio import (_register_task, _register_eager_task,
+                          _unregister_task, _unregister_eager_task,
+                          _enter_task, _leave_task, _swap_current_task,
+                          _scheduled_tasks, _eager_tasks, _current_tasks,
                           current_task)
 except ImportError:
     pass
 else:
     _c_current_task = current_task
     _c_register_task = _register_task
+    _c_register_eager_task = _register_eager_task
     _c_unregister_task = _unregister_task
+    _c_unregister_eager_task = _unregister_eager_task
     _c_enter_task = _enter_task
     _c_leave_task = _leave_task
+    _c_swap_current_task = _swap_current_task
diff -pruN 3.12.0~a7-1/Lib/asyncio/unix_events.py 3.12.0~b1-1/Lib/asyncio/unix_events.py
--- 3.12.0~a7-1/Lib/asyncio/unix_events.py	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Lib/asyncio/unix_events.py	2023-05-22 12:07:36.000000000 +0000
@@ -485,13 +485,21 @@ class _UnixReadPipeTransport(transports.
 
         self._loop.call_soon(self._protocol.connection_made, self)
         # only start reading when connection_made() has been called
-        self._loop.call_soon(self._loop._add_reader,
+        self._loop.call_soon(self._add_reader,
                              self._fileno, self._read_ready)
         if waiter is not None:
             # only wake up the waiter when connection_made() has been called
             self._loop.call_soon(futures._set_result_unless_cancelled,
                                  waiter, None)
 
+    def _add_reader(self, fd, callback):
+        if not self.is_reading():
+            return
+        self._loop._add_reader(fd, callback)
+
+    def is_reading(self):
+        return not self._paused and not self._closing
+
     def __repr__(self):
         info = [self.__class__.__name__]
         if self._pipe is None:
@@ -532,7 +540,7 @@ class _UnixReadPipeTransport(transports.
                 self._loop.call_soon(self._call_connection_lost, None)
 
     def pause_reading(self):
-        if self._closing or self._paused:
+        if not self.is_reading():
             return
         self._paused = True
         self._loop._remove_reader(self._fileno)
diff -pruN 3.12.0~a7-1/Lib/bdb.py 3.12.0~b1-1/Lib/bdb.py
--- 3.12.0~a7-1/Lib/bdb.py	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Lib/bdb.py	2023-05-22 12:07:36.000000000 +0000
@@ -574,6 +574,8 @@ class Bdb:
             line = linecache.getline(filename, lineno, frame.f_globals)
             if line:
                 s += lprefix + line.strip()
+        else:
+            s += f'{lprefix}Warning: lineno is None'
         return s
 
     # The following methods can be called by clients to use
diff -pruN 3.12.0~a7-1/Lib/cProfile.py 3.12.0~b1-1/Lib/cProfile.py
--- 3.12.0~a7-1/Lib/cProfile.py	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Lib/cProfile.py	2023-05-22 12:07:36.000000000 +0000
@@ -8,6 +8,7 @@ __all__ = ["run", "runctx", "Profile"]
 
 import _lsprof
 import importlib.machinery
+import io
 import profile as _pyprofile
 
 # ____________________________________________________________
@@ -168,7 +169,7 @@ def main():
         else:
             progname = args[0]
             sys.path.insert(0, os.path.dirname(progname))
-            with open(progname, 'rb') as fp:
+            with io.open_code(progname) as fp:
                 code = compile(fp.read(), progname, 'exec')
             spec = importlib.machinery.ModuleSpec(name='__main__', loader=None,
                                                   origin=progname)
diff -pruN 3.12.0~a7-1/Lib/calendar.py 3.12.0~b1-1/Lib/calendar.py
--- 3.12.0~a7-1/Lib/calendar.py	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Lib/calendar.py	2023-05-22 12:07:36.000000000 +0000
@@ -7,8 +7,10 @@ set the first day of the week (0=Monday,
 
 import sys
 import datetime
+from enum import IntEnum, global_enum
 import locale as _locale
 from itertools import repeat
+import warnings
 
 __all__ = ["IllegalMonthError", "IllegalWeekdayError", "setfirstweekday",
            "firstweekday", "isleap", "leapdays", "weekday", "monthrange",
@@ -16,6 +18,9 @@ __all__ = ["IllegalMonthError", "Illegal
            "timegm", "month_name", "month_abbr", "day_name", "day_abbr",
            "Calendar", "TextCalendar", "HTMLCalendar", "LocaleTextCalendar",
            "LocaleHTMLCalendar", "weekheader",
+           "Day", "Month", "JANUARY", "FEBRUARY", "MARCH",
+           "APRIL", "MAY", "JUNE", "JULY",
+           "AUGUST", "SEPTEMBER", "OCTOBER", "NOVEMBER", "DECEMBER",
            "MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY",
            "SATURDAY", "SUNDAY"]
 
@@ -37,9 +42,46 @@ class IllegalWeekdayError(ValueError):
         return "bad weekday number %r; must be 0 (Monday) to 6 (Sunday)" % self.weekday
 
 
-# Constants for months referenced later
-January = 1
-February = 2
+def __getattr__(name):
+    if name in ('January', 'February'):
+        warnings.warn(f"The '{name}' attribute is deprecated, use '{name.upper()}' instead",
+                      DeprecationWarning, stacklevel=2)
+        if name == 'January':
+            return 1
+        else:
+            return 2
+
+    raise AttributeError(f"module '{__name__}' has no attribute '{name}'")
+
+
+# Constants for months
+@global_enum
+class Month(IntEnum):
+    JANUARY = 1
+    FEBRUARY = 2
+    MARCH = 3
+    APRIL = 4
+    MAY = 5
+    JUNE = 6
+    JULY = 7
+    AUGUST = 8
+    SEPTEMBER = 9
+    OCTOBER = 10
+    NOVEMBER = 11
+    DECEMBER = 12
+
+
+# Constants for days
+@global_enum
+class Day(IntEnum):
+    MONDAY = 0
+    TUESDAY = 1
+    WEDNESDAY = 2
+    THURSDAY = 3
+    FRIDAY = 4
+    SATURDAY = 5
+    SUNDAY = 6
+
 
 # Number of days per month (except for February in leap years)
 mdays = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
@@ -95,9 +137,6 @@ day_abbr = _localized_day('%a')
 month_name = _localized_month('%B')
 month_abbr = _localized_month('%b')
 
-# Constants for weekdays
-(MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY) = range(7)
-
 
 def isleap(year):
     """Return True for leap years, False for non-leap years."""
@@ -116,7 +155,7 @@ def weekday(year, month, day):
     """Return weekday (0-6 ~ Mon-Sun) for year, month (1-12), day (1-31)."""
     if not datetime.MINYEAR <= year <= datetime.MAXYEAR:
         year = 2000 + year % 400
-    return datetime.date(year, month, day).weekday()
+    return Day(datetime.date(year, month, day).weekday())
 
 
 def monthrange(year, month):
@@ -125,12 +164,12 @@ def monthrange(year, month):
     if not 1 <= month <= 12:
         raise IllegalMonthError(month)
     day1 = weekday(year, month, 1)
-    ndays = mdays[month] + (month == February and isleap(year))
+    ndays = mdays[month] + (month == FEBRUARY and isleap(year))
     return day1, ndays
 
 
 def _monthlen(year, month):
-    return mdays[month] + (month == February and isleap(year))
+    return mdays[month] + (month == FEBRUARY and isleap(year))
 
 
 def _prevmonth(year, month):
@@ -260,10 +299,7 @@ class Calendar(object):
         Each month contains between 4 and 6 weeks and each week contains 1-7
         days. Days are datetime.date objects.
         """
-        months = [
-            self.monthdatescalendar(year, i)
-            for i in range(January, January+12)
-        ]
+        months = [self.monthdatescalendar(year, m) for m in Month]
         return [months[i:i+width] for i in range(0, len(months), width) ]
 
     def yeardays2calendar(self, year, width=3):
@@ -273,10 +309,7 @@ class Calendar(object):
         (day number, weekday number) tuples. Day numbers outside this month are
         zero.
         """
-        months = [
-            self.monthdays2calendar(year, i)
-            for i in range(January, January+12)
-        ]
+        months = [self.monthdays2calendar(year, m) for m in Month]
         return [months[i:i+width] for i in range(0, len(months), width) ]
 
     def yeardayscalendar(self, year, width=3):
@@ -285,10 +318,7 @@ class Calendar(object):
         yeardatescalendar()). Entries in the week lists are day numbers.
         Day numbers outside this month are zero.
         """
-        months = [
-            self.monthdayscalendar(year, i)
-            for i in range(January, January+12)
-        ]
+        months = [self.monthdayscalendar(year, m) for m in Month]
         return [months[i:i+width] for i in range(0, len(months), width) ]
 
 
@@ -509,7 +539,7 @@ class HTMLCalendar(Calendar):
         a('\n')
         a('<tr><th colspan="%d" class="%s">%s</th></tr>' % (
             width, self.cssclass_year_head, theyear))
-        for i in range(January, January+12, width):
+        for i in range(JANUARY, JANUARY+12, width):
             # months in this row
             months = range(i, min(i+width, 13))
             a('<tr>')
diff -pruN 3.12.0~a7-1/Lib/collections/__init__.py 3.12.0~b1-1/Lib/collections/__init__.py
--- 3.12.0~a7-1/Lib/collections/__init__.py	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Lib/collections/__init__.py	2023-05-22 12:07:36.000000000 +0000
@@ -46,6 +46,11 @@ else:
     _collections_abc.MutableSequence.register(deque)
 
 try:
+    from _collections import _deque_iterator
+except ImportError:
+    pass
+
+try:
     from _collections import defaultdict
 except ImportError:
     pass
diff -pruN 3.12.0~a7-1/Lib/contextlib.py 3.12.0~b1-1/Lib/contextlib.py
--- 3.12.0~a7-1/Lib/contextlib.py	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Lib/contextlib.py	2023-05-22 12:07:36.000000000 +0000
@@ -441,7 +441,16 @@ class suppress(AbstractContextManager):
         # exactly reproduce the limitations of the CPython interpreter.
         #
         # See http://bugs.python.org/issue12029 for more details
-        return exctype is not None and issubclass(exctype, self._exceptions)
+        if exctype is None:
+            return
+        if issubclass(exctype, self._exceptions):
+            return True
+        if issubclass(exctype, ExceptionGroup):
+            match, rest = excinst.split(self._exceptions)
+            if rest is None:
+                return True
+            raise rest
+        return False
 
 
 class _BaseExitStack:
diff -pruN 3.12.0~a7-1/Lib/csv.py 3.12.0~b1-1/Lib/csv.py
--- 3.12.0~a7-1/Lib/csv.py	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Lib/csv.py	2023-05-22 12:07:36.000000000 +0000
@@ -9,12 +9,14 @@ from _csv import Error, __version__, wri
                  unregister_dialect, get_dialect, list_dialects, \
                  field_size_limit, \
                  QUOTE_MINIMAL, QUOTE_ALL, QUOTE_NONNUMERIC, QUOTE_NONE, \
+                 QUOTE_STRINGS, QUOTE_NOTNULL, \
                  __doc__
 from _csv import Dialect as _Dialect
 
 from io import StringIO
 
 __all__ = ["QUOTE_MINIMAL", "QUOTE_ALL", "QUOTE_NONNUMERIC", "QUOTE_NONE",
+           "QUOTE_STRINGS", "QUOTE_NOTNULL",
            "Error", "Dialect", "__doc__", "excel", "excel_tab",
            "field_size_limit", "reader", "writer",
            "register_dialect", "get_dialect", "list_dialects", "Sniffer",
diff -pruN 3.12.0~a7-1/Lib/curses/textpad.py 3.12.0~b1-1/Lib/curses/textpad.py
--- 3.12.0~a7-1/Lib/curses/textpad.py	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Lib/curses/textpad.py	2023-05-22 12:07:36.000000000 +0000
@@ -102,7 +102,10 @@ class Textbox:
                 self._insert_printable_char(ch)
         elif ch == curses.ascii.SOH:                           # ^a
             self.win.move(y, 0)
-        elif ch in (curses.ascii.STX,curses.KEY_LEFT, curses.ascii.BS,curses.KEY_BACKSPACE):
+        elif ch in (curses.ascii.STX,curses.KEY_LEFT,
+                    curses.ascii.BS,
+                    curses.KEY_BACKSPACE,
+                    curses.ascii.DEL):
             if x > 0:
                 self.win.move(y, x-1)
             elif y == 0:
@@ -111,7 +114,7 @@ class Textbox:
                 self.win.move(y-1, self._end_of_line(y-1))
             else:
                 self.win.move(y-1, self.maxx)
-            if ch in (curses.ascii.BS, curses.KEY_BACKSPACE):
+            if ch in (curses.ascii.BS, curses.KEY_BACKSPACE, curses.ascii.DEL):
                 self.win.delch()
         elif ch == curses.ascii.EOT:                           # ^d
             self.win.delch()
diff -pruN 3.12.0~a7-1/Lib/dataclasses.py 3.12.0~b1-1/Lib/dataclasses.py
--- 3.12.0~a7-1/Lib/dataclasses.py	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Lib/dataclasses.py	2023-05-22 12:07:36.000000000 +0000
@@ -222,6 +222,29 @@ _POST_INIT_NAME = '__post_init__'
 # https://bugs.python.org/issue33453 for details.
 _MODULE_IDENTIFIER_RE = re.compile(r'^(?:\s*(\w+)\s*\.)?\s*(\w+)')
 
+# Atomic immutable types which don't require any recursive handling and for which deepcopy
+# returns the same object. We can provide a fast-path for these types in asdict and astuple.
+_ATOMIC_TYPES = frozenset({
+    # Common JSON Serializable types
+    types.NoneType,
+    bool,
+    int,
+    float,
+    str,
+    # Other common types
+    complex,
+    bytes,
+    # Other types that are also unaffected by deepcopy
+    types.EllipsisType,
+    types.NotImplementedType,
+    types.CodeType,
+    types.BuiltinFunctionType,
+    types.FunctionType,
+    type,
+    range,
+    property,
+})
+
 # This function's logic is copied from "recursive_repr" function in
 # reprlib module to avoid dependency.
 def _recursive_repr(user_function):
@@ -1105,8 +1128,13 @@ def _process_class(cls, init, repr, eq,
 
     if not getattr(cls, '__doc__'):
         # Create a class doc-string.
-        cls.__doc__ = (cls.__name__ +
-                       str(inspect.signature(cls)).replace(' -> None', ''))
+        try:
+            # In some cases fetching a signature is not possible.
+            # But, we surely should not fail in this case.
+            text_sig = str(inspect.signature(cls)).replace(' -> None', '')
+        except (TypeError, ValueError):
+            text_sig = ''
+        cls.__doc__ = (cls.__name__ + text_sig)
 
     if match_args:
         # I could probably compute this once
@@ -1199,8 +1227,10 @@ def _add_slots(cls, is_frozen, weakref_s
 
     if is_frozen:
         # Need this for pickling frozen classes with slots.
-        cls.__getstate__ = _dataclass_getstate
-        cls.__setstate__ = _dataclass_setstate
+        if '__getstate__' not in cls_dict:
+            cls.__getstate__ = _dataclass_getstate
+        if '__setstate__' not in cls_dict:
+            cls.__setstate__ = _dataclass_setstate
 
     return cls
 
@@ -1291,12 +1321,21 @@ def asdict(obj, *, dict_factory=dict):
 
 
 def _asdict_inner(obj, dict_factory):
-    if _is_dataclass_instance(obj):
-        result = []
-        for f in fields(obj):
-            value = _asdict_inner(getattr(obj, f.name), dict_factory)
-            result.append((f.name, value))
-        return dict_factory(result)
+    if type(obj) in _ATOMIC_TYPES:
+        return obj
+    elif _is_dataclass_instance(obj):
+        # fast path for the common case
+        if dict_factory is dict:
+            return {
+                f.name: _asdict_inner(getattr(obj, f.name), dict)
+                for f in fields(obj)
+            }
+        else:
+            result = []
+            for f in fields(obj):
+                value = _asdict_inner(getattr(obj, f.name), dict_factory)
+                result.append((f.name, value))
+            return dict_factory(result)
     elif isinstance(obj, tuple) and hasattr(obj, '_fields'):
         # obj is a namedtuple.  Recurse into it, but the returned
         # object is another namedtuple of the same type.  This is
@@ -1363,7 +1402,9 @@ def astuple(obj, *, tuple_factory=tuple)
 
 
 def _astuple_inner(obj, tuple_factory):
-    if _is_dataclass_instance(obj):
+    if type(obj) in _ATOMIC_TYPES:
+        return obj
+    elif _is_dataclass_instance(obj):
         result = []
         for f in fields(obj):
             value = _astuple_inner(getattr(obj, f.name), tuple_factory)
diff -pruN 3.12.0~a7-1/Lib/datetime.py 3.12.0~b1-1/Lib/datetime.py
--- 3.12.0~a7-1/Lib/datetime.py	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Lib/datetime.py	2023-05-22 12:07:36.000000000 +0000
@@ -1,2644 +1,9 @@
-"""Concrete date/time and related types.
-
-See http://www.iana.org/time-zones/repository/tz-link.html for
-time zone and DST data sources.
-"""
-
-__all__ = ("date", "datetime", "time", "timedelta", "timezone", "tzinfo",
-           "MINYEAR", "MAXYEAR", "UTC")
-
-
-import time as _time
-import math as _math
-import sys
-from operator import index as _index
-
-def _cmp(x, y):
-    return 0 if x == y else 1 if x > y else -1
-
-MINYEAR = 1
-MAXYEAR = 9999
-_MAXORDINAL = 3652059  # date.max.toordinal()
-
-# Utility functions, adapted from Python's Demo/classes/Dates.py, which
-# also assumes the current Gregorian calendar indefinitely extended in
-# both directions.  Difference:  Dates.py calls January 1 of year 0 day
-# number 1.  The code here calls January 1 of year 1 day number 1.  This is
-# to match the definition of the "proleptic Gregorian" calendar in Dershowitz
-# and Reingold's "Calendrical Calculations", where it's the base calendar
-# for all computations.  See the book for algorithms for converting between
-# proleptic Gregorian ordinals and many other calendar systems.
-
-# -1 is a placeholder for indexing purposes.
-_DAYS_IN_MONTH = [-1, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
-
-_DAYS_BEFORE_MONTH = [-1]  # -1 is a placeholder for indexing purposes.
-dbm = 0
-for dim in _DAYS_IN_MONTH[1:]:
-    _DAYS_BEFORE_MONTH.append(dbm)
-    dbm += dim
-del dbm, dim
-
-def _is_leap(year):
-    "year -> 1 if leap year, else 0."
-    return year % 4 == 0 and (year % 100 != 0 or year % 400 == 0)
-
-def _days_before_year(year):
-    "year -> number of days before January 1st of year."
-    y = year - 1
-    return y*365 + y//4 - y//100 + y//400
-
-def _days_in_month(year, month):
-    "year, month -> number of days in that month in that year."
-    assert 1 <= month <= 12, month
-    if month == 2 and _is_leap(year):
-        return 29
-    return _DAYS_IN_MONTH[month]
-
-def _days_before_month(year, month):
-    "year, month -> number of days in year preceding first day of month."
-    assert 1 <= month <= 12, 'month must be in 1..12'
-    return _DAYS_BEFORE_MONTH[month] + (month > 2 and _is_leap(year))
-
-def _ymd2ord(year, month, day):
-    "year, month, day -> ordinal, considering 01-Jan-0001 as day 1."
-    assert 1 <= month <= 12, 'month must be in 1..12'
-    dim = _days_in_month(year, month)
-    assert 1 <= day <= dim, ('day must be in 1..%d' % dim)
-    return (_days_before_year(year) +
-            _days_before_month(year, month) +
-            day)
-
-_DI400Y = _days_before_year(401)    # number of days in 400 years
-_DI100Y = _days_before_year(101)    #    "    "   "   " 100   "
-_DI4Y   = _days_before_year(5)      #    "    "   "   "   4   "
-
-# A 4-year cycle has an extra leap day over what we'd get from pasting
-# together 4 single years.
-assert _DI4Y == 4 * 365 + 1
-
-# Similarly, a 400-year cycle has an extra leap day over what we'd get from
-# pasting together 4 100-year cycles.
-assert _DI400Y == 4 * _DI100Y + 1
-
-# OTOH, a 100-year cycle has one fewer leap day than we'd get from
-# pasting together 25 4-year cycles.
-assert _DI100Y == 25 * _DI4Y - 1
-
-def _ord2ymd(n):
-    "ordinal -> (year, month, day), considering 01-Jan-0001 as day 1."
-
-    # n is a 1-based index, starting at 1-Jan-1.  The pattern of leap years
-    # repeats exactly every 400 years.  The basic strategy is to find the
-    # closest 400-year boundary at or before n, then work with the offset
-    # from that boundary to n.  Life is much clearer if we subtract 1 from
-    # n first -- then the values of n at 400-year boundaries are exactly
-    # those divisible by _DI400Y:
-    #
-    #     D  M   Y            n              n-1
-    #     -- --- ----        ----------     ----------------
-    #     31 Dec -400        -_DI400Y       -_DI400Y -1
-    #      1 Jan -399         -_DI400Y +1   -_DI400Y      400-year boundary
-    #     ...
-    #     30 Dec  000        -1             -2
-    #     31 Dec  000         0             -1
-    #      1 Jan  001         1              0            400-year boundary
-    #      2 Jan  001         2              1
-    #      3 Jan  001         3              2
-    #     ...
-    #     31 Dec  400         _DI400Y        _DI400Y -1
-    #      1 Jan  401         _DI400Y +1     _DI400Y      400-year boundary
-    n -= 1
-    n400, n = divmod(n, _DI400Y)
-    year = n400 * 400 + 1   # ..., -399, 1, 401, ...
-
-    # Now n is the (non-negative) offset, in days, from January 1 of year, to
-    # the desired date.  Now compute how many 100-year cycles precede n.
-    # Note that it's possible for n100 to equal 4!  In that case 4 full
-    # 100-year cycles precede the desired day, which implies the desired
-    # day is December 31 at the end of a 400-year cycle.
-    n100, n = divmod(n, _DI100Y)
-
-    # Now compute how many 4-year cycles precede it.
-    n4, n = divmod(n, _DI4Y)
-
-    # And now how many single years.  Again n1 can be 4, and again meaning
-    # that the desired day is December 31 at the end of the 4-year cycle.
-    n1, n = divmod(n, 365)
-
-    year += n100 * 100 + n4 * 4 + n1
-    if n1 == 4 or n100 == 4:
-        assert n == 0
-        return year-1, 12, 31
-
-    # Now the year is correct, and n is the offset from January 1.  We find
-    # the month via an estimate that's either exact or one too large.
-    leapyear = n1 == 3 and (n4 != 24 or n100 == 3)
-    assert leapyear == _is_leap(year)
-    month = (n + 50) >> 5
-    preceding = _DAYS_BEFORE_MONTH[month] + (month > 2 and leapyear)
-    if preceding > n:  # estimate is too large
-        month -= 1
-        preceding -= _DAYS_IN_MONTH[month] + (month == 2 and leapyear)
-    n -= preceding
-    assert 0 <= n < _days_in_month(year, month)
-
-    # Now the year and month are correct, and n is the offset from the
-    # start of that month:  we're done!
-    return year, month, n+1
-
-# Month and day names.  For localized versions, see the calendar module.
-_MONTHNAMES = [None, "Jan", "Feb", "Mar", "Apr", "May", "Jun",
-                     "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
-_DAYNAMES = [None, "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]
-
-
-def _build_struct_time(y, m, d, hh, mm, ss, dstflag):
-    wday = (_ymd2ord(y, m, d) + 6) % 7
-    dnum = _days_before_month(y, m) + d
-    return _time.struct_time((y, m, d, hh, mm, ss, wday, dnum, dstflag))
-
-def _format_time(hh, mm, ss, us, timespec='auto'):
-    specs = {
-        'hours': '{:02d}',
-        'minutes': '{:02d}:{:02d}',
-        'seconds': '{:02d}:{:02d}:{:02d}',
-        'milliseconds': '{:02d}:{:02d}:{:02d}.{:03d}',
-        'microseconds': '{:02d}:{:02d}:{:02d}.{:06d}'
-    }
-
-    if timespec == 'auto':
-        # Skip trailing microseconds when us==0.
-        timespec = 'microseconds' if us else 'seconds'
-    elif timespec == 'milliseconds':
-        us //= 1000
-    try:
-        fmt = specs[timespec]
-    except KeyError:
-        raise ValueError('Unknown timespec value')
-    else:
-        return fmt.format(hh, mm, ss, us)
-
-def _format_offset(off, sep=':'):
-    s = ''
-    if off is not None:
-        if off.days < 0:
-            sign = "-"
-            off = -off
-        else:
-            sign = "+"
-        hh, mm = divmod(off, timedelta(hours=1))
-        mm, ss = divmod(mm, timedelta(minutes=1))
-        s += "%s%02d%s%02d" % (sign, hh, sep, mm)
-        if ss or ss.microseconds:
-            s += "%s%02d" % (sep, ss.seconds)
-
-            if ss.microseconds:
-                s += '.%06d' % ss.microseconds
-    return s
-
-# Correctly substitute for %z and %Z escapes in strftime formats.
-def _wrap_strftime(object, format, timetuple):
-    # Don't call utcoffset() or tzname() unless actually needed.
-    freplace = None  # the string to use for %f
-    zreplace = None  # the string to use for %z
-    colonzreplace = None  # the string to use for %:z
-    Zreplace = None  # the string to use for %Z
-
-    # Scan format for %z, %:z and %Z escapes, replacing as needed.
-    newformat = []
-    push = newformat.append
-    i, n = 0, len(format)
-    while i < n:
-        ch = format[i]
-        i += 1
-        if ch == '%':
-            if i < n:
-                ch = format[i]
-                i += 1
-                if ch == 'f':
-                    if freplace is None:
-                        freplace = '%06d' % getattr(object,
-                                                    'microsecond', 0)
-                    newformat.append(freplace)
-                elif ch == 'z':
-                    if zreplace is None:
-                        if hasattr(object, "utcoffset"):
-                            zreplace = _format_offset(object.utcoffset(), sep="")
-                        else:
-                            zreplace = ""
-                    assert '%' not in zreplace
-                    newformat.append(zreplace)
-                elif ch == ':':
-                    if i < n:
-                        ch2 = format[i]
-                        i += 1
-                        if ch2 == 'z':
-                            if colonzreplace is None:
-                                if hasattr(object, "utcoffset"):
-                                    colonzreplace = _format_offset(object.utcoffset(), sep=":")
-                                else:
-                                    colonzreplace = ""
-                            assert '%' not in colonzreplace
-                            newformat.append(colonzreplace)
-                        else:
-                            push('%')
-                            push(ch)
-                            push(ch2)
-                elif ch == 'Z':
-                    if Zreplace is None:
-                        Zreplace = ""
-                        if hasattr(object, "tzname"):
-                            s = object.tzname()
-                            if s is not None:
-                                # strftime is going to have at this: escape %
-                                Zreplace = s.replace('%', '%%')
-                    newformat.append(Zreplace)
-                else:
-                    push('%')
-                    push(ch)
-            else:
-                push('%')
-        else:
-            push(ch)
-    newformat = "".join(newformat)
-    return _time.strftime(newformat, timetuple)
-
-# Helpers for parsing the result of isoformat()
-def _is_ascii_digit(c):
-    return c in "0123456789"
-
-def _find_isoformat_datetime_separator(dtstr):
-    # See the comment in _datetimemodule.c:_find_isoformat_datetime_separator
-    len_dtstr = len(dtstr)
-    if len_dtstr == 7:
-        return 7
-
-    assert len_dtstr > 7
-    date_separator = "-"
-    week_indicator = "W"
-
-    if dtstr[4] == date_separator:
-        if dtstr[5] == week_indicator:
-            if len_dtstr < 8:
-                raise ValueError("Invalid ISO string")
-            if len_dtstr > 8 and dtstr[8] == date_separator:
-                if len_dtstr == 9:
-                    raise ValueError("Invalid ISO string")
-                if len_dtstr > 10 and _is_ascii_digit(dtstr[10]):
-                    # This is as far as we need to resolve the ambiguity for
-                    # the moment - if we have YYYY-Www-##, the separator is
-                    # either a hyphen at 8 or a number at 10.
-                    #
-                    # We'll assume it's a hyphen at 8 because it's way more
-                    # likely that someone will use a hyphen as a separator than
-                    # a number, but at this point it's really best effort
-                    # because this is an extension of the spec anyway.
-                    # TODO(pganssle): Document this
-                    return 8
-                return 10
-            else:
-                # YYYY-Www (8)
-                return 8
-        else:
-            # YYYY-MM-DD (10)
-            return 10
-    else:
-        if dtstr[4] == week_indicator:
-            # YYYYWww (7) or YYYYWwwd (8)
-            idx = 7
-            while idx < len_dtstr:
-                if not _is_ascii_digit(dtstr[idx]):
-                    break
-                idx += 1
-
-            if idx < 9:
-                return idx
-
-            if idx % 2 == 0:
-                # If the index of the last number is even, it's YYYYWwwd
-                return 7
-            else:
-                return 8
-        else:
-            # YYYYMMDD (8)
-            return 8
-
-
-def _parse_isoformat_date(dtstr):
-    # It is assumed that this is an ASCII-only string of lengths 7, 8 or 10,
-    # see the comment on Modules/_datetimemodule.c:_find_isoformat_datetime_separator
-    assert len(dtstr) in (7, 8, 10)
-    year = int(dtstr[0:4])
-    has_sep = dtstr[4] == '-'
-
-    pos = 4 + has_sep
-    if dtstr[pos:pos + 1] == "W":
-        # YYYY-?Www-?D?
-        pos += 1
-        weekno = int(dtstr[pos:pos + 2])
-        pos += 2
-
-        dayno = 1
-        if len(dtstr) > pos:
-            if (dtstr[pos:pos + 1] == '-') != has_sep:
-                raise ValueError("Inconsistent use of dash separator")
-
-            pos += has_sep
-
-            dayno = int(dtstr[pos:pos + 1])
-
-        return list(_isoweek_to_gregorian(year, weekno, dayno))
-    else:
-        month = int(dtstr[pos:pos + 2])
-        pos += 2
-        if (dtstr[pos:pos + 1] == "-") != has_sep:
-            raise ValueError("Inconsistent use of dash separator")
-
-        pos += has_sep
-        day = int(dtstr[pos:pos + 2])
-
-        return [year, month, day]
-
-
-_FRACTION_CORRECTION = [100000, 10000, 1000, 100, 10]
-
-
-def _parse_hh_mm_ss_ff(tstr):
-    # Parses things of the form HH[:?MM[:?SS[{.,}fff[fff]]]]
-    len_str = len(tstr)
-
-    time_comps = [0, 0, 0, 0]
-    pos = 0
-    for comp in range(0, 3):
-        if (len_str - pos) < 2:
-            raise ValueError("Incomplete time component")
-
-        time_comps[comp] = int(tstr[pos:pos+2])
-
-        pos += 2
-        next_char = tstr[pos:pos+1]
-
-        if comp == 0:
-            has_sep = next_char == ':'
-
-        if not next_char or comp >= 2:
-            break
-
-        if has_sep and next_char != ':':
-            raise ValueError("Invalid time separator: %c" % next_char)
-
-        pos += has_sep
-
-    if pos < len_str:
-        if tstr[pos] not in '.,':
-            raise ValueError("Invalid microsecond component")
-        else:
-            pos += 1
-
-            len_remainder = len_str - pos
-
-            if len_remainder >= 6:
-                to_parse = 6
-            else:
-                to_parse = len_remainder
-
-            time_comps[3] = int(tstr[pos:(pos+to_parse)])
-            if to_parse < 6:
-                time_comps[3] *= _FRACTION_CORRECTION[to_parse-1]
-            if (len_remainder > to_parse
-                    and not all(map(_is_ascii_digit, tstr[(pos+to_parse):]))):
-                raise ValueError("Non-digit values in unparsed fraction")
-
-    return time_comps
-
-def _parse_isoformat_time(tstr):
-    # Format supported is HH[:MM[:SS[.fff[fff]]]][+HH:MM[:SS[.ffffff]]]
-    len_str = len(tstr)
-    if len_str < 2:
-        raise ValueError("Isoformat time too short")
-
-    # This is equivalent to re.search('[+-Z]', tstr), but faster
-    tz_pos = (tstr.find('-') + 1 or tstr.find('+') + 1 or tstr.find('Z') + 1)
-    timestr = tstr[:tz_pos-1] if tz_pos > 0 else tstr
-
-    time_comps = _parse_hh_mm_ss_ff(timestr)
-
-    tzi = None
-    if tz_pos == len_str and tstr[-1] == 'Z':
-        tzi = timezone.utc
-    elif tz_pos > 0:
-        tzstr = tstr[tz_pos:]
-
-        # Valid time zone strings are:
-        # HH                  len: 2
-        # HHMM                len: 4
-        # HH:MM               len: 5
-        # HHMMSS              len: 6
-        # HHMMSS.f+           len: 7+
-        # HH:MM:SS            len: 8
-        # HH:MM:SS.f+         len: 10+
-
-        if len(tzstr) in (0, 1, 3):
-            raise ValueError("Malformed time zone string")
-
-        tz_comps = _parse_hh_mm_ss_ff(tzstr)
-
-        if all(x == 0 for x in tz_comps):
-            tzi = timezone.utc
-        else:
-            tzsign = -1 if tstr[tz_pos - 1] == '-' else 1
-
-            td = timedelta(hours=tz_comps[0], minutes=tz_comps[1],
-                           seconds=tz_comps[2], microseconds=tz_comps[3])
-
-            tzi = timezone(tzsign * td)
-
-    time_comps.append(tzi)
-
-    return time_comps
-
-# tuple[int, int, int] -> tuple[int, int, int] version of date.fromisocalendar
-def _isoweek_to_gregorian(year, week, day):
-    # Year is bounded this way because 9999-12-31 is (9999, 52, 5)
-    if not MINYEAR <= year <= MAXYEAR:
-        raise ValueError(f"Year is out of range: {year}")
-
-    if not 0 < week < 53:
-        out_of_range = True
-
-        if week == 53:
-            # ISO years have 53 weeks in them on years starting with a
-            # Thursday and leap years starting on a Wednesday
-            first_weekday = _ymd2ord(year, 1, 1) % 7
-            if (first_weekday == 4 or (first_weekday == 3 and
-                                       _is_leap(year))):
-                out_of_range = False
-
-        if out_of_range:
-            raise ValueError(f"Invalid week: {week}")
-
-    if not 0 < day < 8:
-        raise ValueError(f"Invalid weekday: {day} (range is [1, 7])")
-
-    # Now compute the offset from (Y, 1, 1) in days:
-    day_offset = (week - 1) * 7 + (day - 1)
-
-    # Calculate the ordinal day for monday, week 1
-    day_1 = _isoweek1monday(year)
-    ord_day = day_1 + day_offset
-
-    return _ord2ymd(ord_day)
-
-
-# Just raise TypeError if the arg isn't None or a string.
-def _check_tzname(name):
-    if name is not None and not isinstance(name, str):
-        raise TypeError("tzinfo.tzname() must return None or string, "
-                        "not '%s'" % type(name))
-
-# name is the offset-producing method, "utcoffset" or "dst".
-# offset is what it returned.
-# If offset isn't None or timedelta, raises TypeError.
-# If offset is None, returns None.
-# Else offset is checked for being in range.
-# If it is, its integer value is returned.  Else ValueError is raised.
-def _check_utc_offset(name, offset):
-    assert name in ("utcoffset", "dst")
-    if offset is None:
-        return
-    if not isinstance(offset, timedelta):
-        raise TypeError("tzinfo.%s() must return None "
-                        "or timedelta, not '%s'" % (name, type(offset)))
-    if not -timedelta(1) < offset < timedelta(1):
-        raise ValueError("%s()=%s, must be strictly between "
-                         "-timedelta(hours=24) and timedelta(hours=24)" %
-                         (name, offset))
-
-def _check_date_fields(year, month, day):
-    year = _index(year)
-    month = _index(month)
-    day = _index(day)
-    if not MINYEAR <= year <= MAXYEAR:
-        raise ValueError('year must be in %d..%d' % (MINYEAR, MAXYEAR), year)
-    if not 1 <= month <= 12:
-        raise ValueError('month must be in 1..12', month)
-    dim = _days_in_month(year, month)
-    if not 1 <= day <= dim:
-        raise ValueError('day must be in 1..%d' % dim, day)
-    return year, month, day
-
-def _check_time_fields(hour, minute, second, microsecond, fold):
-    hour = _index(hour)
-    minute = _index(minute)
-    second = _index(second)
-    microsecond = _index(microsecond)
-    if not 0 <= hour <= 23:
-        raise ValueError('hour must be in 0..23', hour)
-    if not 0 <= minute <= 59:
-        raise ValueError('minute must be in 0..59', minute)
-    if not 0 <= second <= 59:
-        raise ValueError('second must be in 0..59', second)
-    if not 0 <= microsecond <= 999999:
-        raise ValueError('microsecond must be in 0..999999', microsecond)
-    if fold not in (0, 1):
-        raise ValueError('fold must be either 0 or 1', fold)
-    return hour, minute, second, microsecond, fold
-
-def _check_tzinfo_arg(tz):
-    if tz is not None and not isinstance(tz, tzinfo):
-        raise TypeError("tzinfo argument must be None or of a tzinfo subclass")
-
-def _cmperror(x, y):
-    raise TypeError("can't compare '%s' to '%s'" % (
-                    type(x).__name__, type(y).__name__))
-
-def _divide_and_round(a, b):
-    """divide a by b and round result to the nearest integer
-
-    When the ratio is exactly half-way between two integers,
-    the even integer is returned.
-    """
-    # Based on the reference implementation for divmod_near
-    # in Objects/longobject.c.
-    q, r = divmod(a, b)
-    # round up if either r / b > 0.5, or r / b == 0.5 and q is odd.
-    # The expression r / b > 0.5 is equivalent to 2 * r > b if b is
-    # positive, 2 * r < b if b negative.
-    r *= 2
-    greater_than_half = r > b if b > 0 else r < b
-    if greater_than_half or r == b and q % 2 == 1:
-        q += 1
-
-    return q
-
-
-class timedelta:
-    """Represent the difference between two datetime objects.
-
-    Supported operators:
-
-    - add, subtract timedelta
-    - unary plus, minus, abs
-    - compare to timedelta
-    - multiply, divide by int
-
-    In addition, datetime supports subtraction of two datetime objects
-    returning a timedelta, and addition or subtraction of a datetime
-    and a timedelta giving a datetime.
-
-    Representation: (days, seconds, microseconds).
-    """
-    # The representation of (days, seconds, microseconds) was chosen
-    # arbitrarily; the exact rationale originally specified in the docstring
-    # was "Because I felt like it."
-
-    __slots__ = '_days', '_seconds', '_microseconds', '_hashcode'
-
-    def __new__(cls, days=0, seconds=0, microseconds=0,
-                milliseconds=0, minutes=0, hours=0, weeks=0):
-        # Doing this efficiently and accurately in C is going to be difficult
-        # and error-prone, due to ubiquitous overflow possibilities, and that
-        # C double doesn't have enough bits of precision to represent
-        # microseconds over 10K years faithfully.  The code here tries to make
-        # explicit where go-fast assumptions can be relied on, in order to
-        # guide the C implementation; it's way more convoluted than speed-
-        # ignoring auto-overflow-to-long idiomatic Python could be.
-
-        # XXX Check that all inputs are ints or floats.
-
-        # Final values, all integer.
-        # s and us fit in 32-bit signed ints; d isn't bounded.
-        d = s = us = 0
-
-        # Normalize everything to days, seconds, microseconds.
-        days += weeks*7
-        seconds += minutes*60 + hours*3600
-        microseconds += milliseconds*1000
-
-        # Get rid of all fractions, and normalize s and us.
-        # Take a deep breath <wink>.
-        if isinstance(days, float):
-            dayfrac, days = _math.modf(days)
-            daysecondsfrac, daysecondswhole = _math.modf(dayfrac * (24.*3600.))
-            assert daysecondswhole == int(daysecondswhole)  # can't overflow
-            s = int(daysecondswhole)
-            assert days == int(days)
-            d = int(days)
-        else:
-            daysecondsfrac = 0.0
-            d = days
-        assert isinstance(daysecondsfrac, float)
-        assert abs(daysecondsfrac) <= 1.0
-        assert isinstance(d, int)
-        assert abs(s) <= 24 * 3600
-        # days isn't referenced again before redefinition
-
-        if isinstance(seconds, float):
-            secondsfrac, seconds = _math.modf(seconds)
-            assert seconds == int(seconds)
-            seconds = int(seconds)
-            secondsfrac += daysecondsfrac
-            assert abs(secondsfrac) <= 2.0
-        else:
-            secondsfrac = daysecondsfrac
-        # daysecondsfrac isn't referenced again
-        assert isinstance(secondsfrac, float)
-        assert abs(secondsfrac) <= 2.0
-
-        assert isinstance(seconds, int)
-        days, seconds = divmod(seconds, 24*3600)
-        d += days
-        s += int(seconds)    # can't overflow
-        assert isinstance(s, int)
-        assert abs(s) <= 2 * 24 * 3600
-        # seconds isn't referenced again before redefinition
-
-        usdouble = secondsfrac * 1e6
-        assert abs(usdouble) < 2.1e6    # exact value not critical
-        # secondsfrac isn't referenced again
-
-        if isinstance(microseconds, float):
-            microseconds = round(microseconds + usdouble)
-            seconds, microseconds = divmod(microseconds, 1000000)
-            days, seconds = divmod(seconds, 24*3600)
-            d += days
-            s += seconds
-        else:
-            microseconds = int(microseconds)
-            seconds, microseconds = divmod(microseconds, 1000000)
-            days, seconds = divmod(seconds, 24*3600)
-            d += days
-            s += seconds
-            microseconds = round(microseconds + usdouble)
-        assert isinstance(s, int)
-        assert isinstance(microseconds, int)
-        assert abs(s) <= 3 * 24 * 3600
-        assert abs(microseconds) < 3.1e6
-
-        # Just a little bit of carrying possible for microseconds and seconds.
-        seconds, us = divmod(microseconds, 1000000)
-        s += seconds
-        days, s = divmod(s, 24*3600)
-        d += days
-
-        assert isinstance(d, int)
-        assert isinstance(s, int) and 0 <= s < 24*3600
-        assert isinstance(us, int) and 0 <= us < 1000000
-
-        if abs(d) > 999999999:
-            raise OverflowError("timedelta # of days is too large: %d" % d)
-
-        self = object.__new__(cls)
-        self._days = d
-        self._seconds = s
-        self._microseconds = us
-        self._hashcode = -1
-        return self
-
-    def __repr__(self):
-        args = []
-        if self._days:
-            args.append("days=%d" % self._days)
-        if self._seconds:
-            args.append("seconds=%d" % self._seconds)
-        if self._microseconds:
-            args.append("microseconds=%d" % self._microseconds)
-        if not args:
-            args.append('0')
-        return "%s.%s(%s)" % (self.__class__.__module__,
-                              self.__class__.__qualname__,
-                              ', '.join(args))
-
-    def __str__(self):
-        mm, ss = divmod(self._seconds, 60)
-        hh, mm = divmod(mm, 60)
-        s = "%d:%02d:%02d" % (hh, mm, ss)
-        if self._days:
-            def plural(n):
-                return n, abs(n) != 1 and "s" or ""
-            s = ("%d day%s, " % plural(self._days)) + s
-        if self._microseconds:
-            s = s + ".%06d" % self._microseconds
-        return s
-
-    def total_seconds(self):
-        """Total seconds in the duration."""
-        return ((self.days * 86400 + self.seconds) * 10**6 +
-                self.microseconds) / 10**6
-
-    # Read-only field accessors
-    @property
-    def days(self):
-        """days"""
-        return self._days
-
-    @property
-    def seconds(self):
-        """seconds"""
-        return self._seconds
-
-    @property
-    def microseconds(self):
-        """microseconds"""
-        return self._microseconds
-
-    def __add__(self, other):
-        if isinstance(other, timedelta):
-            # for CPython compatibility, we cannot use
-            # our __class__ here, but need a real timedelta
-            return timedelta(self._days + other._days,
-                             self._seconds + other._seconds,
-                             self._microseconds + other._microseconds)
-        return NotImplemented
-
-    __radd__ = __add__
-
-    def __sub__(self, other):
-        if isinstance(other, timedelta):
-            # for CPython compatibility, we cannot use
-            # our __class__ here, but need a real timedelta
-            return timedelta(self._days - other._days,
-                             self._seconds - other._seconds,
-                             self._microseconds - other._microseconds)
-        return NotImplemented
-
-    def __rsub__(self, other):
-        if isinstance(other, timedelta):
-            return -self + other
-        return NotImplemented
-
-    def __neg__(self):
-        # for CPython compatibility, we cannot use
-        # our __class__ here, but need a real timedelta
-        return timedelta(-self._days,
-                         -self._seconds,
-                         -self._microseconds)
-
-    def __pos__(self):
-        return self
-
-    def __abs__(self):
-        if self._days < 0:
-            return -self
-        else:
-            return self
-
-    def __mul__(self, other):
-        if isinstance(other, int):
-            # for CPython compatibility, we cannot use
-            # our __class__ here, but need a real timedelta
-            return timedelta(self._days * other,
-                             self._seconds * other,
-                             self._microseconds * other)
-        if isinstance(other, float):
-            usec = self._to_microseconds()
-            a, b = other.as_integer_ratio()
-            return timedelta(0, 0, _divide_and_round(usec * a, b))
-        return NotImplemented
-
-    __rmul__ = __mul__
-
-    def _to_microseconds(self):
-        return ((self._days * (24*3600) + self._seconds) * 1000000 +
-                self._microseconds)
-
-    def __floordiv__(self, other):
-        if not isinstance(other, (int, timedelta)):
-            return NotImplemented
-        usec = self._to_microseconds()
-        if isinstance(other, timedelta):
-            return usec // other._to_microseconds()
-        if isinstance(other, int):
-            return timedelta(0, 0, usec // other)
-
-    def __truediv__(self, other):
-        if not isinstance(other, (int, float, timedelta)):
-            return NotImplemented
-        usec = self._to_microseconds()
-        if isinstance(other, timedelta):
-            return usec / other._to_microseconds()
-        if isinstance(other, int):
-            return timedelta(0, 0, _divide_and_round(usec, other))
-        if isinstance(other, float):
-            a, b = other.as_integer_ratio()
-            return timedelta(0, 0, _divide_and_round(b * usec, a))
-
-    def __mod__(self, other):
-        if isinstance(other, timedelta):
-            r = self._to_microseconds() % other._to_microseconds()
-            return timedelta(0, 0, r)
-        return NotImplemented
-
-    def __divmod__(self, other):
-        if isinstance(other, timedelta):
-            q, r = divmod(self._to_microseconds(),
-                          other._to_microseconds())
-            return q, timedelta(0, 0, r)
-        return NotImplemented
-
-    # Comparisons of timedelta objects with other.
-
-    def __eq__(self, other):
-        if isinstance(other, timedelta):
-            return self._cmp(other) == 0
-        else:
-            return NotImplemented
-
-    def __le__(self, other):
-        if isinstance(other, timedelta):
-            return self._cmp(other) <= 0
-        else:
-            return NotImplemented
-
-    def __lt__(self, other):
-        if isinstance(other, timedelta):
-            return self._cmp(other) < 0
-        else:
-            return NotImplemented
-
-    def __ge__(self, other):
-        if isinstance(other, timedelta):
-            return self._cmp(other) >= 0
-        else:
-            return NotImplemented
-
-    def __gt__(self, other):
-        if isinstance(other, timedelta):
-            return self._cmp(other) > 0
-        else:
-            return NotImplemented
-
-    def _cmp(self, other):
-        assert isinstance(other, timedelta)
-        return _cmp(self._getstate(), other._getstate())
-
-    def __hash__(self):
-        if self._hashcode == -1:
-            self._hashcode = hash(self._getstate())
-        return self._hashcode
-
-    def __bool__(self):
-        return (self._days != 0 or
-                self._seconds != 0 or
-                self._microseconds != 0)
-
-    # Pickle support.
-
-    def _getstate(self):
-        return (self._days, self._seconds, self._microseconds)
-
-    def __reduce__(self):
-        return (self.__class__, self._getstate())
-
-timedelta.min = timedelta(-999999999)
-timedelta.max = timedelta(days=999999999, hours=23, minutes=59, seconds=59,
-                          microseconds=999999)
-timedelta.resolution = timedelta(microseconds=1)
-
-class date:
-    """Concrete date type.
-
-    Constructors:
-
-    __new__()
-    fromtimestamp()
-    today()
-    fromordinal()
-
-    Operators:
-
-    __repr__, __str__
-    __eq__, __le__, __lt__, __ge__, __gt__, __hash__
-    __add__, __radd__, __sub__ (add/radd only with timedelta arg)
-
-    Methods:
-
-    timetuple()
-    toordinal()
-    weekday()
-    isoweekday(), isocalendar(), isoformat()
-    ctime()
-    strftime()
-
-    Properties (readonly):
-    year, month, day
-    """
-    __slots__ = '_year', '_month', '_day', '_hashcode'
-
-    def __new__(cls, year, month=None, day=None):
-        """Constructor.
-
-        Arguments:
-
-        year, month, day (required, base 1)
-        """
-        if (month is None and
-            isinstance(year, (bytes, str)) and len(year) == 4 and
-            1 <= ord(year[2:3]) <= 12):
-            # Pickle support
-            if isinstance(year, str):
-                try:
-                    year = year.encode('latin1')
-                except UnicodeEncodeError:
-                    # More informative error message.
-                    raise ValueError(
-                        "Failed to encode latin1 string when unpickling "
-                        "a date object. "
-                        "pickle.load(data, encoding='latin1') is assumed.")
-            self = object.__new__(cls)
-            self.__setstate(year)
-            self._hashcode = -1
-            return self
-        year, month, day = _check_date_fields(year, month, day)
-        self = object.__new__(cls)
-        self._year = year
-        self._month = month
-        self._day = day
-        self._hashcode = -1
-        return self
-
-    # Additional constructors
-
-    @classmethod
-    def fromtimestamp(cls, t):
-        "Construct a date from a POSIX timestamp (like time.time())."
-        y, m, d, hh, mm, ss, weekday, jday, dst = _time.localtime(t)
-        return cls(y, m, d)
-
-    @classmethod
-    def today(cls):
-        "Construct a date from time.time()."
-        t = _time.time()
-        return cls.fromtimestamp(t)
-
-    @classmethod
-    def fromordinal(cls, n):
-        """Construct a date from a proleptic Gregorian ordinal.
-
-        January 1 of year 1 is day 1.  Only the year, month and day are
-        non-zero in the result.
-        """
-        y, m, d = _ord2ymd(n)
-        return cls(y, m, d)
-
-    @classmethod
-    def fromisoformat(cls, date_string):
-        """Construct a date from a string in ISO 8601 format."""
-        if not isinstance(date_string, str):
-            raise TypeError('fromisoformat: argument must be str')
-
-        if len(date_string) not in (7, 8, 10):
-            raise ValueError(f'Invalid isoformat string: {date_string!r}')
-
-        try:
-            return cls(*_parse_isoformat_date(date_string))
-        except Exception:
-            raise ValueError(f'Invalid isoformat string: {date_string!r}')
-
-    @classmethod
-    def fromisocalendar(cls, year, week, day):
-        """Construct a date from the ISO year, week number and weekday.
-
-        This is the inverse of the date.isocalendar() function"""
-        return cls(*_isoweek_to_gregorian(year, week, day))
-
-    # Conversions to string
-
-    def __repr__(self):
-        """Convert to formal string, for repr().
-
-        >>> dt = datetime(2010, 1, 1)
-        >>> repr(dt)
-        'datetime.datetime(2010, 1, 1, 0, 0)'
-
-        >>> dt = datetime(2010, 1, 1, tzinfo=timezone.utc)
-        >>> repr(dt)
-        'datetime.datetime(2010, 1, 1, 0, 0, tzinfo=datetime.timezone.utc)'
-        """
-        return "%s.%s(%d, %d, %d)" % (self.__class__.__module__,
-                                      self.__class__.__qualname__,
-                                      self._year,
-                                      self._month,
-                                      self._day)
-    # XXX These shouldn't depend on time.localtime(), because that
-    # clips the usable dates to [1970 .. 2038).  At least ctime() is
-    # easily done without using strftime() -- that's better too because
-    # strftime("%c", ...) is locale specific.
-
-
-    def ctime(self):
-        "Return ctime() style string."
-        weekday = self.toordinal() % 7 or 7
-        return "%s %s %2d 00:00:00 %04d" % (
-            _DAYNAMES[weekday],
-            _MONTHNAMES[self._month],
-            self._day, self._year)
-
-    def strftime(self, format):
-        """
-        Format using strftime().
-
-        Example: "%d/%m/%Y, %H:%M:%S"
-        """
-        return _wrap_strftime(self, format, self.timetuple())
-
-    def __format__(self, fmt):
-        if not isinstance(fmt, str):
-            raise TypeError("must be str, not %s" % type(fmt).__name__)
-        if len(fmt) != 0:
-            return self.strftime(fmt)
-        return str(self)
-
-    def isoformat(self):
-        """Return the date formatted according to ISO.
-
-        This is 'YYYY-MM-DD'.
-
-        References:
-        - http://www.w3.org/TR/NOTE-datetime
-        - http://www.cl.cam.ac.uk/~mgk25/iso-time.html
-        """
-        return "%04d-%02d-%02d" % (self._year, self._month, self._day)
-
-    __str__ = isoformat
-
-    # Read-only field accessors
-    @property
-    def year(self):
-        """year (1-9999)"""
-        return self._year
-
-    @property
-    def month(self):
-        """month (1-12)"""
-        return self._month
-
-    @property
-    def day(self):
-        """day (1-31)"""
-        return self._day
-
-    # Standard conversions, __eq__, __le__, __lt__, __ge__, __gt__,
-    # __hash__ (and helpers)
-
-    def timetuple(self):
-        "Return local time tuple compatible with time.localtime()."
-        return _build_struct_time(self._year, self._month, self._day,
-                                  0, 0, 0, -1)
-
-    def toordinal(self):
-        """Return proleptic Gregorian ordinal for the year, month and day.
-
-        January 1 of year 1 is day 1.  Only the year, month and day values
-        contribute to the result.
-        """
-        return _ymd2ord(self._year, self._month, self._day)
-
-    def replace(self, year=None, month=None, day=None):
-        """Return a new date with new values for the specified fields."""
-        if year is None:
-            year = self._year
-        if month is None:
-            month = self._month
-        if day is None:
-            day = self._day
-        return type(self)(year, month, day)
-
-    # Comparisons of date objects with other.
-
-    def __eq__(self, other):
-        if isinstance(other, date):
-            return self._cmp(other) == 0
-        return NotImplemented
-
-    def __le__(self, other):
-        if isinstance(other, date):
-            return self._cmp(other) <= 0
-        return NotImplemented
-
-    def __lt__(self, other):
-        if isinstance(other, date):
-            return self._cmp(other) < 0
-        return NotImplemented
-
-    def __ge__(self, other):
-        if isinstance(other, date):
-            return self._cmp(other) >= 0
-        return NotImplemented
-
-    def __gt__(self, other):
-        if isinstance(other, date):
-            return self._cmp(other) > 0
-        return NotImplemented
-
-    def _cmp(self, other):
-        assert isinstance(other, date)
-        y, m, d = self._year, self._month, self._day
-        y2, m2, d2 = other._year, other._month, other._day
-        return _cmp((y, m, d), (y2, m2, d2))
-
-    def __hash__(self):
-        "Hash."
-        if self._hashcode == -1:
-            self._hashcode = hash(self._getstate())
-        return self._hashcode
-
-    # Computations
-
-    def __add__(self, other):
-        "Add a date to a timedelta."
-        if isinstance(other, timedelta):
-            o = self.toordinal() + other.days
-            if 0 < o <= _MAXORDINAL:
-                return type(self).fromordinal(o)
-            raise OverflowError("result out of range")
-        return NotImplemented
-
-    __radd__ = __add__
-
-    def __sub__(self, other):
-        """Subtract two dates, or a date and a timedelta."""
-        if isinstance(other, timedelta):
-            return self + timedelta(-other.days)
-        if isinstance(other, date):
-            days1 = self.toordinal()
-            days2 = other.toordinal()
-            return timedelta(days1 - days2)
-        return NotImplemented
-
-    def weekday(self):
-        "Return day of the week, where Monday == 0 ... Sunday == 6."
-        return (self.toordinal() + 6) % 7
-
-    # Day-of-the-week and week-of-the-year, according to ISO
-
-    def isoweekday(self):
-        "Return day of the week, where Monday == 1 ... Sunday == 7."
-        # 1-Jan-0001 is a Monday
-        return self.toordinal() % 7 or 7
-
-    def isocalendar(self):
-        """Return a named tuple containing ISO year, week number, and weekday.
-
-        The first ISO week of the year is the (Mon-Sun) week
-        containing the year's first Thursday; everything else derives
-        from that.
-
-        The first week is 1; Monday is 1 ... Sunday is 7.
-
-        ISO calendar algorithm taken from
-        http://www.phys.uu.nl/~vgent/calendar/isocalendar.htm
-        (used with permission)
-        """
-        year = self._year
-        week1monday = _isoweek1monday(year)
-        today = _ymd2ord(self._year, self._month, self._day)
-        # Internally, week and day have origin 0
-        week, day = divmod(today - week1monday, 7)
-        if week < 0:
-            year -= 1
-            week1monday = _isoweek1monday(year)
-            week, day = divmod(today - week1monday, 7)
-        elif week >= 52:
-            if today >= _isoweek1monday(year+1):
-                year += 1
-                week = 0
-        return _IsoCalendarDate(year, week+1, day+1)
-
-    # Pickle support.
-
-    def _getstate(self):
-        yhi, ylo = divmod(self._year, 256)
-        return bytes([yhi, ylo, self._month, self._day]),
-
-    def __setstate(self, string):
-        yhi, ylo, self._month, self._day = string
-        self._year = yhi * 256 + ylo
-
-    def __reduce__(self):
-        return (self.__class__, self._getstate())
-
-_date_class = date  # so functions w/ args named "date" can get at the class
-
-date.min = date(1, 1, 1)
-date.max = date(9999, 12, 31)
-date.resolution = timedelta(days=1)
-
-
-class tzinfo:
-    """Abstract base class for time zone info classes.
-
-    Subclasses must override the name(), utcoffset() and dst() methods.
-    """
-    __slots__ = ()
-
-    def tzname(self, dt):
-        "datetime -> string name of time zone."
-        raise NotImplementedError("tzinfo subclass must override tzname()")
-
-    def utcoffset(self, dt):
-        "datetime -> timedelta, positive for east of UTC, negative for west of UTC"
-        raise NotImplementedError("tzinfo subclass must override utcoffset()")
-
-    def dst(self, dt):
-        """datetime -> DST offset as timedelta, positive for east of UTC.
-
-        Return 0 if DST not in effect.  utcoffset() must include the DST
-        offset.
-        """
-        raise NotImplementedError("tzinfo subclass must override dst()")
-
-    def fromutc(self, dt):
-        "datetime in UTC -> datetime in local time."
-
-        if not isinstance(dt, datetime):
-            raise TypeError("fromutc() requires a datetime argument")
-        if dt.tzinfo is not self:
-            raise ValueError("dt.tzinfo is not self")
-
-        dtoff = dt.utcoffset()
-        if dtoff is None:
-            raise ValueError("fromutc() requires a non-None utcoffset() "
-                             "result")
-
-        # See the long comment block at the end of this file for an
-        # explanation of this algorithm.
-        dtdst = dt.dst()
-        if dtdst is None:
-            raise ValueError("fromutc() requires a non-None dst() result")
-        delta = dtoff - dtdst
-        if delta:
-            dt += delta
-            dtdst = dt.dst()
-            if dtdst is None:
-                raise ValueError("fromutc(): dt.dst gave inconsistent "
-                                 "results; cannot convert")
-        return dt + dtdst
-
-    # Pickle support.
-
-    def __reduce__(self):
-        getinitargs = getattr(self, "__getinitargs__", None)
-        if getinitargs:
-            args = getinitargs()
-        else:
-            args = ()
-        return (self.__class__, args, self.__getstate__())
-
-
-class IsoCalendarDate(tuple):
-
-    def __new__(cls, year, week, weekday, /):
-        return super().__new__(cls, (year, week, weekday))
-
-    @property
-    def year(self):
-        return self[0]
-
-    @property
-    def week(self):
-        return self[1]
-
-    @property
-    def weekday(self):
-        return self[2]
-
-    def __reduce__(self):
-        # This code is intended to pickle the object without making the
-        # class public. See https://bugs.python.org/msg352381
-        return (tuple, (tuple(self),))
-
-    def __repr__(self):
-        return (f'{self.__class__.__name__}'
-                f'(year={self[0]}, week={self[1]}, weekday={self[2]})')
-
-
-_IsoCalendarDate = IsoCalendarDate
-del IsoCalendarDate
-_tzinfo_class = tzinfo
-
-class time:
-    """Time with time zone.
-
-    Constructors:
-
-    __new__()
-
-    Operators:
-
-    __repr__, __str__
-    __eq__, __le__, __lt__, __ge__, __gt__, __hash__
-
-    Methods:
-
-    strftime()
-    isoformat()
-    utcoffset()
-    tzname()
-    dst()
-
-    Properties (readonly):
-    hour, minute, second, microsecond, tzinfo, fold
-    """
-    __slots__ = '_hour', '_minute', '_second', '_microsecond', '_tzinfo', '_hashcode', '_fold'
-
-    def __new__(cls, hour=0, minute=0, second=0, microsecond=0, tzinfo=None, *, fold=0):
-        """Constructor.
-
-        Arguments:
-
-        hour, minute (required)
-        second, microsecond (default to zero)
-        tzinfo (default to None)
-        fold (keyword only, default to zero)
-        """
-        if (isinstance(hour, (bytes, str)) and len(hour) == 6 and
-            ord(hour[0:1])&0x7F < 24):
-            # Pickle support
-            if isinstance(hour, str):
-                try:
-                    hour = hour.encode('latin1')
-                except UnicodeEncodeError:
-                    # More informative error message.
-                    raise ValueError(
-                        "Failed to encode latin1 string when unpickling "
-                        "a time object. "
-                        "pickle.load(data, encoding='latin1') is assumed.")
-            self = object.__new__(cls)
-            self.__setstate(hour, minute or None)
-            self._hashcode = -1
-            return self
-        hour, minute, second, microsecond, fold = _check_time_fields(
-            hour, minute, second, microsecond, fold)
-        _check_tzinfo_arg(tzinfo)
-        self = object.__new__(cls)
-        self._hour = hour
-        self._minute = minute
-        self._second = second
-        self._microsecond = microsecond
-        self._tzinfo = tzinfo
-        self._hashcode = -1
-        self._fold = fold
-        return self
-
-    # Read-only field accessors
-    @property
-    def hour(self):
-        """hour (0-23)"""
-        return self._hour
-
-    @property
-    def minute(self):
-        """minute (0-59)"""
-        return self._minute
-
-    @property
-    def second(self):
-        """second (0-59)"""
-        return self._second
-
-    @property
-    def microsecond(self):
-        """microsecond (0-999999)"""
-        return self._microsecond
-
-    @property
-    def tzinfo(self):
-        """timezone info object"""
-        return self._tzinfo
-
-    @property
-    def fold(self):
-        return self._fold
-
-    # Standard conversions, __hash__ (and helpers)
-
-    # Comparisons of time objects with other.
-
-    def __eq__(self, other):
-        if isinstance(other, time):
-            return self._cmp(other, allow_mixed=True) == 0
-        else:
-            return NotImplemented
-
-    def __le__(self, other):
-        if isinstance(other, time):
-            return self._cmp(other) <= 0
-        else:
-            return NotImplemented
-
-    def __lt__(self, other):
-        if isinstance(other, time):
-            return self._cmp(other) < 0
-        else:
-            return NotImplemented
-
-    def __ge__(self, other):
-        if isinstance(other, time):
-            return self._cmp(other) >= 0
-        else:
-            return NotImplemented
-
-    def __gt__(self, other):
-        if isinstance(other, time):
-            return self._cmp(other) > 0
-        else:
-            return NotImplemented
-
-    def _cmp(self, other, allow_mixed=False):
-        assert isinstance(other, time)
-        mytz = self._tzinfo
-        ottz = other._tzinfo
-        myoff = otoff = None
-
-        if mytz is ottz:
-            base_compare = True
-        else:
-            myoff = self.utcoffset()
-            otoff = other.utcoffset()
-            base_compare = myoff == otoff
-
-        if base_compare:
-            return _cmp((self._hour, self._minute, self._second,
-                         self._microsecond),
-                        (other._hour, other._minute, other._second,
-                         other._microsecond))
-        if myoff is None or otoff is None:
-            if allow_mixed:
-                return 2 # arbitrary non-zero value
-            else:
-                raise TypeError("cannot compare naive and aware times")
-        myhhmm = self._hour * 60 + self._minute - myoff//timedelta(minutes=1)
-        othhmm = other._hour * 60 + other._minute - otoff//timedelta(minutes=1)
-        return _cmp((myhhmm, self._second, self._microsecond),
-                    (othhmm, other._second, other._microsecond))
-
-    def __hash__(self):
-        """Hash."""
-        if self._hashcode == -1:
-            if self.fold:
-                t = self.replace(fold=0)
-            else:
-                t = self
-            tzoff = t.utcoffset()
-            if not tzoff:  # zero or None
-                self._hashcode = hash(t._getstate()[0])
-            else:
-                h, m = divmod(timedelta(hours=self.hour, minutes=self.minute) - tzoff,
-                              timedelta(hours=1))
-                assert not m % timedelta(minutes=1), "whole minute"
-                m //= timedelta(minutes=1)
-                if 0 <= h < 24:
-                    self._hashcode = hash(time(h, m, self.second, self.microsecond))
-                else:
-                    self._hashcode = hash((h, m, self.second, self.microsecond))
-        return self._hashcode
-
-    # Conversion to string
-
-    def _tzstr(self):
-        """Return formatted timezone offset (+xx:xx) or an empty string."""
-        off = self.utcoffset()
-        return _format_offset(off)
-
-    def __repr__(self):
-        """Convert to formal string, for repr()."""
-        if self._microsecond != 0:
-            s = ", %d, %d" % (self._second, self._microsecond)
-        elif self._second != 0:
-            s = ", %d" % self._second
-        else:
-            s = ""
-        s= "%s.%s(%d, %d%s)" % (self.__class__.__module__,
-                                self.__class__.__qualname__,
-                                self._hour, self._minute, s)
-        if self._tzinfo is not None:
-            assert s[-1:] == ")"
-            s = s[:-1] + ", tzinfo=%r" % self._tzinfo + ")"
-        if self._fold:
-            assert s[-1:] == ")"
-            s = s[:-1] + ", fold=1)"
-        return s
-
-    def isoformat(self, timespec='auto'):
-        """Return the time formatted according to ISO.
-
-        The full format is 'HH:MM:SS.mmmmmm+zz:zz'. By default, the fractional
-        part is omitted if self.microsecond == 0.
-
-        The optional argument timespec specifies the number of additional
-        terms of the time to include. Valid options are 'auto', 'hours',
-        'minutes', 'seconds', 'milliseconds' and 'microseconds'.
-        """
-        s = _format_time(self._hour, self._minute, self._second,
-                          self._microsecond, timespec)
-        tz = self._tzstr()
-        if tz:
-            s += tz
-        return s
-
-    __str__ = isoformat
-
-    @classmethod
-    def fromisoformat(cls, time_string):
-        """Construct a time from a string in one of the ISO 8601 formats."""
-        if not isinstance(time_string, str):
-            raise TypeError('fromisoformat: argument must be str')
-
-        # The spec actually requires that time-only ISO 8601 strings start with
-        # T, but the extended format allows this to be omitted as long as there
-        # is no ambiguity with date strings.
-        time_string = time_string.removeprefix('T')
-
-        try:
-            return cls(*_parse_isoformat_time(time_string))
-        except Exception:
-            raise ValueError(f'Invalid isoformat string: {time_string!r}')
-
-    def strftime(self, format):
-        """Format using strftime().  The date part of the timestamp passed
-        to underlying strftime should not be used.
-        """
-        # The year must be >= 1000 else Python's strftime implementation
-        # can raise a bogus exception.
-        timetuple = (1900, 1, 1,
-                     self._hour, self._minute, self._second,
-                     0, 1, -1)
-        return _wrap_strftime(self, format, timetuple)
-
-    def __format__(self, fmt):
-        if not isinstance(fmt, str):
-            raise TypeError("must be str, not %s" % type(fmt).__name__)
-        if len(fmt) != 0:
-            return self.strftime(fmt)
-        return str(self)
-
-    # Timezone functions
-
-    def utcoffset(self):
-        """Return the timezone offset as timedelta, positive east of UTC
-         (negative west of UTC)."""
-        if self._tzinfo is None:
-            return None
-        offset = self._tzinfo.utcoffset(None)
-        _check_utc_offset("utcoffset", offset)
-        return offset
-
-    def tzname(self):
-        """Return the timezone name.
-
-        Note that the name is 100% informational -- there's no requirement that
-        it mean anything in particular. For example, "GMT", "UTC", "-500",
-        "-5:00", "EDT", "US/Eastern", "America/New York" are all valid replies.
-        """
-        if self._tzinfo is None:
-            return None
-        name = self._tzinfo.tzname(None)
-        _check_tzname(name)
-        return name
-
-    def dst(self):
-        """Return 0 if DST is not in effect, or the DST offset (as timedelta
-        positive eastward) if DST is in effect.
-
-        This is purely informational; the DST offset has already been added to
-        the UTC offset returned by utcoffset() if applicable, so there's no
-        need to consult dst() unless you're interested in displaying the DST
-        info.
-        """
-        if self._tzinfo is None:
-            return None
-        offset = self._tzinfo.dst(None)
-        _check_utc_offset("dst", offset)
-        return offset
-
-    def replace(self, hour=None, minute=None, second=None, microsecond=None,
-                tzinfo=True, *, fold=None):
-        """Return a new time with new values for the specified fields."""
-        if hour is None:
-            hour = self.hour
-        if minute is None:
-            minute = self.minute
-        if second is None:
-            second = self.second
-        if microsecond is None:
-            microsecond = self.microsecond
-        if tzinfo is True:
-            tzinfo = self.tzinfo
-        if fold is None:
-            fold = self._fold
-        return type(self)(hour, minute, second, microsecond, tzinfo, fold=fold)
-
-    # Pickle support.
-
-    def _getstate(self, protocol=3):
-        us2, us3 = divmod(self._microsecond, 256)
-        us1, us2 = divmod(us2, 256)
-        h = self._hour
-        if self._fold and protocol > 3:
-            h += 128
-        basestate = bytes([h, self._minute, self._second,
-                           us1, us2, us3])
-        if self._tzinfo is None:
-            return (basestate,)
-        else:
-            return (basestate, self._tzinfo)
-
-    def __setstate(self, string, tzinfo):
-        if tzinfo is not None and not isinstance(tzinfo, _tzinfo_class):
-            raise TypeError("bad tzinfo state arg")
-        h, self._minute, self._second, us1, us2, us3 = string
-        if h > 127:
-            self._fold = 1
-            self._hour = h - 128
-        else:
-            self._fold = 0
-            self._hour = h
-        self._microsecond = (((us1 << 8) | us2) << 8) | us3
-        self._tzinfo = tzinfo
-
-    def __reduce_ex__(self, protocol):
-        return (self.__class__, self._getstate(protocol))
-
-    def __reduce__(self):
-        return self.__reduce_ex__(2)
-
-_time_class = time  # so functions w/ args named "time" can get at the class
-
-time.min = time(0, 0, 0)
-time.max = time(23, 59, 59, 999999)
-time.resolution = timedelta(microseconds=1)
-
-
-class datetime(date):
-    """datetime(year, month, day[, hour[, minute[, second[, microsecond[,tzinfo]]]]])
-
-    The year, month and day arguments are required. tzinfo may be None, or an
-    instance of a tzinfo subclass. The remaining arguments may be ints.
-    """
-    __slots__ = date.__slots__ + time.__slots__
-
-    def __new__(cls, year, month=None, day=None, hour=0, minute=0, second=0,
-                microsecond=0, tzinfo=None, *, fold=0):
-        if (isinstance(year, (bytes, str)) and len(year) == 10 and
-            1 <= ord(year[2:3])&0x7F <= 12):
-            # Pickle support
-            if isinstance(year, str):
-                try:
-                    year = bytes(year, 'latin1')
-                except UnicodeEncodeError:
-                    # More informative error message.
-                    raise ValueError(
-                        "Failed to encode latin1 string when unpickling "
-                        "a datetime object. "
-                        "pickle.load(data, encoding='latin1') is assumed.")
-            self = object.__new__(cls)
-            self.__setstate(year, month)
-            self._hashcode = -1
-            return self
-        year, month, day = _check_date_fields(year, month, day)
-        hour, minute, second, microsecond, fold = _check_time_fields(
-            hour, minute, second, microsecond, fold)
-        _check_tzinfo_arg(tzinfo)
-        self = object.__new__(cls)
-        self._year = year
-        self._month = month
-        self._day = day
-        self._hour = hour
-        self._minute = minute
-        self._second = second
-        self._microsecond = microsecond
-        self._tzinfo = tzinfo
-        self._hashcode = -1
-        self._fold = fold
-        return self
-
-    # Read-only field accessors
-    @property
-    def hour(self):
-        """hour (0-23)"""
-        return self._hour
-
-    @property
-    def minute(self):
-        """minute (0-59)"""
-        return self._minute
-
-    @property
-    def second(self):
-        """second (0-59)"""
-        return self._second
-
-    @property
-    def microsecond(self):
-        """microsecond (0-999999)"""
-        return self._microsecond
-
-    @property
-    def tzinfo(self):
-        """timezone info object"""
-        return self._tzinfo
-
-    @property
-    def fold(self):
-        return self._fold
-
-    @classmethod
-    def _fromtimestamp(cls, t, utc, tz):
-        """Construct a datetime from a POSIX timestamp (like time.time()).
-
-        A timezone info object may be passed in as well.
-        """
-        frac, t = _math.modf(t)
-        us = round(frac * 1e6)
-        if us >= 1000000:
-            t += 1
-            us -= 1000000
-        elif us < 0:
-            t -= 1
-            us += 1000000
-
-        converter = _time.gmtime if utc else _time.localtime
-        y, m, d, hh, mm, ss, weekday, jday, dst = converter(t)
-        ss = min(ss, 59)    # clamp out leap seconds if the platform has them
-        result = cls(y, m, d, hh, mm, ss, us, tz)
-        if tz is None and not utc:
-            # As of version 2015f max fold in IANA database is
-            # 23 hours at 1969-09-30 13:00:00 in Kwajalein.
-            # Let's probe 24 hours in the past to detect a transition:
-            max_fold_seconds = 24 * 3600
-
-            # On Windows localtime_s throws an OSError for negative values,
-            # thus we can't perform fold detection for values of time less
-            # than the max time fold. See comments in _datetimemodule's
-            # version of this method for more details.
-            if t < max_fold_seconds and sys.platform.startswith("win"):
-                return result
-
-            y, m, d, hh, mm, ss = converter(t - max_fold_seconds)[:6]
-            probe1 = cls(y, m, d, hh, mm, ss, us, tz)
-            trans = result - probe1 - timedelta(0, max_fold_seconds)
-            if trans.days < 0:
-                y, m, d, hh, mm, ss = converter(t + trans // timedelta(0, 1))[:6]
-                probe2 = cls(y, m, d, hh, mm, ss, us, tz)
-                if probe2 == result:
-                    result._fold = 1
-        elif tz is not None:
-            result = tz.fromutc(result)
-        return result
-
-    @classmethod
-    def fromtimestamp(cls, timestamp, tz=None):
-        """Construct a datetime from a POSIX timestamp (like time.time()).
-
-        A timezone info object may be passed in as well.
-        """
-        _check_tzinfo_arg(tz)
-
-        return cls._fromtimestamp(timestamp, tz is not None, tz)
-
-    @classmethod
-    def utcfromtimestamp(cls, t):
-        """Construct a naive UTC datetime from a POSIX timestamp."""
-        return cls._fromtimestamp(t, True, None)
-
-    @classmethod
-    def now(cls, tz=None):
-        "Construct a datetime from time.time() and optional time zone info."
-        t = _time.time()
-        return cls.fromtimestamp(t, tz)
-
-    @classmethod
-    def utcnow(cls):
-        "Construct a UTC datetime from time.time()."
-        t = _time.time()
-        return cls.utcfromtimestamp(t)
-
-    @classmethod
-    def combine(cls, date, time, tzinfo=True):
-        "Construct a datetime from a given date and a given time."
-        if not isinstance(date, _date_class):
-            raise TypeError("date argument must be a date instance")
-        if not isinstance(time, _time_class):
-            raise TypeError("time argument must be a time instance")
-        if tzinfo is True:
-            tzinfo = time.tzinfo
-        return cls(date.year, date.month, date.day,
-                   time.hour, time.minute, time.second, time.microsecond,
-                   tzinfo, fold=time.fold)
-
-    @classmethod
-    def fromisoformat(cls, date_string):
-        """Construct a datetime from a string in one of the ISO 8601 formats."""
-        if not isinstance(date_string, str):
-            raise TypeError('fromisoformat: argument must be str')
-
-        if len(date_string) < 7:
-            raise ValueError(f'Invalid isoformat string: {date_string!r}')
-
-        # Split this at the separator
-        try:
-            separator_location = _find_isoformat_datetime_separator(date_string)
-            dstr = date_string[0:separator_location]
-            tstr = date_string[(separator_location+1):]
-
-            date_components = _parse_isoformat_date(dstr)
-        except ValueError:
-            raise ValueError(
-                f'Invalid isoformat string: {date_string!r}') from None
-
-        if tstr:
-            try:
-                time_components = _parse_isoformat_time(tstr)
-            except ValueError:
-                raise ValueError(
-                    f'Invalid isoformat string: {date_string!r}') from None
-        else:
-            time_components = [0, 0, 0, 0, None]
-
-        return cls(*(date_components + time_components))
-
-    def timetuple(self):
-        "Return local time tuple compatible with time.localtime()."
-        dst = self.dst()
-        if dst is None:
-            dst = -1
-        elif dst:
-            dst = 1
-        else:
-            dst = 0
-        return _build_struct_time(self.year, self.month, self.day,
-                                  self.hour, self.minute, self.second,
-                                  dst)
-
-    def _mktime(self):
-        """Return integer POSIX timestamp."""
-        epoch = datetime(1970, 1, 1)
-        max_fold_seconds = 24 * 3600
-        t = (self - epoch) // timedelta(0, 1)
-        def local(u):
-            y, m, d, hh, mm, ss = _time.localtime(u)[:6]
-            return (datetime(y, m, d, hh, mm, ss) - epoch) // timedelta(0, 1)
-
-        # Our goal is to solve t = local(u) for u.
-        a = local(t) - t
-        u1 = t - a
-        t1 = local(u1)
-        if t1 == t:
-            # We found one solution, but it may not be the one we need.
-            # Look for an earlier solution (if `fold` is 0), or a
-            # later one (if `fold` is 1).
-            u2 = u1 + (-max_fold_seconds, max_fold_seconds)[self.fold]
-            b = local(u2) - u2
-            if a == b:
-                return u1
-        else:
-            b = t1 - u1
-            assert a != b
-        u2 = t - b
-        t2 = local(u2)
-        if t2 == t:
-            return u2
-        if t1 == t:
-            return u1
-        # We have found both offsets a and b, but neither t - a nor t - b is
-        # a solution.  This means t is in the gap.
-        return (max, min)[self.fold](u1, u2)
-
-
-    def timestamp(self):
-        "Return POSIX timestamp as float"
-        if self._tzinfo is None:
-            s = self._mktime()
-            return s + self.microsecond / 1e6
-        else:
-            return (self - _EPOCH).total_seconds()
-
-    def utctimetuple(self):
-        "Return UTC time tuple compatible with time.gmtime()."
-        offset = self.utcoffset()
-        if offset:
-            self -= offset
-        y, m, d = self.year, self.month, self.day
-        hh, mm, ss = self.hour, self.minute, self.second
-        return _build_struct_time(y, m, d, hh, mm, ss, 0)
-
-    def date(self):
-        "Return the date part."
-        return date(self._year, self._month, self._day)
-
-    def time(self):
-        "Return the time part, with tzinfo None."
-        return time(self.hour, self.minute, self.second, self.microsecond, fold=self.fold)
-
-    def timetz(self):
-        "Return the time part, with same tzinfo."
-        return time(self.hour, self.minute, self.second, self.microsecond,
-                    self._tzinfo, fold=self.fold)
-
-    def replace(self, year=None, month=None, day=None, hour=None,
-                minute=None, second=None, microsecond=None, tzinfo=True,
-                *, fold=None):
-        """Return a new datetime with new values for the specified fields."""
-        if year is None:
-            year = self.year
-        if month is None:
-            month = self.month
-        if day is None:
-            day = self.day
-        if hour is None:
-            hour = self.hour
-        if minute is None:
-            minute = self.minute
-        if second is None:
-            second = self.second
-        if microsecond is None:
-            microsecond = self.microsecond
-        if tzinfo is True:
-            tzinfo = self.tzinfo
-        if fold is None:
-            fold = self.fold
-        return type(self)(year, month, day, hour, minute, second,
-                          microsecond, tzinfo, fold=fold)
-
-    def _local_timezone(self):
-        if self.tzinfo is None:
-            ts = self._mktime()
-        else:
-            ts = (self - _EPOCH) // timedelta(seconds=1)
-        localtm = _time.localtime(ts)
-        local = datetime(*localtm[:6])
-        # Extract TZ data
-        gmtoff = localtm.tm_gmtoff
-        zone = localtm.tm_zone
-        return timezone(timedelta(seconds=gmtoff), zone)
-
-    def astimezone(self, tz=None):
-        if tz is None:
-            tz = self._local_timezone()
-        elif not isinstance(tz, tzinfo):
-            raise TypeError("tz argument must be an instance of tzinfo")
-
-        mytz = self.tzinfo
-        if mytz is None:
-            mytz = self._local_timezone()
-            myoffset = mytz.utcoffset(self)
-        else:
-            myoffset = mytz.utcoffset(self)
-            if myoffset is None:
-                mytz = self.replace(tzinfo=None)._local_timezone()
-                myoffset = mytz.utcoffset(self)
-
-        if tz is mytz:
-            return self
-
-        # Convert self to UTC, and attach the new time zone object.
-        utc = (self - myoffset).replace(tzinfo=tz)
-
-        # Convert from UTC to tz's local time.
-        return tz.fromutc(utc)
-
-    # Ways to produce a string.
-
-    def ctime(self):
-        "Return ctime() style string."
-        weekday = self.toordinal() % 7 or 7
-        return "%s %s %2d %02d:%02d:%02d %04d" % (
-            _DAYNAMES[weekday],
-            _MONTHNAMES[self._month],
-            self._day,
-            self._hour, self._minute, self._second,
-            self._year)
-
-    def isoformat(self, sep='T', timespec='auto'):
-        """Return the time formatted according to ISO.
-
-        The full format looks like 'YYYY-MM-DD HH:MM:SS.mmmmmm'.
-        By default, the fractional part is omitted if self.microsecond == 0.
-
-        If self.tzinfo is not None, the UTC offset is also attached, giving
-        giving a full format of 'YYYY-MM-DD HH:MM:SS.mmmmmm+HH:MM'.
-
-        Optional argument sep specifies the separator between date and
-        time, default 'T'.
-
-        The optional argument timespec specifies the number of additional
-        terms of the time to include. Valid options are 'auto', 'hours',
-        'minutes', 'seconds', 'milliseconds' and 'microseconds'.
-        """
-        s = ("%04d-%02d-%02d%c" % (self._year, self._month, self._day, sep) +
-             _format_time(self._hour, self._minute, self._second,
-                          self._microsecond, timespec))
-
-        off = self.utcoffset()
-        tz = _format_offset(off)
-        if tz:
-            s += tz
-
-        return s
-
-    def __repr__(self):
-        """Convert to formal string, for repr()."""
-        L = [self._year, self._month, self._day,  # These are never zero
-             self._hour, self._minute, self._second, self._microsecond]
-        if L[-1] == 0:
-            del L[-1]
-        if L[-1] == 0:
-            del L[-1]
-        s = "%s.%s(%s)" % (self.__class__.__module__,
-                           self.__class__.__qualname__,
-                           ", ".join(map(str, L)))
-        if self._tzinfo is not None:
-            assert s[-1:] == ")"
-            s = s[:-1] + ", tzinfo=%r" % self._tzinfo + ")"
-        if self._fold:
-            assert s[-1:] == ")"
-            s = s[:-1] + ", fold=1)"
-        return s
-
-    def __str__(self):
-        "Convert to string, for str()."
-        return self.isoformat(sep=' ')
-
-    @classmethod
-    def strptime(cls, date_string, format):
-        'string, format -> new datetime parsed from a string (like time.strptime()).'
-        import _strptime
-        return _strptime._strptime_datetime(cls, date_string, format)
-
-    def utcoffset(self):
-        """Return the timezone offset as timedelta positive east of UTC (negative west of
-        UTC)."""
-        if self._tzinfo is None:
-            return None
-        offset = self._tzinfo.utcoffset(self)
-        _check_utc_offset("utcoffset", offset)
-        return offset
-
-    def tzname(self):
-        """Return the timezone name.
-
-        Note that the name is 100% informational -- there's no requirement that
-        it mean anything in particular. For example, "GMT", "UTC", "-500",
-        "-5:00", "EDT", "US/Eastern", "America/New York" are all valid replies.
-        """
-        if self._tzinfo is None:
-            return None
-        name = self._tzinfo.tzname(self)
-        _check_tzname(name)
-        return name
-
-    def dst(self):
-        """Return 0 if DST is not in effect, or the DST offset (as timedelta
-        positive eastward) if DST is in effect.
-
-        This is purely informational; the DST offset has already been added to
-        the UTC offset returned by utcoffset() if applicable, so there's no
-        need to consult dst() unless you're interested in displaying the DST
-        info.
-        """
-        if self._tzinfo is None:
-            return None
-        offset = self._tzinfo.dst(self)
-        _check_utc_offset("dst", offset)
-        return offset
-
-    # Comparisons of datetime objects with other.
-
-    def __eq__(self, other):
-        if isinstance(other, datetime):
-            return self._cmp(other, allow_mixed=True) == 0
-        elif not isinstance(other, date):
-            return NotImplemented
-        else:
-            return False
-
-    def __le__(self, other):
-        if isinstance(other, datetime):
-            return self._cmp(other) <= 0
-        elif not isinstance(other, date):
-            return NotImplemented
-        else:
-            _cmperror(self, other)
-
-    def __lt__(self, other):
-        if isinstance(other, datetime):
-            return self._cmp(other) < 0
-        elif not isinstance(other, date):
-            return NotImplemented
-        else:
-            _cmperror(self, other)
-
-    def __ge__(self, other):
-        if isinstance(other, datetime):
-            return self._cmp(other) >= 0
-        elif not isinstance(other, date):
-            return NotImplemented
-        else:
-            _cmperror(self, other)
-
-    def __gt__(self, other):
-        if isinstance(other, datetime):
-            return self._cmp(other) > 0
-        elif not isinstance(other, date):
-            return NotImplemented
-        else:
-            _cmperror(self, other)
-
-    def _cmp(self, other, allow_mixed=False):
-        assert isinstance(other, datetime)
-        mytz = self._tzinfo
-        ottz = other._tzinfo
-        myoff = otoff = None
-
-        if mytz is ottz:
-            base_compare = True
-        else:
-            myoff = self.utcoffset()
-            otoff = other.utcoffset()
-            # Assume that allow_mixed means that we are called from __eq__
-            if allow_mixed:
-                if myoff != self.replace(fold=not self.fold).utcoffset():
-                    return 2
-                if otoff != other.replace(fold=not other.fold).utcoffset():
-                    return 2
-            base_compare = myoff == otoff
-
-        if base_compare:
-            return _cmp((self._year, self._month, self._day,
-                         self._hour, self._minute, self._second,
-                         self._microsecond),
-                        (other._year, other._month, other._day,
-                         other._hour, other._minute, other._second,
-                         other._microsecond))
-        if myoff is None or otoff is None:
-            if allow_mixed:
-                return 2 # arbitrary non-zero value
-            else:
-                raise TypeError("cannot compare naive and aware datetimes")
-        # XXX What follows could be done more efficiently...
-        diff = self - other     # this will take offsets into account
-        if diff.days < 0:
-            return -1
-        return diff and 1 or 0
-
-    def __add__(self, other):
-        "Add a datetime and a timedelta."
-        if not isinstance(other, timedelta):
-            return NotImplemented
-        delta = timedelta(self.toordinal(),
-                          hours=self._hour,
-                          minutes=self._minute,
-                          seconds=self._second,
-                          microseconds=self._microsecond)
-        delta += other
-        hour, rem = divmod(delta.seconds, 3600)
-        minute, second = divmod(rem, 60)
-        if 0 < delta.days <= _MAXORDINAL:
-            return type(self).combine(date.fromordinal(delta.days),
-                                      time(hour, minute, second,
-                                           delta.microseconds,
-                                           tzinfo=self._tzinfo))
-        raise OverflowError("result out of range")
-
-    __radd__ = __add__
-
-    def __sub__(self, other):
-        "Subtract two datetimes, or a datetime and a timedelta."
-        if not isinstance(other, datetime):
-            if isinstance(other, timedelta):
-                return self + -other
-            return NotImplemented
-
-        days1 = self.toordinal()
-        days2 = other.toordinal()
-        secs1 = self._second + self._minute * 60 + self._hour * 3600
-        secs2 = other._second + other._minute * 60 + other._hour * 3600
-        base = timedelta(days1 - days2,
-                         secs1 - secs2,
-                         self._microsecond - other._microsecond)
-        if self._tzinfo is other._tzinfo:
-            return base
-        myoff = self.utcoffset()
-        otoff = other.utcoffset()
-        if myoff == otoff:
-            return base
-        if myoff is None or otoff is None:
-            raise TypeError("cannot mix naive and timezone-aware time")
-        return base + otoff - myoff
-
-    def __hash__(self):
-        if self._hashcode == -1:
-            if self.fold:
-                t = self.replace(fold=0)
-            else:
-                t = self
-            tzoff = t.utcoffset()
-            if tzoff is None:
-                self._hashcode = hash(t._getstate()[0])
-            else:
-                days = _ymd2ord(self.year, self.month, self.day)
-                seconds = self.hour * 3600 + self.minute * 60 + self.second
-                self._hashcode = hash(timedelta(days, seconds, self.microsecond) - tzoff)
-        return self._hashcode
-
-    # Pickle support.
-
-    def _getstate(self, protocol=3):
-        yhi, ylo = divmod(self._year, 256)
-        us2, us3 = divmod(self._microsecond, 256)
-        us1, us2 = divmod(us2, 256)
-        m = self._month
-        if self._fold and protocol > 3:
-            m += 128
-        basestate = bytes([yhi, ylo, m, self._day,
-                           self._hour, self._minute, self._second,
-                           us1, us2, us3])
-        if self._tzinfo is None:
-            return (basestate,)
-        else:
-            return (basestate, self._tzinfo)
-
-    def __setstate(self, string, tzinfo):
-        if tzinfo is not None and not isinstance(tzinfo, _tzinfo_class):
-            raise TypeError("bad tzinfo state arg")
-        (yhi, ylo, m, self._day, self._hour,
-         self._minute, self._second, us1, us2, us3) = string
-        if m > 127:
-            self._fold = 1
-            self._month = m - 128
-        else:
-            self._fold = 0
-            self._month = m
-        self._year = yhi * 256 + ylo
-        self._microsecond = (((us1 << 8) | us2) << 8) | us3
-        self._tzinfo = tzinfo
-
-    def __reduce_ex__(self, protocol):
-        return (self.__class__, self._getstate(protocol))
-
-    def __reduce__(self):
-        return self.__reduce_ex__(2)
-
-
-datetime.min = datetime(1, 1, 1)
-datetime.max = datetime(9999, 12, 31, 23, 59, 59, 999999)
-datetime.resolution = timedelta(microseconds=1)
-
-
-def _isoweek1monday(year):
-    # Helper to calculate the day number of the Monday starting week 1
-    # XXX This could be done more efficiently
-    THURSDAY = 3
-    firstday = _ymd2ord(year, 1, 1)
-    firstweekday = (firstday + 6) % 7  # See weekday() above
-    week1monday = firstday - firstweekday
-    if firstweekday > THURSDAY:
-        week1monday += 7
-    return week1monday
-
-
-class timezone(tzinfo):
-    __slots__ = '_offset', '_name'
-
-    # Sentinel value to disallow None
-    _Omitted = object()
-    def __new__(cls, offset, name=_Omitted):
-        if not isinstance(offset, timedelta):
-            raise TypeError("offset must be a timedelta")
-        if name is cls._Omitted:
-            if not offset:
-                return cls.utc
-            name = None
-        elif not isinstance(name, str):
-            raise TypeError("name must be a string")
-        if not cls._minoffset <= offset <= cls._maxoffset:
-            raise ValueError("offset must be a timedelta "
-                             "strictly between -timedelta(hours=24) and "
-                             "timedelta(hours=24).")
-        return cls._create(offset, name)
-
-    @classmethod
-    def _create(cls, offset, name=None):
-        self = tzinfo.__new__(cls)
-        self._offset = offset
-        self._name = name
-        return self
-
-    def __getinitargs__(self):
-        """pickle support"""
-        if self._name is None:
-            return (self._offset,)
-        return (self._offset, self._name)
-
-    def __eq__(self, other):
-        if isinstance(other, timezone):
-            return self._offset == other._offset
-        return NotImplemented
-
-    def __hash__(self):
-        return hash(self._offset)
-
-    def __repr__(self):
-        """Convert to formal string, for repr().
-
-        >>> tz = timezone.utc
-        >>> repr(tz)
-        'datetime.timezone.utc'
-        >>> tz = timezone(timedelta(hours=-5), 'EST')
-        >>> repr(tz)
-        "datetime.timezone(datetime.timedelta(-1, 68400), 'EST')"
-        """
-        if self is self.utc:
-            return 'datetime.timezone.utc'
-        if self._name is None:
-            return "%s.%s(%r)" % (self.__class__.__module__,
-                                  self.__class__.__qualname__,
-                                  self._offset)
-        return "%s.%s(%r, %r)" % (self.__class__.__module__,
-                                  self.__class__.__qualname__,
-                                  self._offset, self._name)
-
-    def __str__(self):
-        return self.tzname(None)
-
-    def utcoffset(self, dt):
-        if isinstance(dt, datetime) or dt is None:
-            return self._offset
-        raise TypeError("utcoffset() argument must be a datetime instance"
-                        " or None")
-
-    def tzname(self, dt):
-        if isinstance(dt, datetime) or dt is None:
-            if self._name is None:
-                return self._name_from_offset(self._offset)
-            return self._name
-        raise TypeError("tzname() argument must be a datetime instance"
-                        " or None")
-
-    def dst(self, dt):
-        if isinstance(dt, datetime) or dt is None:
-            return None
-        raise TypeError("dst() argument must be a datetime instance"
-                        " or None")
-
-    def fromutc(self, dt):
-        if isinstance(dt, datetime):
-            if dt.tzinfo is not self:
-                raise ValueError("fromutc: dt.tzinfo "
-                                 "is not self")
-            return dt + self._offset
-        raise TypeError("fromutc() argument must be a datetime instance"
-                        " or None")
-
-    _maxoffset = timedelta(hours=24, microseconds=-1)
-    _minoffset = -_maxoffset
-
-    @staticmethod
-    def _name_from_offset(delta):
-        if not delta:
-            return 'UTC'
-        if delta < timedelta(0):
-            sign = '-'
-            delta = -delta
-        else:
-            sign = '+'
-        hours, rest = divmod(delta, timedelta(hours=1))
-        minutes, rest = divmod(rest, timedelta(minutes=1))
-        seconds = rest.seconds
-        microseconds = rest.microseconds
-        if microseconds:
-            return (f'UTC{sign}{hours:02d}:{minutes:02d}:{seconds:02d}'
-                    f'.{microseconds:06d}')
-        if seconds:
-            return f'UTC{sign}{hours:02d}:{minutes:02d}:{seconds:02d}'
-        return f'UTC{sign}{hours:02d}:{minutes:02d}'
-
-UTC = timezone.utc = timezone._create(timedelta(0))
-
-# bpo-37642: These attributes are rounded to the nearest minute for backwards
-# compatibility, even though the constructor will accept a wider range of
-# values. This may change in the future.
-timezone.min = timezone._create(-timedelta(hours=23, minutes=59))
-timezone.max = timezone._create(timedelta(hours=23, minutes=59))
-_EPOCH = datetime(1970, 1, 1, tzinfo=timezone.utc)
-
-# Some time zone algebra.  For a datetime x, let
-#     x.n = x stripped of its timezone -- its naive time.
-#     x.o = x.utcoffset(), and assuming that doesn't raise an exception or
-#           return None
-#     x.d = x.dst(), and assuming that doesn't raise an exception or
-#           return None
-#     x.s = x's standard offset, x.o - x.d
-#
-# Now some derived rules, where k is a duration (timedelta).
-#
-# 1. x.o = x.s + x.d
-#    This follows from the definition of x.s.
-#
-# 2. If x and y have the same tzinfo member, x.s = y.s.
-#    This is actually a requirement, an assumption we need to make about
-#    sane tzinfo classes.
-#
-# 3. The naive UTC time corresponding to x is x.n - x.o.
-#    This is again a requirement for a sane tzinfo class.
-#
-# 4. (x+k).s = x.s
-#    This follows from #2, and that datetime.timetz+timedelta preserves tzinfo.
-#
-# 5. (x+k).n = x.n + k
-#    Again follows from how arithmetic is defined.
-#
-# Now we can explain tz.fromutc(x).  Let's assume it's an interesting case
-# (meaning that the various tzinfo methods exist, and don't blow up or return
-# None when called).
-#
-# The function wants to return a datetime y with timezone tz, equivalent to x.
-# x is already in UTC.
-#
-# By #3, we want
-#
-#     y.n - y.o = x.n                             [1]
-#
-# The algorithm starts by attaching tz to x.n, and calling that y.  So
-# x.n = y.n at the start.  Then it wants to add a duration k to y, so that [1]
-# becomes true; in effect, we want to solve [2] for k:
-#
-#    (y+k).n - (y+k).o = x.n                      [2]
-#
-# By #1, this is the same as
-#
-#    (y+k).n - ((y+k).s + (y+k).d) = x.n          [3]
-#
-# By #5, (y+k).n = y.n + k, which equals x.n + k because x.n=y.n at the start.
-# Substituting that into [3],
-#
-#    x.n + k - (y+k).s - (y+k).d = x.n; the x.n terms cancel, leaving
-#    k - (y+k).s - (y+k).d = 0; rearranging,
-#    k = (y+k).s - (y+k).d; by #4, (y+k).s == y.s, so
-#    k = y.s - (y+k).d
-#
-# On the RHS, (y+k).d can't be computed directly, but y.s can be, and we
-# approximate k by ignoring the (y+k).d term at first.  Note that k can't be
-# very large, since all offset-returning methods return a duration of magnitude
-# less than 24 hours.  For that reason, if y is firmly in std time, (y+k).d must
-# be 0, so ignoring it has no consequence then.
-#
-# In any case, the new value is
-#
-#     z = y + y.s                                 [4]
-#
-# It's helpful to step back at look at [4] from a higher level:  it's simply
-# mapping from UTC to tz's standard time.
-#
-# At this point, if
-#
-#     z.n - z.o = x.n                             [5]
-#
-# we have an equivalent time, and are almost done.  The insecurity here is
-# at the start of daylight time.  Picture US Eastern for concreteness.  The wall
-# time jumps from 1:59 to 3:00, and wall hours of the form 2:MM don't make good
-# sense then.  The docs ask that an Eastern tzinfo class consider such a time to
-# be EDT (because it's "after 2"), which is a redundant spelling of 1:MM EST
-# on the day DST starts.  We want to return the 1:MM EST spelling because that's
-# the only spelling that makes sense on the local wall clock.
-#
-# In fact, if [5] holds at this point, we do have the standard-time spelling,
-# but that takes a bit of proof.  We first prove a stronger result.  What's the
-# difference between the LHS and RHS of [5]?  Let
-#
-#     diff = x.n - (z.n - z.o)                    [6]
-#
-# Now
-#     z.n =                       by [4]
-#     (y + y.s).n =               by #5
-#     y.n + y.s =                 since y.n = x.n
-#     x.n + y.s =                 since z and y are have the same tzinfo member,
-#                                     y.s = z.s by #2
-#     x.n + z.s
-#
-# Plugging that back into [6] gives
-#
-#     diff =
-#     x.n - ((x.n + z.s) - z.o) =     expanding
-#     x.n - x.n - z.s + z.o =         cancelling
-#     - z.s + z.o =                   by #2
-#     z.d
-#
-# So diff = z.d.
-#
-# If [5] is true now, diff = 0, so z.d = 0 too, and we have the standard-time
-# spelling we wanted in the endcase described above.  We're done.  Contrarily,
-# if z.d = 0, then we have a UTC equivalent, and are also done.
-#
-# If [5] is not true now, diff = z.d != 0, and z.d is the offset we need to
-# add to z (in effect, z is in tz's standard time, and we need to shift the
-# local clock into tz's daylight time).
-#
-# Let
-#
-#     z' = z + z.d = z + diff                     [7]
-#
-# and we can again ask whether
-#
-#     z'.n - z'.o = x.n                           [8]
-#
-# If so, we're done.  If not, the tzinfo class is insane, according to the
-# assumptions we've made.  This also requires a bit of proof.  As before, let's
-# compute the difference between the LHS and RHS of [8] (and skipping some of
-# the justifications for the kinds of substitutions we've done several times
-# already):
-#
-#     diff' = x.n - (z'.n - z'.o) =           replacing z'.n via [7]
-#             x.n  - (z.n + diff - z'.o) =    replacing diff via [6]
-#             x.n - (z.n + x.n - (z.n - z.o) - z'.o) =
-#             x.n - z.n - x.n + z.n - z.o + z'.o =    cancel x.n
-#             - z.n + z.n - z.o + z'.o =              cancel z.n
-#             - z.o + z'.o =                      #1 twice
-#             -z.s - z.d + z'.s + z'.d =          z and z' have same tzinfo
-#             z'.d - z.d
-#
-# So z' is UTC-equivalent to x iff z'.d = z.d at this point.  If they are equal,
-# we've found the UTC-equivalent so are done.  In fact, we stop with [7] and
-# return z', not bothering to compute z'.d.
-#
-# How could z.d and z'd differ?  z' = z + z.d [7], so merely moving z' by
-# a dst() offset, and starting *from* a time already in DST (we know z.d != 0),
-# would have to change the result dst() returns:  we start in DST, and moving
-# a little further into it takes us out of DST.
-#
-# There isn't a sane case where this can happen.  The closest it gets is at
-# the end of DST, where there's an hour in UTC with no spelling in a hybrid
-# tzinfo class.  In US Eastern, that's 5:MM UTC = 0:MM EST = 1:MM EDT.  During
-# that hour, on an Eastern clock 1:MM is taken as being in standard time (6:MM
-# UTC) because the docs insist on that, but 0:MM is taken as being in daylight
-# time (4:MM UTC).  There is no local time mapping to 5:MM UTC.  The local
-# clock jumps from 1:59 back to 1:00 again, and repeats the 1:MM hour in
-# standard time.  Since that's what the local clock *does*, we want to map both
-# UTC hours 5:MM and 6:MM to 1:MM Eastern.  The result is ambiguous
-# in local time, but so it goes -- it's the way the local clock works.
-#
-# When x = 5:MM UTC is the input to this algorithm, x.o=0, y.o=-5 and y.d=0,
-# so z=0:MM.  z.d=60 (minutes) then, so [5] doesn't hold and we keep going.
-# z' = z + z.d = 1:MM then, and z'.d=0, and z'.d - z.d = -60 != 0 so [8]
-# (correctly) concludes that z' is not UTC-equivalent to x.
-#
-# Because we know z.d said z was in daylight time (else [5] would have held and
-# we would have stopped then), and we know z.d != z'.d (else [8] would have held
-# and we have stopped then), and there are only 2 possible values dst() can
-# return in Eastern, it follows that z'.d must be 0 (which it is in the example,
-# but the reasoning doesn't depend on the example -- it depends on there being
-# two possible dst() outcomes, one zero and the other non-zero).  Therefore
-# z' must be in standard time, and is the spelling we want in this case.
-#
-# Note again that z' is not UTC-equivalent as far as the hybrid tzinfo class is
-# concerned (because it takes z' as being in standard time rather than the
-# daylight time we intend here), but returning it gives the real-life "local
-# clock repeats an hour" behavior when mapping the "unspellable" UTC hour into
-# tz.
-#
-# When the input is 6:MM, z=1:MM and z.d=0, and we stop at once, again with
-# the 1:MM standard time spelling we want.
-#
-# So how can this break?  One of the assumptions must be violated.  Two
-# possibilities:
-#
-# 1) [2] effectively says that y.s is invariant across all y belong to a given
-#    time zone.  This isn't true if, for political reasons or continental drift,
-#    a region decides to change its base offset from UTC.
-#
-# 2) There may be versions of "double daylight" time where the tail end of
-#    the analysis gives up a step too early.  I haven't thought about that
-#    enough to say.
-#
-# In any case, it's clear that the default fromutc() is strong enough to handle
-# "almost all" time zones:  so long as the standard offset is invariant, it
-# doesn't matter if daylight time transition points change from year to year, or
-# if daylight time is skipped in some years; it doesn't matter how large or
-# small dst() may get within its bounds; and it doesn't even matter if some
-# perverse time zone returns a negative dst()).  So a breaking case must be
-# pretty bizarre, and a tzinfo subclass can override fromutc() if it is.
-
 try:
     from _datetime import *
-except ImportError:
-    pass
-else:
-    # Clean up unused names
-    del (_DAYNAMES, _DAYS_BEFORE_MONTH, _DAYS_IN_MONTH, _DI100Y, _DI400Y,
-         _DI4Y, _EPOCH, _MAXORDINAL, _MONTHNAMES, _build_struct_time,
-         _check_date_fields, _check_time_fields,
-         _check_tzinfo_arg, _check_tzname, _check_utc_offset, _cmp, _cmperror,
-         _date_class, _days_before_month, _days_before_year, _days_in_month,
-         _format_time, _format_offset, _index, _is_leap, _isoweek1monday, _math,
-         _ord2ymd, _time, _time_class, _tzinfo_class, _wrap_strftime, _ymd2ord,
-         _divide_and_round, _parse_isoformat_date, _parse_isoformat_time,
-         _parse_hh_mm_ss_ff, _IsoCalendarDate, _isoweek_to_gregorian,
-         _find_isoformat_datetime_separator, _FRACTION_CORRECTION,
-         _is_ascii_digit)
-    # XXX Since import * above excludes names that start with _,
-    # docstring does not get overwritten. In the future, it may be
-    # appropriate to maintain a single module level docstring and
-    # remove the following line.
     from _datetime import __doc__
+except ImportError:
+    from _pydatetime import *
+    from _pydatetime import __doc__
+
+__all__ = ("date", "datetime", "time", "timedelta", "timezone", "tzinfo",
+           "MINYEAR", "MAXYEAR")
diff -pruN 3.12.0~a7-1/Lib/dis.py 3.12.0~b1-1/Lib/dis.py
--- 3.12.0~a7-1/Lib/dis.py	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Lib/dis.py	2023-05-22 12:07:36.000000000 +0000
@@ -11,6 +11,8 @@ from opcode import (
     _cache_format,
     _inline_cache_entries,
     _nb_ops,
+    _intrinsic_1_descs,
+    _intrinsic_2_descs,
     _specializations,
     _specialized_instructions,
 )
@@ -41,6 +43,9 @@ JUMP_BACKWARD = opmap['JUMP_BACKWARD']
 FOR_ITER = opmap['FOR_ITER']
 SEND = opmap['SEND']
 LOAD_ATTR = opmap['LOAD_ATTR']
+LOAD_SUPER_ATTR = opmap['LOAD_SUPER_ATTR']
+CALL_INTRINSIC_1 = opmap['CALL_INTRINSIC_1']
+CALL_INTRINSIC_2 = opmap['CALL_INTRINSIC_2']
 
 CACHE = opmap["CACHE"]
 
@@ -64,10 +69,10 @@ def _try_compile(source, name):
        expect code objects
     """
     try:
-        c = compile(source, name, 'eval')
+        return compile(source, name, 'eval')
     except SyntaxError:
-        c = compile(source, name, 'exec')
-    return c
+        pass
+    return compile(source, name, 'exec')
 
 def dis(x=None, *, file=None, depth=None, show_caches=False, adaptive=False):
     """Disassemble classes, methods, functions, and other compiled objects.
@@ -368,9 +373,8 @@ def _get_const_value(op, arg, co_consts)
     assert op in hasconst
 
     argval = UNKNOWN
-    if op == LOAD_CONST or op == RETURN_CONST:
-        if co_consts is not None:
-            argval = co_consts[arg]
+    if co_consts is not None:
+        argval = co_consts[arg]
     return argval
 
 def _get_const_info(op, arg, co_consts):
@@ -475,6 +479,10 @@ def _get_instructions_bytes(code, varnam
                     argval, argrepr = _get_name_info(arg//2, get_name)
                     if (arg & 1) and argrepr:
                         argrepr = "NULL|self + " + argrepr
+                elif deop == LOAD_SUPER_ATTR:
+                    argval, argrepr = _get_name_info(arg//4, get_name)
+                    if (arg & 1) and argrepr:
+                        argrepr = "NULL|self + " + argrepr
                 else:
                     argval, argrepr = _get_name_info(arg, get_name)
             elif deop in hasjabs:
@@ -502,6 +510,10 @@ def _get_instructions_bytes(code, varnam
                                     if arg & (1<<i))
             elif deop == BINARY_OP:
                 _, argrepr = _nb_ops[arg]
+            elif deop == CALL_INTRINSIC_1:
+                argrepr = _intrinsic_1_descs[arg]
+            elif deop == CALL_INTRINSIC_2:
+                argrepr = _intrinsic_2_descs[arg]
         yield Instruction(_all_opname[op], op,
                           arg, argval, argrepr,
                           offset, starts_line, is_jump_target, positions)
diff -pruN 3.12.0~a7-1/Lib/email/_header_value_parser.py 3.12.0~b1-1/Lib/email/_header_value_parser.py
--- 3.12.0~a7-1/Lib/email/_header_value_parser.py	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Lib/email/_header_value_parser.py	2023-05-22 12:07:36.000000000 +0000
@@ -1987,7 +1987,7 @@ def get_address_list(value):
         try:
             token, value = get_address(value)
             address_list.append(token)
-        except errors.HeaderParseError as err:
+        except errors.HeaderParseError:
             leader = None
             if value[0] in CFWS_LEADER:
                 leader, value = get_cfws(value)
@@ -2096,7 +2096,7 @@ def get_msg_id(value):
     except errors.HeaderParseError:
         try:
             token, value = get_no_fold_literal(value)
-        except errors.HeaderParseError as e:
+        except errors.HeaderParseError:
             try:
                 token, value = get_domain(value)
                 msg_id.defects.append(errors.ObsoleteHeaderDefect(
@@ -2443,7 +2443,6 @@ def get_parameter(value):
         raise errors.HeaderParseError("Parameter not followed by '='")
     param.append(ValueTerminal('=', 'parameter-separator'))
     value = value[1:]
-    leader = None
     if value and value[0] in CFWS_LEADER:
         token, value = get_cfws(value)
         param.append(token)
@@ -2568,7 +2567,7 @@ def parse_mime_parameters(value):
         try:
             token, value = get_parameter(value)
             mime_parameters.append(token)
-        except errors.HeaderParseError as err:
+        except errors.HeaderParseError:
             leader = None
             if value[0] in CFWS_LEADER:
                 leader, value = get_cfws(value)
@@ -2626,7 +2625,6 @@ def parse_content_type_header(value):
     don't do that.
     """
     ctype = ContentType()
-    recover = False
     if not value:
         ctype.defects.append(errors.HeaderMissingRequiredValue(
             "Missing content type specification"))
diff -pruN 3.12.0~a7-1/Lib/email/charset.py 3.12.0~b1-1/Lib/email/charset.py
--- 3.12.0~a7-1/Lib/email/charset.py	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Lib/email/charset.py	2023-05-22 12:07:36.000000000 +0000
@@ -341,7 +341,6 @@ class Charset:
                 if not lines and not current_line:
                     lines.append(None)
                 else:
-                    separator = (' ' if lines else '')
                     joined_line = EMPTYSTRING.join(current_line)
                     header_bytes = _encode(joined_line, codec)
                     lines.append(encoder(header_bytes))
diff -pruN 3.12.0~a7-1/Lib/email/feedparser.py 3.12.0~b1-1/Lib/email/feedparser.py
--- 3.12.0~a7-1/Lib/email/feedparser.py	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Lib/email/feedparser.py	2023-05-22 12:07:36.000000000 +0000
@@ -264,7 +264,7 @@ class FeedParser:
                         yield NeedMoreData
                         continue
                     break
-                msg = self._pop_message()
+                self._pop_message()
                 # We need to pop the EOF matcher in order to tell if we're at
                 # the end of the current file, not the end of the last block
                 # of message headers.
diff -pruN 3.12.0~a7-1/Lib/email/message.py 3.12.0~b1-1/Lib/email/message.py
--- 3.12.0~a7-1/Lib/email/message.py	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Lib/email/message.py	2023-05-22 12:07:36.000000000 +0000
@@ -14,7 +14,7 @@ from io import BytesIO, StringIO
 # Intrapackage imports
 from email import utils
 from email import errors
-from email._policybase import Policy, compat32
+from email._policybase import compat32
 from email import charset as _charset
 from email._encoded_words import decode_b
 Charset = _charset.Charset
diff -pruN 3.12.0~a7-1/Lib/email/mime/text.py 3.12.0~b1-1/Lib/email/mime/text.py
--- 3.12.0~a7-1/Lib/email/mime/text.py	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Lib/email/mime/text.py	2023-05-22 12:07:36.000000000 +0000
@@ -6,7 +6,6 @@
 
 __all__ = ['MIMEText']
 
-from email.charset import Charset
 from email.mime.nonmultipart import MIMENonMultipart
 
 
@@ -36,6 +35,6 @@ class MIMEText(MIMENonMultipart):
                 _charset = 'utf-8'
 
         MIMENonMultipart.__init__(self, 'text', _subtype, policy=policy,
-                                  **{'charset': str(_charset)})
+                                  charset=str(_charset))
 
         self.set_payload(_text, _charset)
diff -pruN 3.12.0~a7-1/Lib/email/utils.py 3.12.0~b1-1/Lib/email/utils.py
--- 3.12.0~a7-1/Lib/email/utils.py	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Lib/email/utils.py	2023-05-22 12:07:36.000000000 +0000
@@ -143,13 +143,13 @@ def formatdate(timeval=None, localtime=F
     # 2822 requires that day and month names be the English abbreviations.
     if timeval is None:
         timeval = time.time()
-    if localtime or usegmt:
-        dt = datetime.datetime.fromtimestamp(timeval, datetime.timezone.utc)
-    else:
-        dt = datetime.datetime.utcfromtimestamp(timeval)
+    dt = datetime.datetime.fromtimestamp(timeval, datetime.timezone.utc)
+
     if localtime:
         dt = dt.astimezone()
         usegmt = False
+    elif not usegmt:
+        dt = dt.replace(tzinfo=None)
     return format_datetime(dt, usegmt)
 
 def format_datetime(dt, usegmt=False):
diff -pruN 3.12.0~a7-1/Lib/ensurepip/__init__.py 3.12.0~b1-1/Lib/ensurepip/__init__.py
--- 3.12.0~a7-1/Lib/ensurepip/__init__.py	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Lib/ensurepip/__init__.py	2023-05-22 12:07:36.000000000 +0000
@@ -9,11 +9,9 @@ from importlib import resources
 
 
 __all__ = ["version", "bootstrap"]
-_PACKAGE_NAMES = ('setuptools', 'pip')
-_SETUPTOOLS_VERSION = "65.5.0"
-_PIP_VERSION = "23.0.1"
+_PACKAGE_NAMES = ('pip',)
+_PIP_VERSION = "23.1.2"
 _PROJECTS = [
-    ("setuptools", _SETUPTOOLS_VERSION, "py3"),
     ("pip", _PIP_VERSION, "py3"),
 ]
 
@@ -153,17 +151,17 @@ def _bootstrap(*, root=None, upgrade=Fal
 
     _disable_pip_configuration_settings()
 
-    # By default, installing pip and setuptools installs all of the
+    # By default, installing pip installs all of the
     # following scripts (X.Y == running Python version):
     #
-    #   pip, pipX, pipX.Y, easy_install, easy_install-X.Y
+    #   pip, pipX, pipX.Y
     #
     # pip 1.5+ allows ensurepip to request that some of those be left out
     if altinstall:
-        # omit pip, pipX and easy_install
+        # omit pip, pipX
         os.environ["ENSUREPIP_OPTIONS"] = "altinstall"
     elif not default_pip:
-        # omit pip and easy_install
+        # omit pip
         os.environ["ENSUREPIP_OPTIONS"] = "install"
 
     with tempfile.TemporaryDirectory() as tmpdir:
@@ -271,14 +269,14 @@ def _main(argv=None):
         action="store_true",
         default=False,
         help=("Make an alternate install, installing only the X.Y versioned "
-              "scripts (Default: pipX, pipX.Y, easy_install-X.Y)."),
+              "scripts (Default: pipX, pipX.Y)."),
     )
     parser.add_argument(
         "--default-pip",
         action="store_true",
         default=False,
         help=("Make a default pip install, installing the unqualified pip "
-              "and easy_install in addition to the versioned scripts."),
+              "in addition to the versioned scripts."),
     )
 
     args = parser.parse_args(argv)
Binary files 3.12.0~a7-1/Lib/ensurepip/_bundled/pip-23.0.1-py3-none-any.whl and 3.12.0~b1-1/Lib/ensurepip/_bundled/pip-23.0.1-py3-none-any.whl differ
Binary files 3.12.0~a7-1/Lib/ensurepip/_bundled/pip-23.1.2-py3-none-any.whl and 3.12.0~b1-1/Lib/ensurepip/_bundled/pip-23.1.2-py3-none-any.whl differ
Binary files 3.12.0~a7-1/Lib/ensurepip/_bundled/setuptools-65.5.0-py3-none-any.whl and 3.12.0~b1-1/Lib/ensurepip/_bundled/setuptools-65.5.0-py3-none-any.whl differ
diff -pruN 3.12.0~a7-1/Lib/enum.py 3.12.0~b1-1/Lib/enum.py
--- 3.12.0~a7-1/Lib/enum.py	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Lib/enum.py	2023-05-22 12:07:36.000000000 +0000
@@ -190,6 +190,8 @@ class property(DynamicClassAttribute):
     """
 
     member = None
+    _attr_type = None
+    _cls_type = None
 
     def __get__(self, instance, ownerclass=None):
         if instance is None:
@@ -199,43 +201,36 @@ class property(DynamicClassAttribute):
                 raise AttributeError(
                         '%r has no attribute %r' % (ownerclass, self.name)
                         )
-        else:
-            if self.fget is None:
-                if self.member is None:   # not sure this can happen, but just in case
-                    raise AttributeError(
-                            '%r has no attribute %r' % (ownerclass, self.name)
-                            )
-                # issue warning deprecating this behavior
-                import warnings
-                warnings.warn(
-                        "`member.member` access (e.g. `Color.RED.BLUE`) is "
-                        "deprecated and will be removed in 3.14.",
-                        DeprecationWarning,
-                        stacklevel=2,
-                        )
-                return self.member
-                # XXX: uncomment in 3.14 and remove warning above
-                # raise AttributeError(
-                #         '%r member has no attribute %r' % (ownerclass, self.name)
-                #         )
-            else:
-                return self.fget(instance)
+        if self.fget is not None:
+            # use previous enum.property
+            return self.fget(instance)
+        elif self._attr_type == 'attr':
+            # look up previous attibute
+            return getattr(self._cls_type, self.name)
+        elif self._attr_type == 'desc':
+            # use previous descriptor
+            return getattr(instance._value_, self.name)
+        # look for a member by this name.
+        try:
+            return ownerclass._member_map_[self.name]
+        except KeyError:
+            raise AttributeError(
+                    '%r has no attribute %r' % (ownerclass, self.name)
+                    ) from None
 
     def __set__(self, instance, value):
-        if self.fset is None:
-            raise AttributeError(
-                    "<enum %r> cannot set attribute %r" % (self.clsname, self.name)
-                    )
-        else:
+        if self.fset is not None:
             return self.fset(instance, value)
+        raise AttributeError(
+                "<enum %r> cannot set attribute %r" % (self.clsname, self.name)
+                )
 
     def __delete__(self, instance):
-        if self.fdel is None:
-            raise AttributeError(
-                    "<enum %r> cannot delete attribute %r" % (self.clsname, self.name)
-                    )
-        else:
+        if self.fdel is not None:
             return self.fdel(instance)
+        raise AttributeError(
+                "<enum %r> cannot delete attribute %r" % (self.clsname, self.name)
+                )
 
     def __set_name__(self, ownerclass, name):
         self.name = name
@@ -285,6 +280,13 @@ class _proto_member:
         enum_member.__objclass__ = enum_class
         enum_member.__init__(*args)
         enum_member._sort_order_ = len(enum_class._member_names_)
+
+        if Flag is not None and issubclass(enum_class, Flag):
+            enum_class._flag_mask_ |= value
+            if _is_single_bit(value):
+                enum_class._singles_mask_ |= value
+            enum_class._all_bits_ = 2 ** ((enum_class._flag_mask_).bit_length()) - 1
+
         # If another member with the same value was already defined, the
         # new member becomes an alias to the existing one.
         try:
@@ -314,22 +316,43 @@ class _proto_member:
                 ):
                 # no other instances found, record this member in _member_names_
                 enum_class._member_names_.append(member_name)
-        # get redirect in place before adding to _member_map_
-        # but check for other instances in parent classes first
-        descriptor = None
+        # if necessary, get redirect in place and then add it to _member_map_
+        found_descriptor = None
+        descriptor_type = None
+        class_type = None
         for base in enum_class.__mro__[1:]:
-            descriptor = base.__dict__.get(member_name)
-            if descriptor is not None:
-                if isinstance(descriptor, (property, DynamicClassAttribute)):
+            attr = base.__dict__.get(member_name)
+            if attr is not None:
+                if isinstance(attr, (property, DynamicClassAttribute)):
+                    found_descriptor = attr
+                    class_type = base
+                    descriptor_type = 'enum'
                     break
-        redirect = property()
-        redirect.member = enum_member
-        redirect.__set_name__(enum_class, member_name)
-        if descriptor:
-            redirect.fget = getattr(descriptor, 'fget', None)
-            redirect.fset = getattr(descriptor, 'fset', None)
-            redirect.fdel = getattr(descriptor, 'fdel', None)
-        setattr(enum_class, member_name, redirect)
+                elif _is_descriptor(attr):
+                    found_descriptor = attr
+                    descriptor_type = descriptor_type or 'desc'
+                    class_type = class_type or base
+                    continue
+                else:
+                    descriptor_type = 'attr'
+                    class_type = base
+        if found_descriptor:
+            redirect = property()
+            redirect.member = enum_member
+            redirect.__set_name__(enum_class, member_name)
+            if descriptor_type in ('enum','desc'):
+                # earlier descriptor found; copy fget, fset, fdel to this one.
+                redirect.fget = getattr(found_descriptor, 'fget', None)
+                redirect._get = getattr(found_descriptor, '__get__', None)
+                redirect.fset = getattr(found_descriptor, 'fset', None)
+                redirect._set = getattr(found_descriptor, '__set__', None)
+                redirect.fdel = getattr(found_descriptor, 'fdel', None)
+                redirect._del = getattr(found_descriptor, '__delete__', None)
+            redirect._attr_type = descriptor_type
+            redirect._cls_type = class_type
+            setattr(enum_class, member_name, redirect)
+        else:
+            setattr(enum_class, member_name, enum_member)
         # now add to _member_map_ (even aliases)
         enum_class._member_map_[member_name] = enum_member
         try:
@@ -532,12 +555,8 @@ class EnumType(type):
         classdict['_use_args_'] = use_args
         #
         # convert future enum members into temporary _proto_members
-        # and record integer values in case this will be a Flag
-        flag_mask = 0
         for name in member_names:
             value = classdict[name]
-            if isinstance(value, int):
-                flag_mask |= value
             classdict[name] = _proto_member(value)
         #
         # house-keeping structures
@@ -554,8 +573,9 @@ class EnumType(type):
                 boundary
                 or getattr(first_enum, '_boundary_', None)
                 )
-        classdict['_flag_mask_'] = flag_mask
-        classdict['_all_bits_'] = 2 ** ((flag_mask).bit_length()) - 1
+        classdict['_flag_mask_'] = 0
+        classdict['_singles_mask_'] = 0
+        classdict['_all_bits_'] = 0
         classdict['_inverted_'] = None
         try:
             exc = None
@@ -644,21 +664,10 @@ class EnumType(type):
             ):
             delattr(enum_class, '_boundary_')
             delattr(enum_class, '_flag_mask_')
+            delattr(enum_class, '_singles_mask_')
             delattr(enum_class, '_all_bits_')
             delattr(enum_class, '_inverted_')
         elif Flag is not None and issubclass(enum_class, Flag):
-            # ensure _all_bits_ is correct and there are no missing flags
-            single_bit_total = 0
-            multi_bit_total = 0
-            for flag in enum_class._member_map_.values():
-                flag_value = flag._value_
-                if _is_single_bit(flag_value):
-                    single_bit_total |= flag_value
-                else:
-                    # multi-bit flags are considered aliases
-                    multi_bit_total |= flag_value
-            enum_class._flag_mask_ = single_bit_total
-            #
             # set correct __iter__
             member_list = [m._value_ for m in enum_class]
             if member_list != sorted(member_list):
@@ -974,6 +983,7 @@ class EnumType(type):
 
     @classmethod
     def _find_data_type_(mcls, class_name, bases):
+        # a datatype has a __new__ method, or a __dataclass_fields__ attribute
         data_types = set()
         base_chain = set()
         for chain in bases:
@@ -986,7 +996,7 @@ class EnumType(type):
                     if base._member_type_ is not object:
                         data_types.add(base._member_type_)
                         break
-                elif '__new__' in base.__dict__ or '__init__' in base.__dict__:
+                elif '__new__' in base.__dict__ or '__dataclass_fields__' in base.__dict__:
                     data_types.add(candidate or base)
                     break
                 else:
@@ -1303,8 +1313,8 @@ def _reduce_ex_by_global_name(self, prot
 class FlagBoundary(StrEnum):
     """
     control how out of range values are handled
-    "strict" -> error is raised
-    "conform" -> extra bits are discarded   [default for Flag]
+    "strict" -> error is raised             [default for Flag]
+    "conform" -> extra bits are discarded
     "eject" -> lose flag status
     "keep" -> keep flag status and all bits [default for IntFlag]
     """
@@ -1315,7 +1325,7 @@ class FlagBoundary(StrEnum):
 STRICT, CONFORM, EJECT, KEEP = FlagBoundary
 
 
-class Flag(Enum, boundary=CONFORM):
+class Flag(Enum, boundary=STRICT):
     """
     Support for flags
     """
@@ -1394,6 +1404,7 @@ class Flag(Enum, boundary=CONFORM):
         # - value must not include any skipped flags (e.g. if bit 2 is not
         #   defined, then 0d10 is invalid)
         flag_mask = cls._flag_mask_
+        singles_mask = cls._singles_mask_
         all_bits = cls._all_bits_
         neg_value = None
         if (
@@ -1425,7 +1436,8 @@ class Flag(Enum, boundary=CONFORM):
             value = all_bits + 1 + value
         # get members and unknown
         unknown = value & ~flag_mask
-        member_value = value & flag_mask
+        aliases = value & ~singles_mask
+        member_value = value & singles_mask
         if unknown and cls._boundary_ is not KEEP:
             raise ValueError(
                     '%s(%r) -->  unknown values %r [%s]'
@@ -1439,11 +1451,25 @@ class Flag(Enum, boundary=CONFORM):
             pseudo_member = cls._member_type_.__new__(cls, value)
         if not hasattr(pseudo_member, '_value_'):
             pseudo_member._value_ = value
-        if member_value:
-            pseudo_member._name_ = '|'.join([
-                m._name_ for m in cls._iter_member_(member_value)
-                ])
-            if unknown:
+        if member_value or aliases:
+            members = []
+            combined_value = 0
+            for m in cls._iter_member_(member_value):
+                members.append(m)
+                combined_value |= m._value_
+            if aliases:
+                value = member_value | aliases
+                for n, pm in cls._member_map_.items():
+                    if pm not in members and pm._value_ and pm._value_ & value == pm._value_:
+                        members.append(pm)
+                        combined_value |= pm._value_
+            unknown = value ^ combined_value
+            pseudo_member._name_ = '|'.join([m._name_ for m in members])
+            if not combined_value:
+                pseudo_member._name_ = None
+            elif unknown and cls._boundary_ is STRICT:
+                raise ValueError('%r: no members with value %r' % (cls, unknown))
+            elif unknown:
                 pseudo_member._name_ += '|%s' % cls._numeric_repr_(unknown)
         else:
             pseudo_member._name_ = None
@@ -1675,6 +1701,7 @@ def _simple_enum(etype=Enum, *, boundary
             body['_boundary_'] = boundary or etype._boundary_
             body['_flag_mask_'] = None
             body['_all_bits_'] = None
+            body['_singles_mask_'] = None
             body['_inverted_'] = None
             body['__or__'] = Flag.__or__
             body['__xor__'] = Flag.__xor__
@@ -1750,7 +1777,8 @@ def _simple_enum(etype=Enum, *, boundary
                     else:
                         multi_bits |= value
                     gnv_last_values.append(value)
-            enum_class._flag_mask_ = single_bits
+            enum_class._flag_mask_ = single_bits | multi_bits
+            enum_class._singles_mask_ = single_bits
             enum_class._all_bits_ = 2 ** ((single_bits|multi_bits).bit_length()) - 1
             # set correct __iter__
             member_list = [m._value_ for m in enum_class]
diff -pruN 3.12.0~a7-1/Lib/functools.py 3.12.0~b1-1/Lib/functools.py
--- 3.12.0~a7-1/Lib/functools.py	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Lib/functools.py	2023-05-22 12:07:36.000000000 +0000
@@ -30,7 +30,7 @@ from types import GenericAlias
 # wrapper functions that can handle naive introspection
 
 WRAPPER_ASSIGNMENTS = ('__module__', '__name__', '__qualname__', '__doc__',
-                       '__annotations__')
+                       '__annotations__', '__type_params__')
 WRAPPER_UPDATES = ('__dict__',)
 def update_wrapper(wrapper,
                    wrapped,
diff -pruN 3.12.0~a7-1/Lib/gzip.py 3.12.0~b1-1/Lib/gzip.py
--- 3.12.0~a7-1/Lib/gzip.py	2023-04-04 15:52:42.000000000 +0000
+++ 3.12.0~b1-1/Lib/gzip.py	2023-05-22 12:07:36.000000000 +0000
@@ -22,6 +22,7 @@ _COMPRESS_LEVEL_TRADEOFF = 6
 _COMPRESS_LEVEL_BEST = 9
 
 READ_BUFFER_SIZE = 128 * 1024
+_WRITE_BUFFER_SIZE = 4 * io.DEFAULT_BUFFER_SIZE
 
 
 def open(filename, mode="rb", compresslevel=_COMPRESS_LEVEL_BEST,
@@ -120,6 +121,21 @@ class BadGzipFile(OSError):
     """Exception raised in some cases for invalid gzip files."""
 
 
+class _WriteBufferStream(io.RawIOBase):
+    """Minimal object to pass WriteBuffer flushes into GzipFile"""
+    def __init__(self, gzip_file):
+        self.gzip_file = gzip_file
+
+    def write(self, data):
+        return self.gzip_file._write_raw(data)
+
+    def seekable(self):
+        return False
+
+    def writable(self):
+        return True
+
+
 class GzipFile(_compression.BaseStream):
     """The GzipFile class simulates most of the methods of a file object with
     the exception of the truncate() method.
@@ -184,6 +200,7 @@ class GzipFile(_compression.BaseStream):
         if mode is None:
             mode = getattr(fileobj, 'mode', 'rb')
 
+
         if mode.startswith('r'):
             self.mode = READ
             raw = _GzipReader(fileobj)
@@ -206,6 +223,9 @@ class GzipFile(_compression.BaseStream):
                                              zlib.DEF_MEM_LEVEL,
                                              0)
             self._write_mtime = mtime
+            self._buffer_size = _WRITE_BUFFER_SIZE
+            self._buffer = io.BufferedWriter(_WriteBufferStream(self),
+                                             buffer_size=self._buffer_size)
         else:
             raise ValueError("Invalid mode: {!r}".format(mode))
 
@@ -231,6 +251,11 @@ class GzipFile(_compression.BaseStream):
         self.bufsize = 0
         self.offset = 0  # Current file offset for seek(), tell(), etc
 
+    def tell(self):
+        self._check_not_closed()
+        self._buffer.flush()
+        return super().tell()
+
     def _write_gzip_header(self, compresslevel):
         self.fileobj.write(b'\037\213')             # magic header
         self.fileobj.write(b'\010')                 # compression method
@@ -272,6 +297,10 @@ class GzipFile(_compression.BaseStream):
         if self.fileobj is None:
             raise ValueError("write() on closed GzipFile object")
 
+        return self._buffer.write(data)
+
+    def _write_raw(self, data):
+        # Called by our self._buffer underlying WriteBufferStream.
         if isinstance(data, (bytes, bytearray)):
             length = len(data)
         e