From 7f80d2efd05d216ce3dbe5145439ce48db093cf6 Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Mon, 30 Dec 2024 10:22:42 -0600
Subject: [PATCH 001/157] Show Docker build errors when available (#458)

Needed this...
---
 pythonbuild/docker.py | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/pythonbuild/docker.py b/pythonbuild/docker.py
index 3c75297d..5428ce17 100644
--- a/pythonbuild/docker.py
+++ b/pythonbuild/docker.py
@@ -48,6 +48,9 @@ def ensure_docker_image(client, fh, image_path=None):
         if "aux" in s and "ID" in s["aux"]:
             image = s["aux"]["ID"]
 
+        if "error" in s:
+            log(s["error"])
+
     if not image:
         raise Exception("unable to determine built Docker image")
 

From 916bb0d3d5fc80250521c1f6158aac2415c20c0d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tam=C3=A1s=20Nepusz?= <ntamas@gmail.com>
Date: Mon, 30 Dec 2024 17:23:34 +0100
Subject: [PATCH 002/157] Add missing parser files to Python 3.13 Linux and
 macOS builds (#456)

This PR fixes the CPython 3.13 distributions on Linux and macOS builds
to include the additional object files in subdirectories of the `Parser`
directory. Will fix #378 when merged.

Windows builds are unaffected by the bug because the Windows build
script uses a different mechanism to collect the object files.
---
 cpython-unix/build-cpython.sh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/cpython-unix/build-cpython.sh b/cpython-unix/build-cpython.sh
index 31536f3a..70727c56 100755
--- a/cpython-unix/build-cpython.sh
+++ b/cpython-unix/build-cpython.sh
@@ -989,7 +989,7 @@ ${BUILD_PYTHON} ${ROOT}/fix_shebangs.py ${ROOT}/out/python/install
 
 # Also copy object files so they can be linked in a custom manner by
 # downstream consumers.
-OBJECT_DIRS="Objects Parser Parser/pegen Programs Python Python/deepfreeze"
+OBJECT_DIRS="Objects Parser Parser/lexer Parser/pegen Parser/tokenizer Programs Python Python/deepfreeze"
 OBJECT_DIRS="${OBJECT_DIRS} Modules"
 for ext in _blake2 cjkcodecs _ctypes _ctypes/darwin _decimal _expat _hacl _io _multiprocessing _sha3 _sqlite _sre _testinternalcapi _xxtestfuzz ; do
     OBJECT_DIRS="${OBJECT_DIRS} Modules/${ext}"

From 4c4d3475db6f58479e7d8b9a465130ab8234d5e9 Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Wed, 1 Jan 2025 15:45:53 -0600
Subject: [PATCH 003/157] Configure `pkg-config` during CPython builds (#460)

Closes https://github.com/astral-sh/python-build-standalone/issues/449
---
 cpython-unix/build-cpython.sh | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/cpython-unix/build-cpython.sh b/cpython-unix/build-cpython.sh
index 70727c56..a94b8fab 100755
--- a/cpython-unix/build-cpython.sh
+++ b/cpython-unix/build-cpython.sh
@@ -9,6 +9,12 @@ export ROOT=`pwd`
 
 export PATH=${TOOLS_PATH}/${TOOLCHAIN}/bin:${TOOLS_PATH}/host/bin:${TOOLS_PATH}/deps/bin:$PATH
 
+# Ensure that `pkg-config` (run by CPython's configure script) can find our dependencies
+export PKG_CONFIG_PATH=${TOOLS_PATH}/deps/share/pkgconfig:${TOOLS_PATH}/deps/lib/pkgconfig
+
+# Ensure that `pkg-config` invocations include the static libraries
+export PKG_CONFIG="pkg-config --static"
+
 # configure somehow has problems locating llvm-profdata even though it is in
 # PATH. The macro it is using allows us to specify its path via an
 # environment variable.

From 4859cdf4c3b0a8ef7f4c30c1ae3592e498bd64f1 Mon Sep 17 00:00:00 2001
From: Gregory Szorc <gregory.szorc@gmail.com>
Date: Wed, 1 Jan 2025 15:08:18 -0800
Subject: [PATCH 004/157] unix: BOLT fixes (#463)

As part of investigating failures with BOLT when upgrading to LLVM 19, I
found and fixed a few issues with BOLT.

First, `test_embed` had been segfaulting on BOLT instrumented binaries.
Why I'm not entirely sure. But the segfault only seems to occur in
instrumentation mode. These tests are doing low-level things with the
interpreter. So I suspect some kind of global mutable state issue or
something.

I found the exact tests triggering the segfaults and added annotations
to skip them.

The CPython build system treats the segfault as fatal on 3.13 but not
3.12. This means that on 3.12 we were only running a subset of tests and
not collecting BOLT instrumentation nor applying optimizations for all
tests after `test_embed`.

The removal of the segfault enables us to enable BOLT on 3.13+.

Second, LLVM 19.x has a hard error when handling PIC compiled functions
containing computed gotos. It appears prior versions of LLVM could
silently have buggy behavior in this scenario. We need to skip functions
with computed gotos to allow LLVM 19.x to work with BOLT. It makes sense
to apply this patch before LLVM 19.x upgrade to prevent bugs with
computed gotos.

Third, I noticed BOLT was complaining about the lack of
`-update-debug-sections` during instrumentation.

The 2nd and 3rd issues require common arguments to both BOLT
instrumentation and application invocations. The patch fixing both
introduces a new configure variable to hold common BOLT arguments. This
patch is a good candidate for upstreaming.
---
 cpython-unix/build-cpython.sh                 | 25 +++++++---
 cpython-unix/patch-configure-bolt-flags.patch | 50 +++++++++++++++++++
 ...tch-test-embed-prevent-segfault-3.14.patch | 36 +++++++++++++
 .../patch-test-embed-prevent-segfault.patch   | 20 ++++++++
 4 files changed, 125 insertions(+), 6 deletions(-)
 create mode 100644 cpython-unix/patch-configure-bolt-flags.patch
 create mode 100644 cpython-unix/patch-test-embed-prevent-segfault-3.14.patch
 create mode 100644 cpython-unix/patch-test-embed-prevent-segfault.patch

diff --git a/cpython-unix/build-cpython.sh b/cpython-unix/build-cpython.sh
index a94b8fab..5274f8d2 100755
--- a/cpython-unix/build-cpython.sh
+++ b/cpython-unix/build-cpython.sh
@@ -259,6 +259,11 @@ if [ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_11}" ]; then
     patch -p1 -i ${ROOT}/patch-pwd-remove-conditional.patch
 fi
 
+# Adjust BOLT flags to yield better behavior. See inline details in patch.
+if [ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_12}" ]; then
+    patch -p1 -i ${ROOT}/patch-configure-bolt-flags.patch
+fi
+
 # The optimization make targets are both phony and non-phony. This leads
 # to PGO targets getting reevaluated after a build when you use multiple
 # make invocations. e.g. `make install` like we do below. Fix that.
@@ -293,6 +298,19 @@ if [ -n "${CROSS_COMPILING}" ]; then
   patch -p1 -i ${ROOT}/patch-force-cross-compile.patch
 fi
 
+# BOLT instrumented binaries segfault in some test_embed tests for unknown reasons.
+# On 3.12 (minimum BOLT version), the segfault causes the test harness to
+# abort and BOLT optimization uses the partial test results. On 3.13, the segfault
+# is a fatal error.
+if [ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_10}" ]; then
+    patch -p1 -i ${ROOT}/patch-test-embed-prevent-segfault.patch
+fi
+
+# Same as above but for an additional set of tests introduced in 3.14.
+if [ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_14}" ]; then
+    patch -p1 -i ${ROOT}/patch-test-embed-prevent-segfault-3.14.patch
+fi
+
 # Most bits look at CFLAGS. But setup.py only looks at CPPFLAGS.
 # So we need to set both.
 CFLAGS="${EXTRA_TARGET_CFLAGS} -fPIC -I${TOOLS_PATH}/deps/include -I${TOOLS_PATH}/deps/include/ncursesw"
@@ -393,12 +411,7 @@ fi
 
 if [ -n "${CPYTHON_OPTIMIZED}" ]; then
     CONFIGURE_FLAGS="${CONFIGURE_FLAGS} --enable-optimizations"
-    if [[ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_13}" && -n "${BOLT_CAPABLE}" ]]; then
-        # Due to a SEGFAULT when running `test_embed` with BOLT instrumented binaries, we can't use
-        # BOLT on Python 3.13+.
-        # TODO: Find a fix for this or consider skipping these tests specifically
-        echo "BOLT is disabled on Python 3.13+"
-    elif [[ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_12}" && -n "${BOLT_CAPABLE}" ]]; then
+    if [[ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_12}" && -n "${BOLT_CAPABLE}" ]]; then
         CONFIGURE_FLAGS="${CONFIGURE_FLAGS} --enable-bolt"
     fi
 fi
diff --git a/cpython-unix/patch-configure-bolt-flags.patch b/cpython-unix/patch-configure-bolt-flags.patch
new file mode 100644
index 00000000..c9fbf824
--- /dev/null
+++ b/cpython-unix/patch-configure-bolt-flags.patch
@@ -0,0 +1,50 @@
+diff --git a/configure.ac b/configure.ac
+index bc8c357e996..eef55d4839a 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -2104,6 +2104,27 @@ AS_VAR_IF([enable_shared], [yes], [
+   BOLT_BINARIES="${BOLT_BINARIES} \$(INSTSONAME)"
+ ])
+ 
++AC_ARG_VAR(
++  [BOLT_COMMON_FLAGS],
++  [Common arguments to llvm-bolt when instrumenting and applying]
++)
++
++AC_MSG_CHECKING([BOLT_COMMON_FLAGS])
++if test -z "${BOLT_COMMON_FLAGS}"
++then
++  AS_VAR_SET(
++    [BOLT_COMMON_FLAGS],
++    [m4_normalize("
++      [-update-debug-sections]
++
++      dnl At least LLVM 19.x doesn't support computed gotos in PIC compiled code.
++      dnl Exclude functions containing computed gotos.
++      dnl TODO this may be fixed in LLVM 20.x via https://github.com/llvm/llvm-project/pull/120267.
++      [-skip-funcs=_PyEval_EvalFrameDefault,sre_ucs1_match/1,sre_ucs2_match/1,sre_ucs4_match/1]
++    ")]
++  )
++fi
++
+ AC_ARG_VAR(
+   [BOLT_INSTRUMENT_FLAGS],
+   [Arguments to llvm-bolt when instrumenting binaries]
+@@ -2111,7 +2132,7 @@ AC_ARG_VAR(
+ AC_MSG_CHECKING([BOLT_INSTRUMENT_FLAGS])
+ if test -z "${BOLT_INSTRUMENT_FLAGS}"
+ then
+-  BOLT_INSTRUMENT_FLAGS=
++  BOLT_INSTRUMENT_FLAGS="${BOLT_COMMON_FLAGS}"
+ fi
+ AC_MSG_RESULT([$BOLT_INSTRUMENT_FLAGS])
+ 
+@@ -2125,7 +2146,7 @@ then
+   AS_VAR_SET(
+     [BOLT_APPLY_FLAGS],
+     [m4_normalize("
+-     -update-debug-sections
++     ${BOLT_COMMON_FLAGS}
+      -reorder-blocks=ext-tsp
+      -reorder-functions=hfsort+
+      -split-functions
diff --git a/cpython-unix/patch-test-embed-prevent-segfault-3.14.patch b/cpython-unix/patch-test-embed-prevent-segfault-3.14.patch
new file mode 100644
index 00000000..1d75df4d
--- /dev/null
+++ b/cpython-unix/patch-test-embed-prevent-segfault-3.14.patch
@@ -0,0 +1,36 @@
+diff --git a/Lib/test/test_embed.py b/Lib/test/test_embed.py
+index 7110fb889f3..61e4d0f6179 100644
+--- a/Lib/test/test_embed.py
++++ b/Lib/test/test_embed.py
+@@ -940,6 +940,7 @@ def check_all_configs(self, testname, expected_config=None,
+         self.check_global_config(configs)
+         return configs
+ 
++    @unittest.skip("segfaults on BOLT instrumented binaries")
+     def test_init_default_config(self):
+         self.check_all_configs("test_init_initialize_config", api=API_COMPAT)
+ 
+@@ -1039,6 +1040,7 @@ def test_init_from_config(self):
+         self.check_all_configs("test_init_from_config", config, preconfig,
+                                api=API_COMPAT)
+ 
++    @unittest.skip("segfaults on BOLT instrumented binaries")
+     def test_init_compat_env(self):
+         preconfig = {
+             'allocator': ALLOCATOR_FOR_CONFIG,
+@@ -1074,6 +1076,7 @@ def test_init_compat_env(self):
+         self.check_all_configs("test_init_compat_env", config, preconfig,
+                                api=API_COMPAT)
+ 
++    @unittest.skip("segfaults on BOLT instrumented binaries")
+     def test_init_python_env(self):
+         preconfig = {
+             'allocator': ALLOCATOR_FOR_CONFIG,
+@@ -1772,6 +1775,7 @@ def test_init_set_config(self):
+         self.check_all_configs("test_init_set_config", config,
+                                api=API_ISOLATED)
+ 
++    @unittest.skip("segfaults on BOLT instrumented binaries")
+     def test_initconfig_api(self):
+         preconfig = {
+             'configure_locale': True,
diff --git a/cpython-unix/patch-test-embed-prevent-segfault.patch b/cpython-unix/patch-test-embed-prevent-segfault.patch
new file mode 100644
index 00000000..fa9d9894
--- /dev/null
+++ b/cpython-unix/patch-test-embed-prevent-segfault.patch
@@ -0,0 +1,20 @@
+diff --git a/Lib/test/test_embed.py b/Lib/test/test_embed.py
+index 13713cf37b8..ba23880b15f 100644
+--- a/Lib/test/test_embed.py
++++ b/Lib/test/test_embed.py
+@@ -1615,6 +1615,7 @@ def test_getpath_abspath_win32(self):
+         for (_, expected), result in zip(CASES, results):
+             self.assertEqual(result, expected)
+ 
++    @unittest.skip("segfaults on BOLT instrumented binaries")
+     def test_global_pathconfig(self):
+         # Test C API functions getting the path configuration:
+         #
+@@ -1866,6 +1867,7 @@ def test_no_memleak(self):
+                 self.assertEqual(blocks, 0, out)
+ 
+ 
++@unittest.skip("segfaults on BOLT instrumented binaries")
+ class StdPrinterTests(EmbeddingTestsMixin, unittest.TestCase):
+     # Test PyStdPrinter_Type which is used by _PySys_SetPreliminaryStderr():
+     #   "Set up a preliminary stderr printer until we have enough

From 9122defeacdd0828a2b80577aa7b327da1661a9e Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Wed, 1 Jan 2025 19:52:49 -0600
Subject: [PATCH 005/157] Bump autoconf from 2.71 -> 2.72 (#365)

---
 pythonbuild/downloads.py | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/pythonbuild/downloads.py b/pythonbuild/downloads.py
index 6505c811..40b54f04 100644
--- a/pythonbuild/downloads.py
+++ b/pythonbuild/downloads.py
@@ -4,10 +4,10 @@
 
 DOWNLOADS = {
     "autoconf": {
-        "url": "https://ftp.gnu.org/gnu/autoconf/autoconf-2.71.tar.gz",
-        "size": 2003781,
-        "sha256": "431075ad0bf529ef13cb41e9042c542381103e80015686222b8a9d4abef42a1c",
-        "version": "2.71",
+        "url": "https://ftp.gnu.org/gnu/autoconf/autoconf-2.72.tar.gz",
+        "size": 2143794,
+        "sha256": "afb181a76e1ee72832f6581c0eddf8df032b83e2e0239ef79ebedc4467d92d6e",
+        "version": "2.72",
     },
     # 6.0.19 is the last version licensed under the Sleepycat license.
     "bdb": {

From 2b45a4ddfca45f19791a682bc633011709aad660 Mon Sep 17 00:00:00 2001
From: Gregory Szorc <gregory.szorc@gmail.com>
Date: Wed, 1 Jan 2025 20:23:52 -0800
Subject: [PATCH 006/157] ci: enable PGO on x86-64-v4 (#467)

The GitHub Actions x86-64 runners are using ancient Azure instances
that lack AVX-512. As a result we can't run x86-64-v4 binaries. As
a result we can't perform PGO/BOLT nor run tests using the built
interpreter.

We recently adopted custom runners. Whatever hardware they are
using under the hood appears to support AVX-512 and therefore
the x86-64-v4 instruction set. So we're able to enable PGO
and running tests.

This will theoretically deliver performance wins for the x86-64-v4
builds. But I haven't performed comprehensive testing.
---
 ci-targets.yaml | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/ci-targets.yaml b/ci-targets.yaml
index fa20735e..cd6d2916 100644
--- a/ci-targets.yaml
+++ b/ci-targets.yaml
@@ -218,14 +218,13 @@ linux:
       - "3.14"
     build_options:
       - debug
-      - noopt
-      - lto
+      - pgo+lto
     build_options_conditional:
       - options:
           - freethreaded+debug
-          - freethreaded+noopt
-          - freethreaded+lto
+          - freethreaded+pgo+lto
         minimum-python-version: "3.13"
+    run: true
 
   x86_64-unknown-linux-musl:
     arch: x86_64
@@ -288,6 +287,7 @@ linux:
       - debug
       - noopt
       - lto
+    run: true
 
 windows:
   i686-pc-windows-msvc:

From 0be0a575b4a397599329aa11c919264361550d3b Mon Sep 17 00:00:00 2001
From: Gregory Szorc <gregory.szorc@gmail.com>
Date: Thu, 2 Jan 2025 10:15:42 -0800
Subject: [PATCH 007/157] Upgrade LLVM to 19.1.6 (#462)

This is a redo of #420, which was merged prematurely.

With the BOLT changes from #463 merged, LLVM 19 _just works_.

As part of this we also modernize the BOLT apply settings to follow the
recommendations at
https://llvm.org/devmtg/2024-03/slides/practical-use-of-bolt.pdf.

This includes enabling support for loading hot code from a huge page at
runtime. This should _just work_ and could result in perf wins via
improved iTLB hit rate, etc.
---
 cpython-unix/build-cpython.sh                 |   5 +-
 cpython-unix/build-libffi.sh                  | 362 ++++++++++++++++++
 .../patch-configure-bolt-apply-flags.patch    |  23 ++
 pythonbuild/downloads.py                      |  26 +-
 pythonbuild/utils.py                          |   2 +-
 src/release.rs                                |   6 +-
 6 files changed, 406 insertions(+), 18 deletions(-)
 create mode 100644 cpython-unix/patch-configure-bolt-apply-flags.patch

diff --git a/cpython-unix/build-cpython.sh b/cpython-unix/build-cpython.sh
index 5274f8d2..445726b1 100755
--- a/cpython-unix/build-cpython.sh
+++ b/cpython-unix/build-cpython.sh
@@ -259,9 +259,12 @@ if [ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_11}" ]; then
     patch -p1 -i ${ROOT}/patch-pwd-remove-conditional.patch
 fi
 
-# Adjust BOLT flags to yield better behavior. See inline details in patch.
 if [ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_12}" ]; then
+    # Adjust BOLT flags to yield better behavior. See inline details in patch.
     patch -p1 -i ${ROOT}/patch-configure-bolt-flags.patch
+
+    # Adjust BOLT application flags to make use of modern LLVM features.
+    patch -p1 -i ${ROOT}/patch-configure-bolt-apply-flags.patch
 fi
 
 # The optimization make targets are both phony and non-phony. This leads
diff --git a/cpython-unix/build-libffi.sh b/cpython-unix/build-libffi.sh
index 7a50589e..9b188024 100755
--- a/cpython-unix/build-libffi.sh
+++ b/cpython-unix/build-libffi.sh
@@ -13,6 +13,368 @@ tar -xf libffi-${LIBFFI_VERSION}.tar.gz
 
 pushd libffi-${LIBFFI_VERSION}
 
+# Patches needed to fix compilation on aarch64. Will presumably be in libffi
+# 3.4.7 or 3.5.
+
+# Commit f64141ee3f9e455a060bd09e9ab72b6c94653d7c.
+patch -p1 <<'EOF'
+diff --git a/src/aarch64/sysv.S b/src/aarch64/sysv.S
+index fdd0e8b..60cfa50 100644
+--- a/src/aarch64/sysv.S
++++ b/src/aarch64/sysv.S
+@@ -68,7 +68,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
+ #define BTI_J hint #36
+ /*
+  * The ELF Notes section needs to indicate if BTI is supported, as the first ELF loaded that doesn't
+- * declare this support disables it for the whole process.
++ * declare this support disables it for memory region containing the loaded library.
+  */
+ # define GNU_PROPERTY_AARCH64_BTI (1 << 0)         /* Has Branch Target Identification */
+ 	.text
+@@ -527,6 +527,7 @@ L(do_closure):
+ #if defined(FFI_EXEC_STATIC_TRAMP)
+ 	.align 4
+ CNAME(ffi_closure_SYSV_V_alt):
++	BTI_C
+ 	/* See the comments above trampoline_code_table. */
+ 	ldr	x17, [sp, #8]			/* Load closure in x17 */
+ 	add	sp, sp, #16			/* Restore the stack */
+@@ -541,6 +542,7 @@ CNAME(ffi_closure_SYSV_V_alt):
+
+ 	.align 4
+ CNAME(ffi_closure_SYSV_alt):
++	BTI_C
+ 	/* See the comments above trampoline_code_table. */
+ 	ldr	x17, [sp, #8]			/* Load closure in x17 */
+ 	add	sp, sp, #16			/* Restore the stack */
+diff --git a/testsuite/Makefile.am b/testsuite/Makefile.am
+index d286cf7..6ba98e1 100644
+--- a/testsuite/Makefile.am
++++ b/testsuite/Makefile.am
+@@ -8,7 +8,7 @@ CLEANFILES = *.exe core* *.log *.sum
+
+ EXTRA_DIST = config/default.exp emscripten/build.sh emscripten/conftest.py \
+ 	emscripten/node-tests.sh emscripten/test.html emscripten/test_libffi.py \
+-  emscripten/build-tests.sh lib/libffi.exp lib/target-libpath.exp \
++	emscripten/build-tests.sh lib/libffi.exp lib/target-libpath.exp \
+ 	lib/wrapper.exp libffi.bhaible/Makefile libffi.bhaible/README \
+ 	libffi.bhaible/alignof.h libffi.bhaible/bhaible.exp libffi.bhaible/test-call.c \
+ 	libffi.bhaible/test-callback.c libffi.bhaible/testcases.c libffi.call/align_mixed.c \
+EOF
+
+# Commit 45d284f2d066cc3a080c5be88e51b4d934349797.
+patch -p1 <<'EOF'
+diff --git a/configure.ac b/configure.ac
+index 816bfd6..b35a999 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -189,17 +189,17 @@ AC_CACHE_CHECK([whether compiler supports pointer authentication],
+    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[
+ #ifdef __clang__
+ # if __has_feature(ptrauth_calls)
+-#  define HAVE_PTRAUTH 1
++#  define HAVE_ARM64E_PTRAUTH 1
+ # endif
+ #endif
+
+-#ifndef HAVE_PTRAUTH
++#ifndef HAVE_ARM64E_PTRAUTH
+ # error Pointer authentication not supported
+ #endif
+ 		   ]])],[libffi_cv_as_ptrauth=yes],[libffi_cv_as_ptrauth=no])
+ ])
+ if test "x$libffi_cv_as_ptrauth" = xyes; then
+-    AC_DEFINE(HAVE_PTRAUTH, 1,
++    AC_DEFINE(HAVE_ARM64E_PTRAUTH, 1,
+ 	      [Define if your compiler supports pointer authentication.])
+ fi
+
+diff --git a/include/ffi_cfi.h b/include/ffi_cfi.h
+index f4c292d..8565663 100644
+--- a/include/ffi_cfi.h
++++ b/include/ffi_cfi.h
+@@ -49,6 +49,7 @@
+ # define cfi_personality(enc, exp)	.cfi_personality enc, exp
+ # define cfi_lsda(enc, exp)		.cfi_lsda enc, exp
+ # define cfi_escape(...)		.cfi_escape __VA_ARGS__
++# define cfi_window_save		.cfi_window_save
+
+ #else
+
+@@ -71,6 +72,7 @@
+ # define cfi_personality(enc, exp)
+ # define cfi_lsda(enc, exp)
+ # define cfi_escape(...)
++# define cfi_window_save
+
+ #endif /* HAVE_AS_CFI_PSEUDO_OP */
+ #endif /* FFI_CFI_H */
+diff --git a/src/aarch64/ffi.c b/src/aarch64/ffi.c
+index b13738e..964934d 100644
+--- a/src/aarch64/ffi.c
++++ b/src/aarch64/ffi.c
+@@ -63,7 +63,7 @@ struct call_context
+ #if FFI_EXEC_TRAMPOLINE_TABLE
+
+ #ifdef __MACH__
+-#ifdef HAVE_PTRAUTH
++#ifdef HAVE_ARM64E_PTRAUTH
+ #include <ptrauth.h>
+ #endif
+ #include <mach/vm_param.h>
+@@ -877,7 +877,7 @@ ffi_prep_closure_loc (ffi_closure *closure,
+
+ #if FFI_EXEC_TRAMPOLINE_TABLE
+ # ifdef __MACH__
+-#  ifdef HAVE_PTRAUTH
++#  ifdef HAVE_ARM64E_PTRAUTH
+   codeloc = ptrauth_auth_data(codeloc, ptrauth_key_function_pointer, 0);
+ #  endif
+   void **config = (void **)((uint8_t *)codeloc - PAGE_MAX_SIZE);
+diff --git a/src/aarch64/internal.h b/src/aarch64/internal.h
+index b5d102b..c39f9cb 100644
+--- a/src/aarch64/internal.h
++++ b/src/aarch64/internal.h
+@@ -81,20 +81,62 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
+ /* Helpers for writing assembly compatible with arm ptr auth */
+ #ifdef LIBFFI_ASM
+
+-#ifdef HAVE_PTRAUTH
+-#define SIGN_LR pacibsp
+-#define SIGN_LR_WITH_REG(x) pacib lr, x
+-#define AUTH_LR_AND_RET retab
+-#define AUTH_LR_WITH_REG(x) autib lr, x
+-#define BRANCH_AND_LINK_TO_REG blraaz
+-#define BRANCH_TO_REG braaz
+-#else
+-#define SIGN_LR
+-#define SIGN_LR_WITH_REG(x)
+-#define AUTH_LR_AND_RET ret
+-#define AUTH_LR_WITH_REG(x)
+-#define BRANCH_AND_LINK_TO_REG blr
+-#define BRANCH_TO_REG br
+-#endif
+-
+-#endif
++  #if defined(HAVE_ARM64E_PTRAUTH)
++  /* ARM64E ABI For Darwin */
++  #define SIGN_LR pacibsp
++  #define SIGN_LR_WITH_REG(x) pacib lr, x
++  #define AUTH_LR_AND_RET retab
++  #define AUTH_LR_WITH_REG(x) autib lr, x
++  #define BRANCH_AND_LINK_TO_REG blraaz
++  #define BRANCH_TO_REG braaz
++  #define PAC_CFI_WINDOW_SAVE
++  /* Linux PAC Support */
++  #elif defined(__ARM_FEATURE_PAC_DEFAULT)
++    #define GNU_PROPERTY_AARCH64_POINTER_AUTH (1 << 1)
++    #define PAC_CFI_WINDOW_SAVE cfi_window_save
++    #define TMP_REG x9
++    #define BRANCH_TO_REG br
++    #define BRANCH_AND_LINK_TO_REG blr
++	#define SIGN_LR_LINUX_ONLY SIGN_LR
++    /* Which key to sign with? */
++    #if (__ARM_FEATURE_PAC_DEFAULT & 1) == 1
++      /* Signed with A-key */
++      #define SIGN_LR            hint #25  /* paciasp */
++      #define AUTH_LR            hint #29  /* autiasp */
++    #else
++      /* Signed with B-key */
++      #define SIGN_LR            hint #27  /* pacibsp */
++      #define AUTH_LR            hint #31  /* autibsp */
++    #endif /* __ARM_FEATURE_PAC_DEFAULT */
++    #define AUTH_LR_WITH_REG(x) _auth_lr_with_reg x
++.macro _auth_lr_with_reg modifier
++    mov TMP_REG, sp
++    mov sp, \modifier
++    AUTH_LR
++    mov sp, TMP_REG
++.endm
++  #define SIGN_LR_WITH_REG(x) _sign_lr_with_reg x
++.macro _sign_lr_with_reg modifier
++    mov TMP_REG, sp
++    mov sp, \modifier
++    SIGN_LR
++    mov sp, TMP_REG
++.endm
++  #define AUTH_LR_AND_RET _auth_lr_and_ret modifier
++.macro _auth_lr_and_ret modifier
++    AUTH_LR
++    ret
++.endm
++  #undef TMP_REG
++
++  /* No Pointer Auth */
++  #else
++    #define SIGN_LR
++    #define SIGN_LR_WITH_REG(x)
++    #define AUTH_LR_AND_RET ret
++    #define AUTH_LR_WITH_REG(x)
++    #define BRANCH_AND_LINK_TO_REG blr
++    #define BRANCH_TO_REG br
++    #define PAC_CFI_WINDOW_SAVE
++  #endif /* HAVE_ARM64E_PTRAUTH */
++#endif /* LIBFFI_ASM */
+diff --git a/src/aarch64/sysv.S b/src/aarch64/sysv.S
+index 60cfa50..6a9a561 100644
+--- a/src/aarch64/sysv.S
++++ b/src/aarch64/sysv.S
+@@ -92,27 +92,27 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
+ 	cfi_startproc
+ CNAME(ffi_call_SYSV):
+ 	BTI_C
+-	/* Sign the lr with x1 since that is where it will be stored */
++	PAC_CFI_WINDOW_SAVE
++	/* Sign the lr with x1 since that is the CFA which is the modifer used in auth instructions */
+ 	SIGN_LR_WITH_REG(x1)
+
+-	/* Use a stack frame allocated by our caller.  */
+-#if defined(HAVE_PTRAUTH) && defined(__APPLE__)
++#if defined(HAVE_ARM64E_PTRAUTH) && defined(__APPLE__)
+ 	/* darwin's libunwind assumes that the cfa is the sp and that's the data
+ 	 * used to sign the lr.  In order to allow unwinding through this
+ 	 * function it is necessary to point the cfa at the signing register.
+ 	 */
+ 	cfi_def_cfa(x1, 0);
+-#else
+-	cfi_def_cfa(x1, 40);
+ #endif
++	/* Use a stack frame allocated by our caller.  */
+ 	stp	x29, x30, [x1]
++	cfi_def_cfa_register(x1)
++	cfi_rel_offset (x29, 0)
++	cfi_rel_offset (x30, 8)
+ 	mov	x9, sp
+ 	str	x9, [x1, #32]
+ 	mov	x29, x1
+-	mov	sp, x0
+ 	cfi_def_cfa_register(x29)
+-	cfi_rel_offset (x29, 0)
+-	cfi_rel_offset (x30, 8)
++	mov	sp, x0
+
+ 	mov	x9, x2			/* save fn */
+ 	mov	x8, x3			/* install structure return */
+@@ -326,6 +326,7 @@ CNAME(ffi_closure_SYSV_V):
+ 	cfi_startproc
+ 	BTI_C
+ 	SIGN_LR
++	PAC_CFI_WINDOW_SAVE
+ 	stp     x29, x30, [sp, #-ffi_closure_SYSV_FS]!
+ 	cfi_adjust_cfa_offset (ffi_closure_SYSV_FS)
+ 	cfi_rel_offset (x29, 0)
+@@ -351,6 +352,7 @@ CNAME(ffi_closure_SYSV_V):
+ CNAME(ffi_closure_SYSV):
+ 	BTI_C
+ 	SIGN_LR
++	PAC_CFI_WINDOW_SAVE
+ 	stp     x29, x30, [sp, #-ffi_closure_SYSV_FS]!
+ 	cfi_adjust_cfa_offset (ffi_closure_SYSV_FS)
+ 	cfi_rel_offset (x29, 0)
+@@ -648,6 +650,8 @@ CNAME(ffi_go_closure_SYSV_V):
+ 	cfi_startproc
+ CNAME(ffi_go_closure_SYSV):
+ 	BTI_C
++	SIGN_LR_LINUX_ONLY
++	PAC_CFI_WINDOW_SAVE
+ 	stp     x29, x30, [sp, #-ffi_closure_SYSV_FS]!
+ 	cfi_adjust_cfa_offset (ffi_closure_SYSV_FS)
+ 	cfi_rel_offset (x29, 0)
+diff --git a/src/closures.c b/src/closures.c
+index 67a94a8..02cf78f 100644
+--- a/src/closures.c
++++ b/src/closures.c
+@@ -164,7 +164,7 @@ ffi_tramp_is_present (__attribute__((unused)) void *ptr)
+
+ #include <mach/mach.h>
+ #include <pthread.h>
+-#ifdef HAVE_PTRAUTH
++#ifdef HAVE_ARM64E_PTRAUTH
+ #include <ptrauth.h>
+ #endif
+ #include <stdio.h>
+@@ -223,7 +223,7 @@ ffi_trampoline_table_alloc (void)
+   /* Remap the trampoline table on top of the placeholder page */
+   trampoline_page = config_page + PAGE_MAX_SIZE;
+
+-#ifdef HAVE_PTRAUTH
++#ifdef HAVE_ARM64E_PTRAUTH
+   trampoline_page_template = (vm_address_t)(uintptr_t)ptrauth_auth_data((void *)&ffi_closure_trampoline_table_page, ptrauth_key_function_pointer, 0);
+ #else
+   trampoline_page_template = (vm_address_t)&ffi_closure_trampoline_table_page;
+@@ -268,7 +268,7 @@ ffi_trampoline_table_alloc (void)
+       ffi_trampoline_table_entry *entry = &table->free_list_pool[i];
+       entry->trampoline =
+ 	(void *) (trampoline_page + (i * FFI_TRAMPOLINE_SIZE));
+-#ifdef HAVE_PTRAUTH
++#ifdef HAVE_ARM64E_PTRAUTH
+       entry->trampoline = ptrauth_sign_unauthenticated(entry->trampoline, ptrauth_key_function_pointer, 0);
+ #endif
+
+EOF
+
+# Commit 9c9e8368e49804c4f7c35ac9f0d7c1d0d533308b.
+patch -p1 <<'EOF'
+diff --git a/src/aarch64/internal.h b/src/aarch64/internal.h
+index c39f9cb..50fa5c1 100644
+--- a/src/aarch64/internal.h
++++ b/src/aarch64/internal.h
+@@ -88,6 +88,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
+   #define AUTH_LR_AND_RET retab
+   #define AUTH_LR_WITH_REG(x) autib lr, x
+   #define BRANCH_AND_LINK_TO_REG blraaz
++  #define SIGN_LR_LINUX_ONLY
+   #define BRANCH_TO_REG braaz
+   #define PAC_CFI_WINDOW_SAVE
+   /* Linux PAC Support */
+@@ -136,6 +137,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
+     #define AUTH_LR_AND_RET ret
+     #define AUTH_LR_WITH_REG(x)
+     #define BRANCH_AND_LINK_TO_REG blr
++    #define SIGN_LR_LINUX_ONLY
+     #define BRANCH_TO_REG br
+     #define PAC_CFI_WINDOW_SAVE
+   #endif /* HAVE_ARM64E_PTRAUTH */
+EOF
+
+# Commit 8308bed5b2423878aa20d7884a99cf2e30b8daf7.
+patch -p1 <<'EOF'
+diff --git a/src/aarch64/sysv.S b/src/aarch64/sysv.S
+index 6a9a561..e83bc65 100644
+--- a/src/aarch64/sysv.S
++++ b/src/aarch64/sysv.S
+@@ -89,8 +89,8 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
+    x5 closure
+ */
+
+-	cfi_startproc
+ CNAME(ffi_call_SYSV):
++	cfi_startproc
+ 	BTI_C
+ 	PAC_CFI_WINDOW_SAVE
+ 	/* Sign the lr with x1 since that is the CFA which is the modifer used in auth instructions */
+@@ -348,8 +348,8 @@ CNAME(ffi_closure_SYSV_V):
+ #endif
+
+ 	.align	4
+-	cfi_startproc
+ CNAME(ffi_closure_SYSV):
++	cfi_startproc
+ 	BTI_C
+ 	SIGN_LR
+ 	PAC_CFI_WINDOW_SAVE
+@@ -647,8 +647,8 @@ CNAME(ffi_go_closure_SYSV_V):
+ #endif
+
+ 	.align	4
+-	cfi_startproc
+ CNAME(ffi_go_closure_SYSV):
++	cfi_startproc
+ 	BTI_C
+ 	SIGN_LR_LINUX_ONLY
+ 	PAC_CFI_WINDOW_SAVE
+EOF
+
 EXTRA_CONFIGURE=
 
 # mkostemp() was introduced in macOS 10.10 and libffi doesn't have
diff --git a/cpython-unix/patch-configure-bolt-apply-flags.patch b/cpython-unix/patch-configure-bolt-apply-flags.patch
new file mode 100644
index 00000000..c91822e4
--- /dev/null
+++ b/cpython-unix/patch-configure-bolt-apply-flags.patch
@@ -0,0 +1,23 @@
+diff --git a/configure.ac b/configure.ac
+index ee034e5a962..f1a69b7d4a7 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -2183,8 +2183,9 @@ then
+     [m4_normalize("
+      -update-debug-sections
+      -reorder-blocks=ext-tsp
+-     -reorder-functions=hfsort+
++     -reorder-functions=cdsort
+      -split-functions
++     -split-strategy=cdsplit
+      -icf=1
+      -inline-all
+      -split-eh
+@@ -2196,6 +2197,7 @@ then
+      -dyno-stats
+      -use-gnu-stack
+      -frame-opt=hot
++     -hugify
+    ")]
+   )
+ fi
diff --git a/pythonbuild/downloads.py b/pythonbuild/downloads.py
index 40b54f04..9ef1279a 100644
--- a/pythonbuild/downloads.py
+++ b/pythonbuild/downloads.py
@@ -185,25 +185,25 @@
         "version": "14.0.3+20220508",
     },
     # Remember to update LLVM_URL in src/release.rs whenever upgrading.
-    "llvm-18-x86_64-linux": {
-        "url": "https://github.com/indygreg/toolchain-tools/releases/download/toolchain-bootstrap%2F20240713/llvm-18.0.8+20240713-gnu_only-x86_64-unknown-linux-gnu.tar.zst",
-        "size": 242840506,
-        "sha256": "080c233fc7d75031b187bbfef62a4f9abc01188effb0c68fbc7dc4bc7370ee5b",
-        "version": "18.0.8+20240713",
+    "llvm-19-x86_64-linux": {
+        "url": "https://github.com/indygreg/toolchain-tools/releases/download/toolchain-bootstrap%2F20241231/llvm-19.1.6+20241231-gnu_only-x86_64-unknown-linux-gnu.tar.zst",
+        "size": 251277644,
+        "sha256": "900bbb464d430e960ea97150e073395ae865332ce403e7c1e8f76640cab5e852",
+        "version": "19.1.6+20241231",
     },
     # Remember to update LLVM_URL in src/release.rs whenever upgrading.
     "llvm-aarch64-macos": {
-        "url": "https://github.com/indygreg/toolchain-tools/releases/download/toolchain-bootstrap%2F20240713/llvm-18.0.8+20240713-aarch64-apple-darwin.tar.zst",
-        "size": 136598617,
-        "sha256": "320da8d639186e020e7d54cdc35b7a5473b36cef08fdf7b22c03b59a273ba593",
-        "version": "18.0.8+20240713",
+        "url": "https://github.com/indygreg/toolchain-tools/releases/download/toolchain-bootstrap%2F20241231/llvm-19.1.6+20241231-aarch64-apple-darwin.tar.zst",
+        "size": 143884729,
+        "sha256": "c0252c7ebe0b20125fe592a12d43a693fcab0bfa3bec9def6b96b97087e0f765",
+        "version": "19.1.6+20241231",
     },
     # Remember to update LLVM_URL in src/release.rs whenever upgrading.
     "llvm-x86_64-macos": {
-        "url": "https://github.com/indygreg/toolchain-tools/releases/download/toolchain-bootstrap%2F20240713/llvm-18.0.8+20240713-x86_64-apple-darwin.tar.zst",
-        "size": 136599290,
-        "sha256": "3032161d1cadb8996b07fe5762444c956842b5a7d798b2fcfe5a04574fdf7549",
-        "version": "18.0.8+20240713",
+        "url": "https://github.com/indygreg/toolchain-tools/releases/download/toolchain-bootstrap%2F20241231/llvm-19.1.6+20241231-x86_64-apple-darwin.tar.zst",
+        "size": 143113277,
+        "sha256": "e990dea9ff89e4202d358b477a43f2bd128b244926534b7c8bb29feeaada994e",
+        "version": "19.1.6+20241231",
     },
     "m4": {
         "url": "https://ftp.gnu.org/gnu/m4/m4-1.4.19.tar.xz",
diff --git a/pythonbuild/utils.py b/pythonbuild/utils.py
index 49113a7e..7d30b2df 100644
--- a/pythonbuild/utils.py
+++ b/pythonbuild/utils.py
@@ -426,7 +426,7 @@ def clang_toolchain(host_platform: str, target_triple: str) -> str:
         if "musl" in target_triple:
             return "llvm-14-x86_64-linux"
         else:
-            return "llvm-18-x86_64-linux"
+            return "llvm-19-x86_64-linux"
     elif host_platform == "macos":
         if platform.mac_ver()[2] == "arm64":
             return "llvm-aarch64-macos"
diff --git a/src/release.rs b/src/release.rs
index cb68fe9b..1b6c56d3 100644
--- a/src/release.rs
+++ b/src/release.rs
@@ -575,14 +575,14 @@ pub fn produce_install_only_stripped(tar_gz_path: &Path, llvm_dir: &Path) -> Res
 static LLVM_URL: Lazy<Url> = Lazy::new(|| {
     if cfg!(target_os = "macos") {
         if std::env::consts::ARCH == "aarch64" {
-            Url::parse("https://github.com/indygreg/toolchain-tools/releases/download/toolchain-bootstrap%2F20240713/llvm-18.0.8+20240713-aarch64-apple-darwin.tar.zst").unwrap()
+            Url::parse("https://github.com/indygreg/toolchain-tools/releases/download/toolchain-bootstrap%2F20241231/llvm-19.1.6+20241231-aarch64-apple-darwin.tar.zst").unwrap()
         } else if std::env::consts::ARCH == "x86_64" {
-            Url::parse("https://github.com/indygreg/toolchain-tools/releases/download/toolchain-bootstrap%2F20240713/llvm-18.0.8+20240713-x86_64-apple-darwin.tar.zst").unwrap()
+            Url::parse("https://github.com/indygreg/toolchain-tools/releases/download/toolchain-bootstrap%2F20241231/llvm-19.1.6+20241231-x86_64-apple-darwin.tar.zst").unwrap()
         } else {
             panic!("unsupported macOS architecture");
         }
     } else if cfg!(target_os = "linux") {
-        Url::parse("https://github.com/indygreg/toolchain-tools/releases/download/toolchain-bootstrap%2F20240713/llvm-18.0.8+20240713-gnu_only-x86_64-unknown-linux-gnu.tar.zst").unwrap()
+        Url::parse("https://github.com/indygreg/toolchain-tools/releases/download/toolchain-bootstrap%2F20241231/llvm-19.1.6+20241231-gnu_only-x86_64-unknown-linux-gnu.tar.zst").unwrap()
     } else {
         panic!("unsupported platform");
     }

From 8b019fb706e7e1e5662f7f8733a69935e0b2f763 Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Thu, 2 Jan 2025 12:15:57 -0600
Subject: [PATCH 008/157] Bump zlib from 1.2.13 -> 1.3.1 (#357)

---
 pythonbuild/downloads.py | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/pythonbuild/downloads.py b/pythonbuild/downloads.py
index 9ef1279a..4e113c9a 100644
--- a/pythonbuild/downloads.py
+++ b/pythonbuild/downloads.py
@@ -404,10 +404,10 @@
         "license_public_domain": True,
     },
     "zlib": {
-        "url": "https://github.com/madler/zlib/releases/download/v1.2.13/zlib-1.2.13.tar.gz",
-        "size": 1497445,
-        "sha256": "b3a24de97a8fdbc835b9833169501030b8977031bcb54b3b3ac13740f846ab30",
-        "version": "1.2.13",
+        "url": "https://github.com/madler/zlib/releases/download/v1.3.1/zlib-1.3.1.tar.gz",
+        "size": 1512791,
+        "sha256": "9a93b2b7dfdac77ceba5a558a580e74667dd6fede4585b91eefb60f03b72df23",
+        "version": "1.3.1",
         "library_names": ["z"],
         "licenses": ["Zlib"],
         "license_file": "LICENSE.zlib.txt",

From eed3a7f09ede1402abe1617d83b90604a7e6f248 Mon Sep 17 00:00:00 2001
From: Gregory Szorc <gregory.szorc@gmail.com>
Date: Thu, 2 Jan 2025 22:57:10 -0800
Subject: [PATCH 009/157] unix: refresh test_embed patches to conditionally
 skip on BOLT (#469)

Turns out there is a support function to check for BOLT optimization. So
we can conditionally skip tests on BOLT.

Closes #465.
---
 cpython-unix/build-cpython.sh                          |  2 +-
 .../patch-test-embed-prevent-segfault-3.14.patch       | 10 +++++-----
 cpython-unix/patch-test-embed-prevent-segfault.patch   |  6 +++---
 3 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/cpython-unix/build-cpython.sh b/cpython-unix/build-cpython.sh
index 445726b1..1bb1e0f4 100755
--- a/cpython-unix/build-cpython.sh
+++ b/cpython-unix/build-cpython.sh
@@ -305,7 +305,7 @@ fi
 # On 3.12 (minimum BOLT version), the segfault causes the test harness to
 # abort and BOLT optimization uses the partial test results. On 3.13, the segfault
 # is a fatal error.
-if [ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_10}" ]; then
+if [ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_12}" ]; then
     patch -p1 -i ${ROOT}/patch-test-embed-prevent-segfault.patch
 fi
 
diff --git a/cpython-unix/patch-test-embed-prevent-segfault-3.14.patch b/cpython-unix/patch-test-embed-prevent-segfault-3.14.patch
index 1d75df4d..d5144086 100644
--- a/cpython-unix/patch-test-embed-prevent-segfault-3.14.patch
+++ b/cpython-unix/patch-test-embed-prevent-segfault-3.14.patch
@@ -1,12 +1,12 @@
 diff --git a/Lib/test/test_embed.py b/Lib/test/test_embed.py
-index 7110fb889f3..61e4d0f6179 100644
+index 7110fb889f3..1b55cd156d7 100644
 --- a/Lib/test/test_embed.py
 +++ b/Lib/test/test_embed.py
 @@ -940,6 +940,7 @@ def check_all_configs(self, testname, expected_config=None,
          self.check_global_config(configs)
          return configs
  
-+    @unittest.skip("segfaults on BOLT instrumented binaries")
++    @unittest.skipIf(support.check_bolt_optimized, "segfaults on BOLT instrumented binaries")
      def test_init_default_config(self):
          self.check_all_configs("test_init_initialize_config", api=API_COMPAT)
  
@@ -14,7 +14,7 @@ index 7110fb889f3..61e4d0f6179 100644
          self.check_all_configs("test_init_from_config", config, preconfig,
                                 api=API_COMPAT)
  
-+    @unittest.skip("segfaults on BOLT instrumented binaries")
++    @unittest.skipIf(support.check_bolt_optimized, "segfaults on BOLT instrumented binaries")
      def test_init_compat_env(self):
          preconfig = {
              'allocator': ALLOCATOR_FOR_CONFIG,
@@ -22,7 +22,7 @@ index 7110fb889f3..61e4d0f6179 100644
          self.check_all_configs("test_init_compat_env", config, preconfig,
                                 api=API_COMPAT)
  
-+    @unittest.skip("segfaults on BOLT instrumented binaries")
++    @unittest.skipIf(support.check_bolt_optimized, "segfaults on BOLT instrumented binaries")
      def test_init_python_env(self):
          preconfig = {
              'allocator': ALLOCATOR_FOR_CONFIG,
@@ -30,7 +30,7 @@ index 7110fb889f3..61e4d0f6179 100644
          self.check_all_configs("test_init_set_config", config,
                                 api=API_ISOLATED)
  
-+    @unittest.skip("segfaults on BOLT instrumented binaries")
++    @unittest.skipIf(support.check_bolt_optimized, "segfaults on BOLT instrumented binaries")
      def test_initconfig_api(self):
          preconfig = {
              'configure_locale': True,
diff --git a/cpython-unix/patch-test-embed-prevent-segfault.patch b/cpython-unix/patch-test-embed-prevent-segfault.patch
index fa9d9894..4eac5b28 100644
--- a/cpython-unix/patch-test-embed-prevent-segfault.patch
+++ b/cpython-unix/patch-test-embed-prevent-segfault.patch
@@ -1,12 +1,12 @@
 diff --git a/Lib/test/test_embed.py b/Lib/test/test_embed.py
-index 13713cf37b8..ba23880b15f 100644
+index 13713cf37b8..40ee4837bfe 100644
 --- a/Lib/test/test_embed.py
 +++ b/Lib/test/test_embed.py
 @@ -1615,6 +1615,7 @@ def test_getpath_abspath_win32(self):
          for (_, expected), result in zip(CASES, results):
              self.assertEqual(result, expected)
  
-+    @unittest.skip("segfaults on BOLT instrumented binaries")
++    @unittest.skipIf(support.check_bolt_optimized, "segfaults on BOLT instrumented binaries")
      def test_global_pathconfig(self):
          # Test C API functions getting the path configuration:
          #
@@ -14,7 +14,7 @@ index 13713cf37b8..ba23880b15f 100644
                  self.assertEqual(blocks, 0, out)
  
  
-+@unittest.skip("segfaults on BOLT instrumented binaries")
++@unittest.skipIf(support.check_bolt_optimized, "segfaults on BOLT instrumented binaries")
  class StdPrinterTests(EmbeddingTestsMixin, unittest.TestCase):
      # Test PyStdPrinter_Type which is used by _PySys_SetPreliminaryStderr():
      #   "Set up a preliminary stderr printer until we have enough

From e0d5d553af4a4b82db44487bbebec5a0d7996f89 Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Sat, 4 Jan 2025 00:09:29 -0600
Subject: [PATCH 010/157] Bump Docker timeout from 60s to 10m (#471)

See https://github.com/docker/docker-py/issues/2266

I'm encountering the 60s timeout copying archives in/out of images on a
slower disk.
---
 cpython-unix/build.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/cpython-unix/build.py b/cpython-unix/build.py
index f7ee174e..8122dd9a 100755
--- a/cpython-unix/build.py
+++ b/cpython-unix/build.py
@@ -933,7 +933,7 @@ def main():
         client = None
     else:
         try:
-            client = docker.from_env()
+            client = docker.from_env(timeout=600)
             client.ping()
         except Exception as e:
             print("unable to connect to Docker: %s" % e, file=sys.stderr)

From eae47c49159543d834d1560c7d95243f2a83be57 Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Sat, 4 Jan 2025 23:08:45 -0600
Subject: [PATCH 011/157] Update expected release triples for `x86_64_v4`
 (#474)

Following up on
https://github.com/astral-sh/python-build-standalone/pull/467
---
 src/release.rs | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/release.rs b/src/release.rs
index 1b6c56d3..8dc5c9f1 100644
--- a/src/release.rs
+++ b/src/release.rs
@@ -271,12 +271,12 @@ pub static RELEASE_TRIPLES: Lazy<BTreeMap<&'static str, TripleRelease>> = Lazy::
     h.insert(
         "x86_64_v4-unknown-linux-gnu",
         TripleRelease {
-            suffixes: linux_suffixes_nopgo.clone(),
-            install_only_suffix: "lto",
+            suffixes: linux_suffixes_pgo.clone(),
+            install_only_suffix: "pgo+lto",
             python_version_requirement: Some(VersionSpecifier::from_str(">=3.9").unwrap()),
             conditional_suffixes: vec![ConditionalSuffixes {
                 python_version_requirement: VersionSpecifier::from_str(">=3.13").unwrap(),
-                suffixes: linux_suffixes_nopgo_freethreaded.clone(),
+                suffixes: linux_suffixes_pgo_freethreaded.clone(),
             }],
         },
     );

From 051438c844c63cdb994c64e22018787900a23b13 Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Sat, 4 Jan 2025 23:10:01 -0600
Subject: [PATCH 012/157] Update release distribution fetch script to include
 `darwin.yml` (#475)

Following up on
https://github.com/astral-sh/python-build-standalone/pull/445
---
 src/github.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/github.rs b/src/github.rs
index 3425553e..3fce9e9c 100644
--- a/src/github.rs
+++ b/src/github.rs
@@ -122,7 +122,7 @@ pub async fn command_fetch_release_distributions(args: &ArgMatches) -> Result<()
         .filter_map(|wf| {
             if matches!(
                 wf.path.as_str(),
-                ".github/workflows/apple.yml"
+                ".github/workflows/darwin.yml"
                     | ".github/workflows/linux.yml"
                     | ".github/workflows/windows.yml"
             ) {

From 1be92c6c6d06c8395d8d2293b24d17dcac24dcd6 Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Mon, 6 Jan 2025 11:13:08 -0600
Subject: [PATCH 013/157] Update release distribution fetch script to include
 `macos.yml` (#476)

---
 src/github.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/github.rs b/src/github.rs
index 3fce9e9c..5197e775 100644
--- a/src/github.rs
+++ b/src/github.rs
@@ -122,7 +122,7 @@ pub async fn command_fetch_release_distributions(args: &ArgMatches) -> Result<()
         .filter_map(|wf| {
             if matches!(
                 wf.path.as_str(),
-                ".github/workflows/darwin.yml"
+                ".github/workflows/macos.yml"
                     | ".github/workflows/linux.yml"
                     | ".github/workflows/windows.yml"
             ) {

From b93ab5f1f159579caae845b240bcf7a003a984f3 Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Mon, 6 Jan 2025 11:13:15 -0600
Subject: [PATCH 014/157] Update release targets for x86_64 musl (#477)

---
 src/release.rs | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/src/release.rs b/src/release.rs
index 8dc5c9f1..b7c769a6 100644
--- a/src/release.rs
+++ b/src/release.rs
@@ -283,8 +283,8 @@ pub static RELEASE_TRIPLES: Lazy<BTreeMap<&'static str, TripleRelease>> = Lazy::
     h.insert(
         "x86_64-unknown-linux-musl",
         TripleRelease {
-            suffixes: linux_suffixes_nopgo.clone(),
-            install_only_suffix: "lto",
+            suffixes: linux_suffixes_pgo.clone(),
+            install_only_suffix: "pgo+lto",
             python_version_requirement: None,
             conditional_suffixes: vec![],
         },
@@ -292,8 +292,8 @@ pub static RELEASE_TRIPLES: Lazy<BTreeMap<&'static str, TripleRelease>> = Lazy::
     h.insert(
         "x86_64_v2-unknown-linux-musl",
         TripleRelease {
-            suffixes: linux_suffixes_nopgo.clone(),
-            install_only_suffix: "lto",
+            suffixes: linux_suffixes_pgo.clone(),
+            install_only_suffix: "pgo+lto",
             python_version_requirement: Some(VersionSpecifier::from_str(">=3.9").unwrap()),
             conditional_suffixes: vec![],
         },
@@ -301,8 +301,8 @@ pub static RELEASE_TRIPLES: Lazy<BTreeMap<&'static str, TripleRelease>> = Lazy::
     h.insert(
         "x86_64_v3-unknown-linux-musl",
         TripleRelease {
-            suffixes: linux_suffixes_nopgo.clone(),
-            install_only_suffix: "lto",
+            suffixes: linux_suffixes_pgo.clone(),
+            install_only_suffix: "pgo+lto",
             python_version_requirement: Some(VersionSpecifier::from_str(">=3.9").unwrap()),
             conditional_suffixes: vec![],
         },
@@ -310,8 +310,8 @@ pub static RELEASE_TRIPLES: Lazy<BTreeMap<&'static str, TripleRelease>> = Lazy::
     h.insert(
         "x86_64_v4-unknown-linux-musl",
         TripleRelease {
-            suffixes: linux_suffixes_nopgo.clone(),
-            install_only_suffix: "lto",
+            suffixes: linux_suffixes_pgo.clone(),
+            install_only_suffix: "pgo+lto",
             python_version_requirement: Some(VersionSpecifier::from_str(">=3.9").unwrap()),
             conditional_suffixes: vec![],
         },

From 3a8ea4a9b34474aa31343311ae2b95288208cc39 Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Mon, 6 Jan 2025 11:17:37 -0600
Subject: [PATCH 015/157] Drop 3.14 from expected Windows release targets
 (#478)

---
 src/release.rs | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/src/release.rs b/src/release.rs
index b7c769a6..99d2b07c 100644
--- a/src/release.rs
+++ b/src/release.rs
@@ -105,12 +105,13 @@ pub static RELEASE_TRIPLES: Lazy<BTreeMap<&'static str, TripleRelease>> = Lazy::
     );
 
     // Windows.
+    // TODO: Python 3.14 support on Windows
     h.insert(
         "i686-pc-windows-msvc",
         TripleRelease {
             suffixes: vec!["pgo"],
             install_only_suffix: "pgo",
-            python_version_requirement: None,
+            python_version_requirement: Some(VersionSpecifier::from_str("<3.14").unwrap()),
             conditional_suffixes: vec![ConditionalSuffixes {
                 python_version_requirement: VersionSpecifier::from_str(">=3.13").unwrap(),
                 suffixes: vec!["freethreaded+pgo"],
@@ -122,7 +123,7 @@ pub static RELEASE_TRIPLES: Lazy<BTreeMap<&'static str, TripleRelease>> = Lazy::
         TripleRelease {
             suffixes: vec!["pgo"],
             install_only_suffix: "pgo",
-            python_version_requirement: None,
+            python_version_requirement: Some(VersionSpecifier::from_str("<3.14").unwrap()),
             conditional_suffixes: vec![ConditionalSuffixes {
                 python_version_requirement: VersionSpecifier::from_str(">=3.13").unwrap(),
                 suffixes: vec!["freethreaded+pgo"],
@@ -137,7 +138,7 @@ pub static RELEASE_TRIPLES: Lazy<BTreeMap<&'static str, TripleRelease>> = Lazy::
         TripleRelease {
             suffixes: vec!["pgo"],
             install_only_suffix: "pgo",
-            python_version_requirement: None,
+            python_version_requirement: Some(VersionSpecifier::from_str("<3.14").unwrap()),
             conditional_suffixes: vec![ConditionalSuffixes {
                 python_version_requirement: VersionSpecifier::from_str(">=3.13").unwrap(),
                 suffixes: vec!["freethreaded+pgo"],
@@ -149,7 +150,7 @@ pub static RELEASE_TRIPLES: Lazy<BTreeMap<&'static str, TripleRelease>> = Lazy::
         TripleRelease {
             suffixes: vec!["pgo"],
             install_only_suffix: "pgo",
-            python_version_requirement: None,
+            python_version_requirement: Some(VersionSpecifier::from_str("<3.14").unwrap()),
             conditional_suffixes: vec![ConditionalSuffixes {
                 python_version_requirement: VersionSpecifier::from_str(">=3.13").unwrap(),
                 suffixes: vec!["freethreaded+pgo"],

From ddf4de0d8356fdea16b8b872bdb8797535701537 Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Mon, 6 Jan 2025 11:34:02 -0600
Subject: [PATCH 016/157] Fix musl Linux release targets (#479)

- **Revert "Update release targets for x86_64 musl (#477)"**
- **Drop 3.14 from expected musl Linux release targets**
---
 src/release.rs | 25 +++++++++++++------------
 1 file changed, 13 insertions(+), 12 deletions(-)

diff --git a/src/release.rs b/src/release.rs
index 99d2b07c..e67a114f 100644
--- a/src/release.rs
+++ b/src/release.rs
@@ -281,39 +281,40 @@ pub static RELEASE_TRIPLES: Lazy<BTreeMap<&'static str, TripleRelease>> = Lazy::
             }],
         },
     );
+    // TODO: Python 3.14 support on musl
     h.insert(
         "x86_64-unknown-linux-musl",
         TripleRelease {
-            suffixes: linux_suffixes_pgo.clone(),
-            install_only_suffix: "pgo+lto",
-            python_version_requirement: None,
+            suffixes: linux_suffixes_nopgo.clone(),
+            install_only_suffix: "lto",
+            python_version_requirement: Some(VersionSpecifier::from_str("<3.14").unwrap()),
             conditional_suffixes: vec![],
         },
     );
     h.insert(
         "x86_64_v2-unknown-linux-musl",
         TripleRelease {
-            suffixes: linux_suffixes_pgo.clone(),
-            install_only_suffix: "pgo+lto",
-            python_version_requirement: Some(VersionSpecifier::from_str(">=3.9").unwrap()),
+            suffixes: linux_suffixes_nopgo.clone(),
+            install_only_suffix: "lto",
+            python_version_requirement: Some(VersionSpecifier::from_str("<3.14").unwrap()),
             conditional_suffixes: vec![],
         },
     );
     h.insert(
         "x86_64_v3-unknown-linux-musl",
         TripleRelease {
-            suffixes: linux_suffixes_pgo.clone(),
-            install_only_suffix: "pgo+lto",
-            python_version_requirement: Some(VersionSpecifier::from_str(">=3.9").unwrap()),
+            suffixes: linux_suffixes_nopgo.clone(),
+            install_only_suffix: "lto",
+            python_version_requirement: Some(VersionSpecifier::from_str("<3.14").unwrap()),
             conditional_suffixes: vec![],
         },
     );
     h.insert(
         "x86_64_v4-unknown-linux-musl",
         TripleRelease {
-            suffixes: linux_suffixes_pgo.clone(),
-            install_only_suffix: "pgo+lto",
-            python_version_requirement: Some(VersionSpecifier::from_str(">=3.9").unwrap()),
+            suffixes: linux_suffixes_nopgo.clone(),
+            install_only_suffix: "lto",
+            python_version_requirement: Some(VersionSpecifier::from_str("<3.14").unwrap()),
             conditional_suffixes: vec![],
         },
     );

From 19c27b3e87cdacd03e353220e533bbe893a5c906 Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Mon, 6 Jan 2025 13:16:58 -0600
Subject: [PATCH 017/157] Update comments in release workflow (#480)

---
 .github/workflows/release.yml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index d4abfd97..3faca6ac 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -4,13 +4,13 @@ on:
   workflow_dispatch:
     inputs:
       tag:
-        description: "The version to release (e.g., '20240414')."
+        description: "The version to release (e.g., '20250414')."
         type: string
       sha:
         description: "The full SHA of the commit to be released (e.g., 'd09ff921d92d6da8d8a608eaa850dc8c0f638194')."
         type: string
       dry-run:
-        description: "Whether to run the release process without actually releasing."
+        description: "Dry run? Tests the release process without publishing."
         default: false
         required: false
         type: boolean

From 3c4fe233ae1ffa9b17a52546a423e146f14ea54f Mon Sep 17 00:00:00 2001
From: Gregory Szorc <gregory.szorc@gmail.com>
Date: Mon, 6 Jan 2025 11:17:09 -0800
Subject: [PATCH 018/157] unix: upgrade libedit 20210910-3.1 -> 20240808-3.1
 (#466)

We were soft blocked on upgrading due to musl compatibility issues.

It looks like these got fixed upstream. So we refreshed the configure
patch and libedit build _just worked_.

However, Python 3.9 and 3.10 encountered compile errors with the
newer version.

On 3.10 we worked around this bug by backporting a patch from 3.11.
On 3.9, the backport was non-trivial, so I just hacked up the existing
3.9 patch to manually change some C preprocessor checks to key off
libedit.

While diffing `Modules/readline.c` I found another patch related to
fixing completer delims. While strictly not required, it was trivial
to backport to 3.10 to fix some missing functionality. So I did.

3.13 initially didn't like the upgraded libedit because
we were manually defining a preprocessor variable (introduced in 3.13
by upstream commit 8515fd79fef1ac16d7848cec5ec1797294cb5366). Removing
the variable and letting configure deduce things with the newer libedit
appears to _just work_. Perhaps upstream configure doesn't implement
the feature detection properly on older libedit versions?
---
 cpython-unix/build-cpython.sh                 | 28 +++++++-
 cpython-unix/build-libedit.sh                 | 52 +++++++-------
 cpython-unix/extension-modules.yml            |  2 -
 ...ch-readline-libedit-completer-delims.patch | 72 +++++++++++++++++++
 .../patch-readline-libedit-completions.patch  | 52 ++++++++++++++
 cpython-unix/patch-readline-libedit.patch     | 28 ++++++--
 pythonbuild/downloads.py                      |  9 ++-
 7 files changed, 204 insertions(+), 39 deletions(-)
 create mode 100644 cpython-unix/patch-readline-libedit-completer-delims.patch
 create mode 100644 cpython-unix/patch-readline-libedit-completions.patch

diff --git a/cpython-unix/build-cpython.sh b/cpython-unix/build-cpython.sh
index 1bb1e0f4..bd9c7bc7 100755
--- a/cpython-unix/build-cpython.sh
+++ b/cpython-unix/build-cpython.sh
@@ -221,9 +221,17 @@ if [ -n "${PYTHON_MEETS_MAXIMUM_VERSION_3_9}" ]; then
     patch -p1 -i ${ROOT}/patch-decimal-modern-mpdecimal.patch
 fi
 
+# We build against libedit instead of readline in all environments.
+#
+# On macOS, we use the system/SDK libedit, which is likely somewhat old.
+#
+# On Linux, we use our own libedit, which should be modern.
+#
 # CPython 3.10 added proper support for building against libedit outside of
-# macOS. On older versions, we need to patch readline.c.
-if [ -n "${PYTHON_MEETS_MAXIMUM_VERSION_3_9}" ]; then
+# macOS. On older versions, we need to hack up readline.c to build against
+# libedit. This patch breaks older libedit (as seen on macOS) so don't apply
+# on macOS.
+if [[ -n "${PYTHON_MEETS_MAXIMUM_VERSION_3_9}" && "${PYBUILD_PLATFORM}" != "macos" ]]; then
     # readline.c assumes that a modern readline API version has a free_history_entry().
     # but libedit does not. Change the #ifdef accordingly.
     #
@@ -231,9 +239,25 @@ if [ -n "${PYTHON_MEETS_MAXIMUM_VERSION_3_9}" ]; then
     # HAVE_RL_COMPLETION_SUPPRESS_APPEND improperly. So hack that. This is a bug
     # in our build system, as we should probably be invoking configure again when
     # using libedit.
+    #
+    # Similar workaround for on_completion_display_matches_hook.
     patch -p1 -i ${ROOT}/patch-readline-libedit.patch
 fi
 
+if [ "${PYTHON_MAJMIN_VERSION}" = "3.10" ]; then
+    # Even though 3.10 is libedit aware, it isn't compatible with newer
+    # versions of libedit. We need to backport a 3.11 patch to teach the
+    # build system about completions.
+    # Backport of 9e9df93ffc6df5141843caf651d33d446676a414 from 3.11.
+    patch -p1 -i ${ROOT}/patch-readline-libedit-completions.patch
+
+    # 3.11 has a patch related to completer delims that closes a feature
+    # gap. Backport it as a quality of life enhancement.
+    #
+    # Backport of 42dd2613fe4bc61e1f633078560f2d84a0a16c3f from 3.11.
+    patch -p1 -i ${ROOT}/patch-readline-libedit-completer-delims.patch
+fi
+
 # iOS doesn't have system(). Teach posixmodule.c about that.
 # Python 3.11 makes this a configure time check, so we don't need the patch there.
 if [[ -n "${PYTHON_MEETS_MAXIMUM_VERSION_3_10}" ]]; then
diff --git a/cpython-unix/build-libedit.sh b/cpython-unix/build-libedit.sh
index f0f55d5e..08387ece 100755
--- a/cpython-unix/build-libedit.sh
+++ b/cpython-unix/build-libedit.sh
@@ -19,13 +19,13 @@ pushd libedit-${LIBEDIT_VERSION}
 # run-time. So we hack up the configure script instead.
 patch -p1 << "EOF"
 diff --git a/configure b/configure
-index 26dd8d0..4b6d47c 100755
+index 614795f..4671f1b 100755
 --- a/configure
 +++ b/configure
-@@ -12921,14 +12921,14 @@ test -n "$NROFF" || NROFF="/bin/false"
- 
- 
- 
+@@ -14154,14 +14154,14 @@ test -n "$NROFF" || NROFF="/bin/false"
+
+
+
 -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for tgetent in -lncurses" >&5
 -printf %s "checking for tgetent in -lncurses... " >&6; }
 -if test ${ac_cv_lib_ncurses_tgetent+y}
@@ -34,26 +34,28 @@ index 26dd8d0..4b6d47c 100755
 +if test ${ac_cv_lib_ncursesw_tgetent+y}
  then :
    printf %s "(cached) " >&6
- else $as_nop
-   ac_check_lib_save_LIBS=$LIBS
+ else case e in #(
+   e) ac_check_lib_save_LIBS=$LIBS
 -LIBS="-lncurses  $LIBS"
 +LIBS="-lncursesw  $LIBS"
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
  /* end confdefs.h.  */
- 
-@@ -12946,21 +12946,21 @@ return tgetent ();
+
+@@ -14185,9 +14185,9 @@ return tgetent ();
  _ACEOF
  if ac_fn_c_try_link "$LINENO"
  then :
 -  ac_cv_lib_ncurses_tgetent=yes
 +  ac_cv_lib_ncursesw_tgetent=yes
- else $as_nop
--  ac_cv_lib_ncurses_tgetent=no
-+  ac_cv_lib_ncursesw_tgetent=no
+ else case e in #(
+-  e) ac_cv_lib_ncurses_tgetent=no ;;
++  e) ac_cv_lib_ncursesw_tgetent=no ;;
+ esac
  fi
  rm -f core conftest.err conftest.$ac_objext conftest.beam \
-     conftest$ac_exeext conftest.$ac_ext
- LIBS=$ac_check_lib_save_LIBS
+@@ -14195,13 +14195,13 @@ rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ LIBS=$ac_check_lib_save_LIBS ;;
+ esac
  fi
 -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ncurses_tgetent" >&5
 -printf "%s\n" "$ac_cv_lib_ncurses_tgetent" >&6; }
@@ -63,21 +65,21 @@ index 26dd8d0..4b6d47c 100755
 +if test "x$ac_cv_lib_ncursesw_tgetent" = xyes
  then :
    printf "%s\n" "#define HAVE_LIBNCURSES 1" >>confdefs.h
- 
+
 -  LIBS="-lncurses $LIBS"
 +  LIBS="-lncursesw $LIBS"
- 
- else $as_nop
-   { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for tgetent in -lcurses" >&5
-@@ -13089,7 +13089,7 @@ then :
+
+ else case e in #(
+   e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for tgetent in -lcurses" >&5
+@@ -14354,7 +14354,7 @@ then :
    LIBS="-ltinfo $LIBS"
- 
- else $as_nop
--  as_fn_error $? "libncurses, libcurses, libtermcap or libtinfo is required!" "$LINENO" 5
-+  as_fn_error $? "libncursesw, libcurses, libtermcap or libtinfo is required!" "$LINENO" 5
- 
+
+ else case e in #(
+-  e) as_fn_error $? "libncurses, libcurses, libtermcap or libtinfo is required!" "$LINENO" 5
++  e) as_fn_error $? "libncursesw, libcurses, libtermcap or libtinfo is required!" "$LINENO" 5
+        ;;
+ esac
  fi
- 
 EOF
 
 cflags="${EXTRA_TARGET_CFLAGS} -fPIC -I${TOOLS_PATH}/deps/include -I${TOOLS_PATH}/deps/include/ncursesw"
diff --git a/cpython-unix/extension-modules.yml b/cpython-unix/extension-modules.yml
index d7d3f5a8..6a17cb87 100644
--- a/cpython-unix/extension-modules.yml
+++ b/cpython-unix/extension-modules.yml
@@ -880,8 +880,6 @@ readline:
     - readline.c
   defines:
     - USE_LIBEDIT=1
-    # While some versions do not, our readline `on_startup_hook` takes arguments.
-    - Py_RL_STARTUP_HOOK_TAKES_ARGS
   includes-deps:
     - libedit/include
     - libedit/include/ncursesw
diff --git a/cpython-unix/patch-readline-libedit-completer-delims.patch b/cpython-unix/patch-readline-libedit-completer-delims.patch
new file mode 100644
index 00000000..0a52a649
--- /dev/null
+++ b/cpython-unix/patch-readline-libedit-completer-delims.patch
@@ -0,0 +1,72 @@
+diff --git a/Lib/test/test_readline.py b/Lib/test/test_readline.py
+index 835280f2281..6c2726d3209 100644
+--- a/Lib/test/test_readline.py
++++ b/Lib/test/test_readline.py
+@@ -5,6 +5,7 @@
+ import os
+ import sys
+ import tempfile
++import textwrap
+ import unittest
+ from test.support import verbose
+ from test.support.import_helper import import_module
+@@ -163,6 +164,25 @@ def test_auto_history_disabled(self):
+         # end, so don't expect it in the output.
+         self.assertIn(b"History length: 0", output)
+ 
++    def test_set_complete_delims(self):
++        script = textwrap.dedent("""
++            import readline
++            def complete(text, state):
++                if state == 0 and text == "$":
++                    return "$complete"
++                return None
++            if "libedit" in getattr(readline, "__doc__", ""):
++                readline.parse_and_bind(r'bind "\\t" rl_complete')
++            else:
++                readline.parse_and_bind(r'"\\t": complete')
++            readline.set_completer_delims(" \\t\\n")
++            readline.set_completer(complete)
++            print(input())
++        """)
++
++        output = run_pty(script, input=b"$\t\n")
++        self.assertIn(b"$complete", output)
++
+     def test_nonascii(self):
+         loc = locale.setlocale(locale.LC_CTYPE, None)
+         if loc in ('C', 'POSIX'):
+diff --git a/Modules/readline.c b/Modules/readline.c
+index 8c7f526d418..1e13a0e6e06 100644
+--- a/Modules/readline.c
++++ b/Modules/readline.c
+@@ -572,6 +572,13 @@ readline_set_completer_delims(PyObject *module, PyObject *string)
+     if (break_chars) {
+         free(completer_word_break_characters);
+         completer_word_break_characters = break_chars;
++#ifdef WITH_EDITLINE
++        rl_basic_word_break_characters = break_chars;
++#else
++        if (using_libedit_emulation) {
++            rl_basic_word_break_characters = break_chars;
++        }
++#endif
+         rl_completer_word_break_characters = break_chars;
+         Py_RETURN_NONE;
+     }
+@@ -1260,6 +1267,15 @@ setup_readline(readlinestate *mod_state)
+     completer_word_break_characters =
+         strdup(" \t\n`~!@#$%^&*()-=+[{]}\\|;:'\",<>/?");
+         /* All nonalphanums except '.' */
++#ifdef WITH_EDITLINE
++    // libedit uses rl_basic_word_break_characters instead of
++    // rl_completer_word_break_characters as complete delimiter
++    rl_basic_word_break_characters = completer_word_break_characters;
++#else
++    if (using_libedit_emulation) {
++        rl_basic_word_break_characters = completer_word_break_characters;
++    }
++#endif
+     rl_completer_word_break_characters = completer_word_break_characters;
+ 
+     mod_state->begidx = PyLong_FromLong(0L);
diff --git a/cpython-unix/patch-readline-libedit-completions.patch b/cpython-unix/patch-readline-libedit-completions.patch
new file mode 100644
index 00000000..b4c83939
--- /dev/null
+++ b/cpython-unix/patch-readline-libedit-completions.patch
@@ -0,0 +1,52 @@
+diff --git a/Modules/readline.c b/Modules/readline.c
+index 27b89de7279..8c7f526d418 100644
+--- a/Modules/readline.c
++++ b/Modules/readline.c
+@@ -440,7 +440,7 @@ readline_set_completion_display_matches_hook_impl(PyObject *module,
+        default completion display. */
+     rl_completion_display_matches_hook =
+         readlinestate_global->completion_display_matches_hook ?
+-#if defined(_RL_FUNCTION_TYPEDEF)
++#if defined(HAVE_RL_COMPDISP_FUNC_T)
+         (rl_compdisp_func_t *)on_completion_display_matches_hook : 0;
+ #else
+         (VFunction *)on_completion_display_matches_hook : 0;
+diff --git a/configure.ac b/configure.ac
+index e1cbb7c7fbe..629b7b76c3c 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -5918,6 +5918,20 @@ if test "$py_cv_lib_readline" = yes; then
+   AC_CHECK_LIB($LIBREADLINE, append_history,
+     AC_DEFINE(HAVE_RL_APPEND_HISTORY, 1,
+       [Define if readline supports append_history]),,$READLINE_LIBS)
++
++  # in readline as well as newer editline (April 2023)
++  AC_CHECK_TYPE([rl_compdisp_func_t],
++                [AC_DEFINE([HAVE_RL_COMPDISP_FUNC_T], [1],
++                           [Define if readline supports rl_compdisp_func_t])],
++                [],
++                [
++#include <stdio.h> /* Must be first for Gnu Readline */
++#ifdef WITH_EDITLINE
++# include <editline/readline.h>
++#else
++# include <readline/readline.h>
++#endif
++                ])
+ fi
+ 
+ # End of readline checks: restore LIBS
+diff --git a/pyconfig.h.in b/pyconfig.h.in
+index 0536047f573..94d02e14c44 100644
+--- a/pyconfig.h.in
++++ b/pyconfig.h.in
+@@ -968,6 +968,9 @@
+ /* Define if you can turn off readline's signal handling. */
+ #undef HAVE_RL_CATCH_SIGNAL
+ 
++/* Define if readline supports rl_compdisp_func_t */
++#undef HAVE_RL_COMPDISP_FUNC_T
++
+ /* Define if you have readline 2.2 */
+ #undef HAVE_RL_COMPLETION_APPEND_CHARACTER
+ 
diff --git a/cpython-unix/patch-readline-libedit.patch b/cpython-unix/patch-readline-libedit.patch
index 1c450280..534f9a45 100644
--- a/cpython-unix/patch-readline-libedit.patch
+++ b/cpython-unix/patch-readline-libedit.patch
@@ -1,14 +1,32 @@
 diff --git a/Modules/readline.c b/Modules/readline.c
-index 1e74f997b0..56a36e26e6 100644
+index 1e74f997b07..0c982857283 100644
 --- a/Modules/readline.c
 +++ b/Modules/readline.c
+@@ -35,7 +35,7 @@
+ #define completion_matches(x, y) \
+     rl_completion_matches((x), ((rl_compentry_func_t *)(y)))
+ #else
+-#if defined(_RL_FUNCTION_TYPEDEF)
++#ifdef USE_LIBEDIT
+ extern char **completion_matches(char *, rl_compentry_func_t *);
+ #else
+ 
+@@ -390,7 +390,7 @@ set_completion_display_matches_hook(PyObject *self, PyObject *args)
+        default completion display. */
+     rl_completion_display_matches_hook =
+         readlinestate_global->completion_display_matches_hook ?
+-#if defined(_RL_FUNCTION_TYPEDEF)
++#ifdef USE_LIBEDIT
+         (rl_compdisp_func_t *)on_completion_display_matches_hook : 0;
+ #else
+         (VFunction *)on_completion_display_matches_hook : 0;
 @@ -511,7 +511,7 @@ set the word delimiters for completion");
-
+ 
  /* _py_free_history_entry: Utility function to free a history entry. */
-
+ 
 -#if defined(RL_READLINE_VERSION) && RL_READLINE_VERSION >= 0x0500
 +#ifndef USE_LIBEDIT
-
+ 
  /* Readline version >= 5.0 introduced a timestamp field into the history entry
     structure; this needs to be freed to avoid a memory leak.  This version of
 @@ -1055,7 +1055,7 @@ flex_complete(const char *text, int start, int end)
@@ -19,7 +37,7 @@ index 1e74f997b0..56a36e26e6 100644
 +#ifndef USE_LIBEDIT
      rl_completion_suppress_append = 0;
  #endif
-
+ 
 @@ -1241,7 +1241,7 @@ readline_until_enter_or_signal(const char *prompt, int *signal)
              PyEval_SaveThread();
              if (s < 0) {
diff --git a/pythonbuild/downloads.py b/pythonbuild/downloads.py
index 4e113c9a..e3e1a1ba 100644
--- a/pythonbuild/downloads.py
+++ b/pythonbuild/downloads.py
@@ -115,12 +115,11 @@
         "sha256": "828cb275b91268b1a3ea950d5c0c5eb076c678fdf005d517411f89cc8c3bb416",
         "version": "1.0.7",
     },
-    # 20221009-3.1 fails to build on musl due to an includes issue.
     "libedit": {
-        "url": "https://thrysoee.dk/editline/libedit-20210910-3.1.tar.gz",
-        "size": 524722,
-        "sha256": "6792a6a992050762edcca28ff3318cdb7de37dccf7bc30db59fcd7017eed13c5",
-        "version": "20210910-3.1",
+        "url": "https://thrysoee.dk/editline/libedit-20240808-3.1.tar.gz",
+        "size": 538611,
+        "sha256": "5f0573349d77c4a48967191cdd6634dd7aa5f6398c6a57fe037cc02696d6099f",
+        "version": "20240808-3.1",
         "library_names": ["edit"],
         "licenses": ["BSD-3-Clause"],
         "license_file": "LICENSE.libedit.txt",

From ec55e88efbdd1cdb35f8e6b2a388af35e9d16b1d Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Tue, 7 Jan 2025 16:57:35 -0600
Subject: [PATCH 019/157] Generate CI runners for build matrix dynamically
 (#483)

---
 .github/workflows/linux.yml   |  2 +-
 .github/workflows/macos.yml   |  2 +-
 .github/workflows/windows.yml |  2 +-
 ci-matrix.py                  | 50 +++++++++++++++++++++++++++++++++--
 ci-runners.yaml               | 37 ++++++++++++++++++++++++++
 5 files changed, 88 insertions(+), 5 deletions(-)
 create mode 100644 ci-runners.yaml

diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml
index f2bf45fb..901233ad 100644
--- a/.github/workflows/linux.yml
+++ b/.github/workflows/linux.yml
@@ -168,7 +168,7 @@ jobs:
       - generate-matrix
       - pythonbuild
       - image
-    runs-on: depot-ubuntu-22.04
+    runs-on: ${{ matrix.runner }}
     strategy:
       matrix: ${{ fromJson(needs.generate-matrix.outputs.matrix) }}
       fail-fast: false
diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml
index 122202e8..7aafefa9 100644
--- a/.github/workflows/macos.yml
+++ b/.github/workflows/macos.yml
@@ -90,7 +90,7 @@ jobs:
     strategy:
       matrix: ${{ fromJson(needs.generate-matrix.outputs.matrix) }}
       fail-fast: false
-    runs-on: depot-macos-latest
+    runs-on: ${{ matrix.runner }}
     name: ${{ matrix.target_triple }} / ${{ matrix.python }} / ${{ matrix.build_options }}
     steps:
       - uses: actions/checkout@v4
diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml
index 3d5a7bd0..c625b410 100644
--- a/.github/workflows/windows.yml
+++ b/.github/workflows/windows.yml
@@ -88,7 +88,7 @@ jobs:
     needs:
       - generate-matrix
       - pythonbuild
-    runs-on: windows-latest-large
+    runs-on: ${{ matrix.runner }}
     strategy:
       matrix: ${{ fromJson(needs.generate-matrix.outputs.matrix) }}
       fail-fast: false
diff --git a/ci-matrix.py b/ci-matrix.py
index 21363cc2..e9b882fa 100644
--- a/ci-matrix.py
+++ b/ci-matrix.py
@@ -14,6 +14,7 @@
 from packaging.version import Version
 
 CI_TARGETS_YAML = "ci-targets.yaml"
+CI_RUNNERS_YAML = "ci-runners.yaml"
 CI_EXTRA_SKIP_LABELS = ["documentation"]
 
 
@@ -88,6 +89,7 @@ def should_include_entry(entry: dict[str, str], filters: dict[str, set[str]]) ->
 
 def generate_matrix_entries(
     config: dict[str, Any],
+    runners: dict[str, Any],
     platform_filter: Optional[str] = None,
     label_filters: Optional[dict[str, set[str]]] = None,
 ) -> list[dict[str, str]]:
@@ -103,6 +105,7 @@ def generate_matrix_entries(
                 target_triple,
                 target_config,
                 platform,
+                runners,
                 label_filters.get("directives", set()),
             )
 
@@ -117,22 +120,50 @@ def generate_matrix_entries(
     return matrix_entries
 
 
+def find_runner(runners: dict[str, Any], platform: str, arch: str) -> str:
+    # Find a matching platform first
+    match_platform = [
+        runner for runner in runners if runners[runner]["platform"] == platform
+    ]
+
+    # Then, find a matching architecture
+    match_arch = [
+        runner for runner in match_platform if runners[runner]["arch"] == arch
+    ]
+
+    # If there's a matching architecture, use that
+    if match_arch:
+        return match_arch[0]
+
+    # Otherwise, use the first with a matching platform
+    if match_platform:
+        return match_platform[0]
+
+    raise RuntimeError(f"No runner found for platform {platform!r} and arch {arch!r}")
+
+
 def add_matrix_entries_for_config(
     matrix_entries: list[dict[str, str]],
     target_triple: str,
     config: dict[str, Any],
     platform: str,
+    runners: dict[str, Any],
     directives: set[str],
 ) -> None:
     python_versions = config["python_versions"]
     build_options = config["build_options"]
     arch = config["arch"]
+    runner = find_runner(runners, platform, arch)
 
     # Create base entry that will be used for all variants
     base_entry = {
         "arch": arch,
         "target_triple": target_triple,
         "platform": platform,
+        "runner": runner,
+        # If `run` is in the config, use that — otherwise, default to if the
+        # runner architecture matches the build architecture
+        "run": str(config.get("run", runners[runner]["arch"] == arch)).lower(),
     }
 
     # Add optional fields if they exist
@@ -142,8 +173,6 @@ def add_matrix_entries_for_config(
         base_entry["libc"] = config["libc"]
     if "vcvars" in config:
         base_entry["vcvars"] = config["vcvars"]
-    if "run" in config:
-        base_entry["run"] = str(config["run"]).lower()
 
     if "dry-run" in directives:
         base_entry["dry-run"] = "true"
@@ -191,6 +220,11 @@ def parse_args() -> argparse.Namespace:
         "--labels",
         help="Comma-separated list of labels to filter by (e.g., 'platform:darwin,python:3.13,build:debug'), all must match.",
     )
+    parser.add_argument(
+        "--free-runners",
+        action="store_true",
+        help="If only free runners should be used.",
+    )
     return parser.parse_args()
 
 
@@ -201,9 +235,21 @@ def main() -> None:
     with open(CI_TARGETS_YAML, "r") as f:
         config = yaml.safe_load(f)
 
+    with open(CI_RUNNERS_YAML, "r") as f:
+        runners = yaml.safe_load(f)
+
+    # If only free runners are allowed, reduce to a subset
+    if args.free_runners:
+        runners = {
+            runner: runner_config
+            for runner, runner_config in runners.items()
+            if runner_config.get("free")
+        }
+
     matrix = {
         "include": generate_matrix_entries(
             config,
+            runners,
             args.platform,
             labels,
         )
diff --git a/ci-runners.yaml b/ci-runners.yaml
new file mode 100644
index 00000000..aeb0e5ca
--- /dev/null
+++ b/ci-runners.yaml
@@ -0,0 +1,37 @@
+# Describes the runners that the CI system can use
+
+depot-ubuntu-22.04:
+  arch: x86_64
+  platform: linux
+  free: false
+
+# TODO: Enable this runner to perform native builds for aarch64
+# depot-ubuntu-22.04-arm:
+#   arch: aarch64
+#   platform: linux
+#   free: false
+
+depot-macos-latest:
+  arch: x86_64
+  platform: darwin
+  free: false
+
+ubuntu-latest:
+  arch: x86_64
+  platform: linux
+  free: true
+
+macos-latest:
+  arch: x86_64
+  platform: darwin
+  free: true
+
+windows-latest-large:
+  arch: x86_64
+  platform: windows
+  free: false
+
+windows-latest:
+  arch: x86_64
+  platform: windows
+  free: true

From 37e228370bd64b52552786088e6a586a25a4acec Mon Sep 17 00:00:00 2001
From: Kilian Hu <90606809+kilian-hu@users.noreply.github.com>
Date: Wed, 8 Jan 2025 00:00:37 +0100
Subject: [PATCH 020/157] Fix x86_64-apple-darwin comment in targets.yml (#482)

Hi all,

just fixing an outdated comment about the min macOS version for the
`x86_64-apple-darwin` target.

Thanks for maintaining this project!
---
 cpython-unix/targets.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/cpython-unix/targets.yml b/cpython-unix/targets.yml
index a442cc87..64683ec6 100644
--- a/cpython-unix/targets.yml
+++ b/cpython-unix/targets.yml
@@ -552,7 +552,7 @@ thumb7k-apple-watchos:
 
 # Intel macOS.
 #
-# We target compatibility with macOS 10.9+ for compatibility with older Apple
+# We target compatibility with macOS 10.15+ for compatibility with older Apple
 # machines.
 x86_64-apple-darwin:
   host_platforms:

From 8999425c1ab1e8e00763404eb4309cdd0c7d3e52 Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Tue, 7 Jan 2025 22:57:27 -0600
Subject: [PATCH 021/157] Upgrade Python build environment requirements (#472)

Using `uv` instead of `pip-compile` so I can cross-compile the Windows
requirements, upgrades the Python dependency lock files.
---
 requirements.dev.txt | 898 ++++++++++++++++++++++-------------------
 requirements.txt     | 922 ++++++++++++++++++++++---------------------
 requirements.win.txt |  88 +----
 3 files changed, 984 insertions(+), 924 deletions(-)
 mode change 100755 => 100644 requirements.win.txt

diff --git a/requirements.dev.txt b/requirements.dev.txt
index 59d649bc..dfeb2887 100644
--- a/requirements.dev.txt
+++ b/requirements.dev.txt
@@ -1,201 +1,200 @@
-#
-# This file is autogenerated by pip-compile with Python 3.12
-# by the following command:
-#
-#    pip-compile --generate-hashes requirements.dev.in
-#
-attrs==23.2.0 \
-    --hash=sha256:935dc3b529c262f6cf76e50877d35a4bd3c1de194fd41f47a2b7ae8f19971f30 \
-    --hash=sha256:99b87a485a5820b23b879f04c2305b44b951b502fd64be915879d77a7e8fc6f1
+# This file was autogenerated by uv via the following command:
+#    uv pip compile --generate-hashes requirements.dev.in -o requirements.dev.txt
+attrs==24.3.0 \
+    --hash=sha256:8f5c07333d543103541ba7be0e2ce16eeee8130cb0b3f9238ab904ce1e85baff \
+    --hash=sha256:ac96cd038792094f438ad1f6ff80837353805ac950cd2aa0e0625ef19850c308
     # via
     #   -r requirements.txt
     #   jsonschema
     #   referencing
-certifi==2024.2.2 \
-    --hash=sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f \
-    --hash=sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1
+certifi==2024.12.14 \
+    --hash=sha256:1275f7a45be9464efc1173084eaa30f866fe2e47d389406136d332ed4967ec56 \
+    --hash=sha256:b650d30f370c2b724812bee08008be0c4163b163ddaec3f2546c1caf65f191db
     # via
     #   -r requirements.txt
     #   requests
-charset-normalizer==3.3.2 \
-    --hash=sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027 \
-    --hash=sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087 \
-    --hash=sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786 \
-    --hash=sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8 \
-    --hash=sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09 \
-    --hash=sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185 \
-    --hash=sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574 \
-    --hash=sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e \
-    --hash=sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519 \
-    --hash=sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898 \
-    --hash=sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269 \
-    --hash=sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3 \
-    --hash=sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f \
-    --hash=sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6 \
-    --hash=sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8 \
-    --hash=sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a \
-    --hash=sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73 \
-    --hash=sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc \
-    --hash=sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714 \
-    --hash=sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2 \
-    --hash=sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc \
-    --hash=sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce \
-    --hash=sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d \
-    --hash=sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e \
-    --hash=sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6 \
-    --hash=sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269 \
-    --hash=sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96 \
-    --hash=sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d \
-    --hash=sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a \
-    --hash=sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4 \
-    --hash=sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77 \
-    --hash=sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d \
-    --hash=sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0 \
-    --hash=sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed \
-    --hash=sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068 \
-    --hash=sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac \
-    --hash=sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25 \
-    --hash=sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8 \
-    --hash=sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab \
-    --hash=sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26 \
-    --hash=sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2 \
-    --hash=sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db \
-    --hash=sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f \
-    --hash=sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5 \
-    --hash=sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99 \
-    --hash=sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c \
-    --hash=sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d \
-    --hash=sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811 \
-    --hash=sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa \
-    --hash=sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a \
-    --hash=sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03 \
-    --hash=sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b \
-    --hash=sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04 \
-    --hash=sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c \
-    --hash=sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001 \
-    --hash=sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458 \
-    --hash=sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389 \
-    --hash=sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99 \
-    --hash=sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985 \
-    --hash=sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537 \
-    --hash=sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238 \
-    --hash=sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f \
-    --hash=sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d \
-    --hash=sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796 \
-    --hash=sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a \
-    --hash=sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143 \
-    --hash=sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8 \
-    --hash=sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c \
-    --hash=sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5 \
-    --hash=sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5 \
-    --hash=sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711 \
-    --hash=sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4 \
-    --hash=sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6 \
-    --hash=sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c \
-    --hash=sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7 \
-    --hash=sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4 \
-    --hash=sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b \
-    --hash=sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae \
-    --hash=sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12 \
-    --hash=sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c \
-    --hash=sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae \
-    --hash=sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8 \
-    --hash=sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887 \
-    --hash=sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b \
-    --hash=sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4 \
-    --hash=sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f \
-    --hash=sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5 \
-    --hash=sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33 \
-    --hash=sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519 \
-    --hash=sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561
+charset-normalizer==3.4.1 \
+    --hash=sha256:0167ddc8ab6508fe81860a57dd472b2ef4060e8d378f0cc555707126830f2537 \
+    --hash=sha256:01732659ba9b5b873fc117534143e4feefecf3b2078b0a6a2e925271bb6f4cfa \
+    --hash=sha256:01ad647cdd609225c5350561d084b42ddf732f4eeefe6e678765636791e78b9a \
+    --hash=sha256:04432ad9479fa40ec0f387795ddad4437a2b50417c69fa275e212933519ff294 \
+    --hash=sha256:0907f11d019260cdc3f94fbdb23ff9125f6b5d1039b76003b5b0ac9d6a6c9d5b \
+    --hash=sha256:0924e81d3d5e70f8126529951dac65c1010cdf117bb75eb02dd12339b57749dd \
+    --hash=sha256:09b26ae6b1abf0d27570633b2b078a2a20419c99d66fb2823173d73f188ce601 \
+    --hash=sha256:09b5e6733cbd160dcc09589227187e242a30a49ca5cefa5a7edd3f9d19ed53fd \
+    --hash=sha256:0af291f4fe114be0280cdd29d533696a77b5b49cfde5467176ecab32353395c4 \
+    --hash=sha256:0f55e69f030f7163dffe9fd0752b32f070566451afe180f99dbeeb81f511ad8d \
+    --hash=sha256:1a2bc9f351a75ef49d664206d51f8e5ede9da246602dc2d2726837620ea034b2 \
+    --hash=sha256:22e14b5d70560b8dd51ec22863f370d1e595ac3d024cb8ad7d308b4cd95f8313 \
+    --hash=sha256:234ac59ea147c59ee4da87a0c0f098e9c8d169f4dc2a159ef720f1a61bbe27cd \
+    --hash=sha256:2369eea1ee4a7610a860d88f268eb39b95cb588acd7235e02fd5a5601773d4fa \
+    --hash=sha256:237bdbe6159cff53b4f24f397d43c6336c6b0b42affbe857970cefbb620911c8 \
+    --hash=sha256:28bf57629c75e810b6ae989f03c0828d64d6b26a5e205535585f96093e405ed1 \
+    --hash=sha256:2967f74ad52c3b98de4c3b32e1a44e32975e008a9cd2a8cc8966d6a5218c5cb2 \
+    --hash=sha256:2a75d49014d118e4198bcee5ee0a6f25856b29b12dbf7cd012791f8a6cc5c496 \
+    --hash=sha256:2bdfe3ac2e1bbe5b59a1a63721eb3b95fc9b6817ae4a46debbb4e11f6232428d \
+    --hash=sha256:2d074908e1aecee37a7635990b2c6d504cd4766c7bc9fc86d63f9c09af3fa11b \
+    --hash=sha256:2fb9bd477fdea8684f78791a6de97a953c51831ee2981f8e4f583ff3b9d9687e \
+    --hash=sha256:311f30128d7d333eebd7896965bfcfbd0065f1716ec92bd5638d7748eb6f936a \
+    --hash=sha256:329ce159e82018d646c7ac45b01a430369d526569ec08516081727a20e9e4af4 \
+    --hash=sha256:345b0426edd4e18138d6528aed636de7a9ed169b4aaf9d61a8c19e39d26838ca \
+    --hash=sha256:363e2f92b0f0174b2f8238240a1a30142e3db7b957a5dd5689b0e75fb717cc78 \
+    --hash=sha256:3a3bd0dcd373514dcec91c411ddb9632c0d7d92aed7093b8c3bbb6d69ca74408 \
+    --hash=sha256:3bed14e9c89dcb10e8f3a29f9ccac4955aebe93c71ae803af79265c9ca5644c5 \
+    --hash=sha256:44251f18cd68a75b56585dd00dae26183e102cd5e0f9f1466e6df5da2ed64ea3 \
+    --hash=sha256:44ecbf16649486d4aebafeaa7ec4c9fed8b88101f4dd612dcaf65d5e815f837f \
+    --hash=sha256:4532bff1b8421fd0a320463030c7520f56a79c9024a4e88f01c537316019005a \
+    --hash=sha256:49402233c892a461407c512a19435d1ce275543138294f7ef013f0b63d5d3765 \
+    --hash=sha256:4c0907b1928a36d5a998d72d64d8eaa7244989f7aaaf947500d3a800c83a3fd6 \
+    --hash=sha256:4d86f7aff21ee58f26dcf5ae81a9addbd914115cdebcbb2217e4f0ed8982e146 \
+    --hash=sha256:5777ee0881f9499ed0f71cc82cf873d9a0ca8af166dfa0af8ec4e675b7df48e6 \
+    --hash=sha256:5df196eb874dae23dcfb968c83d4f8fdccb333330fe1fc278ac5ceeb101003a9 \
+    --hash=sha256:619a609aa74ae43d90ed2e89bdd784765de0a25ca761b93e196d938b8fd1dbbd \
+    --hash=sha256:6e27f48bcd0957c6d4cb9d6fa6b61d192d0b13d5ef563e5f2ae35feafc0d179c \
+    --hash=sha256:6ff8a4a60c227ad87030d76e99cd1698345d4491638dfa6673027c48b3cd395f \
+    --hash=sha256:73d94b58ec7fecbc7366247d3b0b10a21681004153238750bb67bd9012414545 \
+    --hash=sha256:7461baadb4dc00fd9e0acbe254e3d7d2112e7f92ced2adc96e54ef6501c5f176 \
+    --hash=sha256:75832c08354f595c760a804588b9357d34ec00ba1c940c15e31e96d902093770 \
+    --hash=sha256:7709f51f5f7c853f0fb938bcd3bc59cdfdc5203635ffd18bf354f6967ea0f824 \
+    --hash=sha256:78baa6d91634dfb69ec52a463534bc0df05dbd546209b79a3880a34487f4b84f \
+    --hash=sha256:7974a0b5ecd505609e3b19742b60cee7aa2aa2fb3151bc917e6e2646d7667dcf \
+    --hash=sha256:7a4f97a081603d2050bfaffdefa5b02a9ec823f8348a572e39032caa8404a487 \
+    --hash=sha256:7b1bef6280950ee6c177b326508f86cad7ad4dff12454483b51d8b7d673a2c5d \
+    --hash=sha256:7d053096f67cd1241601111b698f5cad775f97ab25d81567d3f59219b5f1adbd \
+    --hash=sha256:804a4d582ba6e5b747c625bf1255e6b1507465494a40a2130978bda7b932c90b \
+    --hash=sha256:807f52c1f798eef6cf26beb819eeb8819b1622ddfeef9d0977a8502d4db6d534 \
+    --hash=sha256:80ed5e856eb7f30115aaf94e4a08114ccc8813e6ed1b5efa74f9f82e8509858f \
+    --hash=sha256:8417cb1f36cc0bc7eaba8ccb0e04d55f0ee52df06df3ad55259b9a323555fc8b \
+    --hash=sha256:8436c508b408b82d87dc5f62496973a1805cd46727c34440b0d29d8a2f50a6c9 \
+    --hash=sha256:89149166622f4db9b4b6a449256291dc87a99ee53151c74cbd82a53c8c2f6ccd \
+    --hash=sha256:8bfa33f4f2672964266e940dd22a195989ba31669bd84629f05fab3ef4e2d125 \
+    --hash=sha256:8c60ca7339acd497a55b0ea5d506b2a2612afb2826560416f6894e8b5770d4a9 \
+    --hash=sha256:91b36a978b5ae0ee86c394f5a54d6ef44db1de0815eb43de826d41d21e4af3de \
+    --hash=sha256:955f8851919303c92343d2f66165294848d57e9bba6cf6e3625485a70a038d11 \
+    --hash=sha256:97f68b8d6831127e4787ad15e6757232e14e12060bec17091b85eb1486b91d8d \
+    --hash=sha256:9b23ca7ef998bc739bf6ffc077c2116917eabcc901f88da1b9856b210ef63f35 \
+    --hash=sha256:9f0b8b1c6d84c8034a44893aba5e767bf9c7a211e313a9605d9c617d7083829f \
+    --hash=sha256:aabfa34badd18f1da5ec1bc2715cadc8dca465868a4e73a0173466b688f29dda \
+    --hash=sha256:ab36c8eb7e454e34e60eb55ca5d241a5d18b2c6244f6827a30e451c42410b5f7 \
+    --hash=sha256:b010a7a4fd316c3c484d482922d13044979e78d1861f0e0650423144c616a46a \
+    --hash=sha256:b1ac5992a838106edb89654e0aebfc24f5848ae2547d22c2c3f66454daa11971 \
+    --hash=sha256:b7b2d86dd06bfc2ade3312a83a5c364c7ec2e3498f8734282c6c3d4b07b346b8 \
+    --hash=sha256:b97e690a2118911e39b4042088092771b4ae3fc3aa86518f84b8cf6888dbdb41 \
+    --hash=sha256:bc2722592d8998c870fa4e290c2eec2c1569b87fe58618e67d38b4665dfa680d \
+    --hash=sha256:c0429126cf75e16c4f0ad00ee0eae4242dc652290f940152ca8c75c3a4b6ee8f \
+    --hash=sha256:c30197aa96e8eed02200a83fba2657b4c3acd0f0aa4bdc9f6c1af8e8962e0757 \
+    --hash=sha256:c4c3e6da02df6fa1410a7680bd3f63d4f710232d3139089536310d027950696a \
+    --hash=sha256:c75cb2a3e389853835e84a2d8fb2b81a10645b503eca9bcb98df6b5a43eb8886 \
+    --hash=sha256:c96836c97b1238e9c9e3fe90844c947d5afbf4f4c92762679acfe19927d81d77 \
+    --hash=sha256:d7f50a1f8c450f3925cb367d011448c39239bb3eb4117c36a6d354794de4ce76 \
+    --hash=sha256:d973f03c0cb71c5ed99037b870f2be986c3c05e63622c017ea9816881d2dd247 \
+    --hash=sha256:d98b1668f06378c6dbefec3b92299716b931cd4e6061f3c875a71ced1780ab85 \
+    --hash=sha256:d9c3cdf5390dcd29aa8056d13e8e99526cda0305acc038b96b30352aff5ff2bb \
+    --hash=sha256:dad3e487649f498dd991eeb901125411559b22e8d7ab25d3aeb1af367df5efd7 \
+    --hash=sha256:dccbe65bd2f7f7ec22c4ff99ed56faa1e9f785482b9bbd7c717e26fd723a1d1e \
+    --hash=sha256:dd78cfcda14a1ef52584dbb008f7ac81c1328c0f58184bf9a84c49c605002da6 \
+    --hash=sha256:e218488cd232553829be0664c2292d3af2eeeb94b32bea483cf79ac6a694e037 \
+    --hash=sha256:e358e64305fe12299a08e08978f51fc21fac060dcfcddd95453eabe5b93ed0e1 \
+    --hash=sha256:ea0d8d539afa5eb2728aa1932a988a9a7af94f18582ffae4bc10b3fbdad0626e \
+    --hash=sha256:eab677309cdb30d047996b36d34caeda1dc91149e4fdca0b1a039b3f79d9a807 \
+    --hash=sha256:eb8178fe3dba6450a3e024e95ac49ed3400e506fd4e9e5c32d30adda88cbd407 \
+    --hash=sha256:ecddf25bee22fe4fe3737a399d0d177d72bc22be6913acfab364b40bce1ba83c \
+    --hash=sha256:eea6ee1db730b3483adf394ea72f808b6e18cf3cb6454b4d86e04fa8c4327a12 \
+    --hash=sha256:f08ff5e948271dc7e18a35641d2f11a4cd8dfd5634f55228b691e62b37125eb3 \
+    --hash=sha256:f30bf9fd9be89ecb2360c7d94a711f00c09b976258846efe40db3d05828e8089 \
+    --hash=sha256:fa88b843d6e211393a37219e6a1c1df99d35e8fd90446f1118f4216e307e48cd \
+    --hash=sha256:fc54db6c8593ef7d4b2a331b58653356cf04f67c960f584edb7c3d8c97e8f39e \
+    --hash=sha256:fd4ec41f914fa74ad1b8304bbc634b3de73d2a0889bd32076342a573e0779e00 \
+    --hash=sha256:ffc9202a29ab3920fa812879e95a9e78b2465fd10be7fcbd042899695d75e616
     # via
     #   -r requirements.txt
     #   requests
-docker==7.0.0 \
-    --hash=sha256:12ba681f2777a0ad28ffbcc846a69c31b4dfd9752b47eb425a274ee269c5e14b \
-    --hash=sha256:323736fb92cd9418fc5e7133bc953e11a9da04f4483f828b527db553f1e7e5a3
+docker==7.1.0 \
+    --hash=sha256:ad8c70e6e3f8926cb8a92619b832b4ea5299e2831c14284663184e200546fa6c \
+    --hash=sha256:c96b93b7f0a746f9e77d325bcfb87422a3d8bd4f03136ae8a85b37f1898d5fc0
     # via -r requirements.txt
-idna==3.6 \
-    --hash=sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca \
-    --hash=sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f
+idna==3.10 \
+    --hash=sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9 \
+    --hash=sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3
     # via
     #   -r requirements.txt
     #   requests
-jinja2==3.1.3 \
-    --hash=sha256:7d6d50dd97d52cbc355597bd845fabfbac3f551e1f99619e39a35ce8c370b5fa \
-    --hash=sha256:ac8bd6544d4bb2c9792bf3a159e80bba8fda7f07e81bc3aed565432d5925ba90
+jinja2==3.1.5 \
+    --hash=sha256:8fefff8dc3034e27bb80d67c671eb8a9bc424c0ef4c0826edbff304cceff43bb \
+    --hash=sha256:aba0f4dc9ed8013c424088f68a5c226f7d6097ed89b246d7749c2ec4175c6adb
     # via -r requirements.txt
-jsonschema==4.21.1 \
-    --hash=sha256:7996507afae316306f9e2290407761157c6f78002dcf7419acb99822143d1c6f \
-    --hash=sha256:85727c00279f5fa6bedbe6238d2aa6403bedd8b4864ab11207d07df3cc1b2ee5
+jsonschema==4.23.0 \
+    --hash=sha256:d71497fef26351a33265337fa77ffeb82423f3ea21283cd9467bb03999266bc4 \
+    --hash=sha256:fbadb6f8b144a8f8cf9f0b89ba94501d143e50411a1278633f56a7acf7fd5566
     # via -r requirements.txt
-jsonschema-specifications==2023.12.1 \
-    --hash=sha256:48a76787b3e70f5ed53f1160d2b81f586e4ca6d1548c5de7085d1682674764cc \
-    --hash=sha256:87e4fdf3a94858b8a2ba2778d9ba57d8a9cafca7c7489c46ba0d30a8bc6a9c3c
+jsonschema-specifications==2024.10.1 \
+    --hash=sha256:0f38b83639958ce1152d02a7f062902c41c8fd20d558b0c34344292d417ae272 \
+    --hash=sha256:a09a0680616357d9a0ecf05c12ad234479f549239d0f5b55f3deea67475da9bf
     # via
     #   -r requirements.txt
     #   jsonschema
-markupsafe==2.1.5 \
-    --hash=sha256:00e046b6dd71aa03a41079792f8473dc494d564611a8f89bbbd7cb93295ebdcf \
-    --hash=sha256:075202fa5b72c86ad32dc7d0b56024ebdbcf2048c0ba09f1cde31bfdd57bcfff \
-    --hash=sha256:0e397ac966fdf721b2c528cf028494e86172b4feba51d65f81ffd65c63798f3f \
-    --hash=sha256:17b950fccb810b3293638215058e432159d2b71005c74371d784862b7e4683f3 \
-    --hash=sha256:1f3fbcb7ef1f16e48246f704ab79d79da8a46891e2da03f8783a5b6fa41a9532 \
-    --hash=sha256:2174c595a0d73a3080ca3257b40096db99799265e1c27cc5a610743acd86d62f \
-    --hash=sha256:2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617 \
-    --hash=sha256:2d2d793e36e230fd32babe143b04cec8a8b3eb8a3122d2aceb4a371e6b09b8df \
-    --hash=sha256:30b600cf0a7ac9234b2638fbc0fb6158ba5bdcdf46aeb631ead21248b9affbc4 \
-    --hash=sha256:397081c1a0bfb5124355710fe79478cdbeb39626492b15d399526ae53422b906 \
-    --hash=sha256:3a57fdd7ce31c7ff06cdfbf31dafa96cc533c21e443d57f5b1ecc6cdc668ec7f \
-    --hash=sha256:3c6b973f22eb18a789b1460b4b91bf04ae3f0c4234a0a6aa6b0a92f6f7b951d4 \
-    --hash=sha256:3e53af139f8579a6d5f7b76549125f0d94d7e630761a2111bc431fd820e163b8 \
-    --hash=sha256:4096e9de5c6fdf43fb4f04c26fb114f61ef0bf2e5604b6ee3019d51b69e8c371 \
-    --hash=sha256:4275d846e41ecefa46e2015117a9f491e57a71ddd59bbead77e904dc02b1bed2 \
-    --hash=sha256:4c31f53cdae6ecfa91a77820e8b151dba54ab528ba65dfd235c80b086d68a465 \
-    --hash=sha256:4f11aa001c540f62c6166c7726f71f7573b52c68c31f014c25cc7901deea0b52 \
-    --hash=sha256:5049256f536511ee3f7e1b3f87d1d1209d327e818e6ae1365e8653d7e3abb6a6 \
-    --hash=sha256:58c98fee265677f63a4385256a6d7683ab1832f3ddd1e66fe948d5880c21a169 \
-    --hash=sha256:598e3276b64aff0e7b3451b72e94fa3c238d452e7ddcd893c3ab324717456bad \
-    --hash=sha256:5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2 \
-    --hash=sha256:5dedb4db619ba5a2787a94d877bc8ffc0566f92a01c0ef214865e54ecc9ee5e0 \
-    --hash=sha256:619bc166c4f2de5caa5a633b8b7326fbe98e0ccbfacabd87268a2b15ff73a029 \
-    --hash=sha256:629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f \
-    --hash=sha256:656f7526c69fac7f600bd1f400991cc282b417d17539a1b228617081106feb4a \
-    --hash=sha256:6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced \
-    --hash=sha256:72b6be590cc35924b02c78ef34b467da4ba07e4e0f0454a2c5907f473fc50ce5 \
-    --hash=sha256:7502934a33b54030eaf1194c21c692a534196063db72176b0c4028e140f8f32c \
-    --hash=sha256:7a68b554d356a91cce1236aa7682dc01df0edba8d043fd1ce607c49dd3c1edcf \
-    --hash=sha256:7b2e5a267c855eea6b4283940daa6e88a285f5f2a67f2220203786dfa59b37e9 \
-    --hash=sha256:823b65d8706e32ad2df51ed89496147a42a2a6e01c13cfb6ffb8b1e92bc910bb \
-    --hash=sha256:8590b4ae07a35970728874632fed7bd57b26b0102df2d2b233b6d9d82f6c62ad \
-    --hash=sha256:8dd717634f5a044f860435c1d8c16a270ddf0ef8588d4887037c5028b859b0c3 \
-    --hash=sha256:8dec4936e9c3100156f8a2dc89c4b88d5c435175ff03413b443469c7c8c5f4d1 \
-    --hash=sha256:97cafb1f3cbcd3fd2b6fbfb99ae11cdb14deea0736fc2b0952ee177f2b813a46 \
-    --hash=sha256:a17a92de5231666cfbe003f0e4b9b3a7ae3afb1ec2845aadc2bacc93ff85febc \
-    --hash=sha256:a549b9c31bec33820e885335b451286e2969a2d9e24879f83fe904a5ce59d70a \
-    --hash=sha256:ac07bad82163452a6884fe8fa0963fb98c2346ba78d779ec06bd7a6262132aee \
-    --hash=sha256:ae2ad8ae6ebee9d2d94b17fb62763125f3f374c25618198f40cbb8b525411900 \
-    --hash=sha256:b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5 \
-    --hash=sha256:bc1667f8b83f48511b94671e0e441401371dfd0f0a795c7daa4a3cd1dde55bea \
-    --hash=sha256:bec0a414d016ac1a18862a519e54b2fd0fc8bbfd6890376898a6c0891dd82e9f \
-    --hash=sha256:bf50cd79a75d181c9181df03572cdce0fbb75cc353bc350712073108cba98de5 \
-    --hash=sha256:bff1b4290a66b490a2f4719358c0cdcd9bafb6b8f061e45c7a2460866bf50c2e \
-    --hash=sha256:c061bb86a71b42465156a3ee7bd58c8c2ceacdbeb95d05a99893e08b8467359a \
-    --hash=sha256:c8b29db45f8fe46ad280a7294f5c3ec36dbac9491f2d1c17345be8e69cc5928f \
-    --hash=sha256:ce409136744f6521e39fd8e2a24c53fa18ad67aa5bc7c2cf83645cce5b5c4e50 \
-    --hash=sha256:d050b3361367a06d752db6ead6e7edeb0009be66bc3bae0ee9d97fb326badc2a \
-    --hash=sha256:d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b \
-    --hash=sha256:d9fad5155d72433c921b782e58892377c44bd6252b5af2f67f16b194987338a4 \
-    --hash=sha256:daa4ee5a243f0f20d528d939d06670a298dd39b1ad5f8a72a4275124a7819eff \
-    --hash=sha256:db0b55e0f3cc0be60c1f19efdde9a637c32740486004f20d1cff53c3c0ece4d2 \
-    --hash=sha256:e61659ba32cf2cf1481e575d0462554625196a1f2fc06a1c777d3f48e8865d46 \
-    --hash=sha256:ea3d8a3d18833cf4304cd2fc9cbb1efe188ca9b5efef2bdac7adc20594a0e46b \
-    --hash=sha256:ec6a563cff360b50eed26f13adc43e61bc0c04d94b8be985e6fb24b81f6dcfdf \
-    --hash=sha256:f5dfb42c4604dddc8e4305050aa6deb084540643ed5804d7455b5df8fe16f5e5 \
-    --hash=sha256:fa173ec60341d6bb97a89f5ea19c85c5643c1e7dedebc22f5181eb73573142c5 \
-    --hash=sha256:fa9db3f79de01457b03d4f01b34cf91bc0048eb2c3846ff26f66687c2f6d16ab \
-    --hash=sha256:fce659a462a1be54d2ffcacea5e3ba2d74daa74f30f5f143fe0c58636e355fdd \
-    --hash=sha256:ffee1f21e5ef0d712f9033568f8344d5da8cc2869dbd08d87c84656e6a2d2f68
+markupsafe==3.0.2 \
+    --hash=sha256:0bff5e0ae4ef2e1ae4fdf2dfd5b76c75e5c2fa4132d05fc1b0dabcd20c7e28c4 \
+    --hash=sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30 \
+    --hash=sha256:1225beacc926f536dc82e45f8a4d68502949dc67eea90eab715dea3a21c1b5f0 \
+    --hash=sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9 \
+    --hash=sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396 \
+    --hash=sha256:1a9d3f5f0901fdec14d8d2f66ef7d035f2157240a433441719ac9a3fba440b13 \
+    --hash=sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028 \
+    --hash=sha256:1e084f686b92e5b83186b07e8a17fc09e38fff551f3602b249881fec658d3eca \
+    --hash=sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557 \
+    --hash=sha256:2cb8438c3cbb25e220c2ab33bb226559e7afb3baec11c4f218ffa7308603c832 \
+    --hash=sha256:3169b1eefae027567d1ce6ee7cae382c57fe26e82775f460f0b2778beaad66c0 \
+    --hash=sha256:3809ede931876f5b2ec92eef964286840ed3540dadf803dd570c3b7e13141a3b \
+    --hash=sha256:38a9ef736c01fccdd6600705b09dc574584b89bea478200c5fbf112a6b0d5579 \
+    --hash=sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a \
+    --hash=sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c \
+    --hash=sha256:48032821bbdf20f5799ff537c7ac3d1fba0ba032cfc06194faffa8cda8b560ff \
+    --hash=sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c \
+    --hash=sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22 \
+    --hash=sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094 \
+    --hash=sha256:57cb5a3cf367aeb1d316576250f65edec5bb3be939e9247ae594b4bcbc317dfb \
+    --hash=sha256:5b02fb34468b6aaa40dfc198d813a641e3a63b98c2b05a16b9f80b7ec314185e \
+    --hash=sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5 \
+    --hash=sha256:6af100e168aa82a50e186c82875a5893c5597a0c1ccdb0d8b40240b1f28b969a \
+    --hash=sha256:6c89876f41da747c8d3677a2b540fb32ef5715f97b66eeb0c6b66f5e3ef6f59d \
+    --hash=sha256:6e296a513ca3d94054c2c881cc913116e90fd030ad1c656b3869762b754f5f8a \
+    --hash=sha256:70a87b411535ccad5ef2f1df5136506a10775d267e197e4cf531ced10537bd6b \
+    --hash=sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8 \
+    --hash=sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225 \
+    --hash=sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c \
+    --hash=sha256:88b49a3b9ff31e19998750c38e030fc7bb937398b1f78cfa599aaef92d693144 \
+    --hash=sha256:8c4e8c3ce11e1f92f6536ff07154f9d49677ebaaafc32db9db4620bc11ed480f \
+    --hash=sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87 \
+    --hash=sha256:9025b4018f3a1314059769c7bf15441064b2207cb3f065e6ea1e7359cb46db9d \
+    --hash=sha256:93335ca3812df2f366e80509ae119189886b0f3c2b81325d39efdb84a1e2ae93 \
+    --hash=sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf \
+    --hash=sha256:9e2d922824181480953426608b81967de705c3cef4d1af983af849d7bd619158 \
+    --hash=sha256:a123e330ef0853c6e822384873bef7507557d8e4a082961e1defa947aa59ba84 \
+    --hash=sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb \
+    --hash=sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48 \
+    --hash=sha256:b424c77b206d63d500bcb69fa55ed8d0e6a3774056bdc4839fc9298a7edca171 \
+    --hash=sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c \
+    --hash=sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6 \
+    --hash=sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd \
+    --hash=sha256:bbcb445fa71794da8f178f0f6d66789a28d7319071af7a496d4d507ed566270d \
+    --hash=sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1 \
+    --hash=sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d \
+    --hash=sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca \
+    --hash=sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a \
+    --hash=sha256:cfad01eed2c2e0c01fd0ecd2ef42c492f7f93902e39a42fc9ee1692961443a29 \
+    --hash=sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe \
+    --hash=sha256:d8213e09c917a951de9d09ecee036d5c7d36cb6cb7dbaece4c71a60d79fb9798 \
+    --hash=sha256:e07c3764494e3776c602c1e78e298937c3315ccc9043ead7e685b7f2b8d47b3c \
+    --hash=sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8 \
+    --hash=sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f \
+    --hash=sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f \
+    --hash=sha256:eaa0a10b7f72326f1372a713e73c3f739b524b3af41feb43e4921cb529f5929a \
+    --hash=sha256:eb7972a85c54febfb25b5c4b4f3af4dcc731994c7da0d8a0b4a6eb0640e1d178 \
+    --hash=sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0 \
+    --hash=sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79 \
+    --hash=sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430 \
+    --hash=sha256:fcabf5ff6eea076f859677f5f0b6b5c1a51e70a376b0579e0eadef8db48c6b50
     # via
     #   -r requirements.txt
     #   jinja2
@@ -227,188 +226,184 @@ mypy==1.8.0 \
     --hash=sha256:df9824ac11deaf007443e7ed2a4a26bebff98d2bc43c6da21b2b64185da011c4 \
     --hash=sha256:e46f44b54ebddbeedbd3d5b289a893219065ef805d95094d16a0af6630f5d410 \
     --hash=sha256:f5ac9a4eeb1ec0f1ccdc6f326bcdb464de5f80eb07fb38b5ddd7b0de6bc61e55
-    # via
-    #   -r requirements.dev.in
-    #   -r requirements.txt
+    # via -r requirements.dev.in
 mypy-extensions==1.0.0 \
     --hash=sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d \
     --hash=sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782
-    # via
-    #   -r requirements.txt
-    #   mypy
-packaging==23.2 \
-    --hash=sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5 \
-    --hash=sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7
-    # via
-    #   -r requirements.txt
-    #   docker
-pyyaml==6.0.1 \
-    --hash=sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5 \
-    --hash=sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc \
-    --hash=sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df \
-    --hash=sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741 \
-    --hash=sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206 \
-    --hash=sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27 \
-    --hash=sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595 \
-    --hash=sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62 \
-    --hash=sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98 \
-    --hash=sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696 \
-    --hash=sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290 \
-    --hash=sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9 \
-    --hash=sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d \
-    --hash=sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6 \
-    --hash=sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867 \
-    --hash=sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47 \
-    --hash=sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486 \
-    --hash=sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6 \
-    --hash=sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3 \
-    --hash=sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007 \
-    --hash=sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938 \
-    --hash=sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0 \
-    --hash=sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c \
-    --hash=sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735 \
-    --hash=sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d \
-    --hash=sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28 \
-    --hash=sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4 \
-    --hash=sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba \
-    --hash=sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8 \
-    --hash=sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef \
-    --hash=sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5 \
-    --hash=sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd \
-    --hash=sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3 \
-    --hash=sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0 \
-    --hash=sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515 \
-    --hash=sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c \
-    --hash=sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c \
-    --hash=sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924 \
-    --hash=sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34 \
-    --hash=sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43 \
-    --hash=sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859 \
-    --hash=sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673 \
-    --hash=sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54 \
-    --hash=sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a \
-    --hash=sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b \
-    --hash=sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab \
-    --hash=sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa \
-    --hash=sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c \
-    --hash=sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585 \
-    --hash=sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d \
-    --hash=sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f
+    # via mypy
+pyyaml==6.0.2 \
+    --hash=sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff \
+    --hash=sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48 \
+    --hash=sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086 \
+    --hash=sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e \
+    --hash=sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133 \
+    --hash=sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5 \
+    --hash=sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484 \
+    --hash=sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee \
+    --hash=sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5 \
+    --hash=sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68 \
+    --hash=sha256:24471b829b3bf607e04e88d79542a9d48bb037c2267d7927a874e6c205ca7e9a \
+    --hash=sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf \
+    --hash=sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99 \
+    --hash=sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8 \
+    --hash=sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85 \
+    --hash=sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19 \
+    --hash=sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc \
+    --hash=sha256:43fa96a3ca0d6b1812e01ced1044a003533c47f6ee8aca31724f78e93ccc089a \
+    --hash=sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1 \
+    --hash=sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317 \
+    --hash=sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c \
+    --hash=sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631 \
+    --hash=sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d \
+    --hash=sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652 \
+    --hash=sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5 \
+    --hash=sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e \
+    --hash=sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b \
+    --hash=sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8 \
+    --hash=sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476 \
+    --hash=sha256:82d09873e40955485746739bcb8b4586983670466c23382c19cffecbf1fd8706 \
+    --hash=sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563 \
+    --hash=sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237 \
+    --hash=sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b \
+    --hash=sha256:9056c1ecd25795207ad294bcf39f2db3d845767be0ea6e6a34d856f006006083 \
+    --hash=sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180 \
+    --hash=sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425 \
+    --hash=sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e \
+    --hash=sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f \
+    --hash=sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725 \
+    --hash=sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183 \
+    --hash=sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab \
+    --hash=sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774 \
+    --hash=sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725 \
+    --hash=sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e \
+    --hash=sha256:d7fded462629cfa4b685c5416b949ebad6cec74af5e2d42905d41e257e0869f5 \
+    --hash=sha256:d84a1718ee396f54f3a086ea0a66d8e552b2ab2017ef8b420e92edbc841c352d \
+    --hash=sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290 \
+    --hash=sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44 \
+    --hash=sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed \
+    --hash=sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4 \
+    --hash=sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba \
+    --hash=sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12 \
+    --hash=sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4
     # via -r requirements.txt
-referencing==0.33.0 \
-    --hash=sha256:39240f2ecc770258f28b642dd47fd74bc8b02484de54e1882b74b35ebd779bd5 \
-    --hash=sha256:c775fedf74bc0f9189c2a3be1c12fd03e8c23f4d371dce795df44e06c5b412f7
+referencing==0.35.1 \
+    --hash=sha256:25b42124a6c8b632a425174f24087783efb348a6f1e0008e63cd4466fedf703c \
+    --hash=sha256:eda6d3234d62814d1c64e305c1331c9a3a6132da475ab6382eaa997b21ee75de
     # via
     #   -r requirements.txt
     #   jsonschema
     #   jsonschema-specifications
     #   types-jsonschema
-requests==2.31.0 \
-    --hash=sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f \
-    --hash=sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1
+requests==2.32.3 \
+    --hash=sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760 \
+    --hash=sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6
     # via
     #   -r requirements.txt
     #   docker
-rpds-py==0.18.0 \
-    --hash=sha256:01e36a39af54a30f28b73096dd39b6802eddd04c90dbe161c1b8dbe22353189f \
-    --hash=sha256:044a3e61a7c2dafacae99d1e722cc2d4c05280790ec5a05031b3876809d89a5c \
-    --hash=sha256:08231ac30a842bd04daabc4d71fddd7e6d26189406d5a69535638e4dcb88fe76 \
-    --hash=sha256:08f9ad53c3f31dfb4baa00da22f1e862900f45908383c062c27628754af2e88e \
-    --hash=sha256:0ab39c1ba9023914297dd88ec3b3b3c3f33671baeb6acf82ad7ce883f6e8e157 \
-    --hash=sha256:0af039631b6de0397ab2ba16eaf2872e9f8fca391b44d3d8cac317860a700a3f \
-    --hash=sha256:0b8612cd233543a3781bc659c731b9d607de65890085098986dfd573fc2befe5 \
-    --hash=sha256:11a8c85ef4a07a7638180bf04fe189d12757c696eb41f310d2426895356dcf05 \
-    --hash=sha256:1374f4129f9bcca53a1bba0bb86bf78325a0374577cf7e9e4cd046b1e6f20e24 \
-    --hash=sha256:1d4acf42190d449d5e89654d5c1ed3a4f17925eec71f05e2a41414689cda02d1 \
-    --hash=sha256:1d9a5be316c15ffb2b3c405c4ff14448c36b4435be062a7f578ccd8b01f0c4d8 \
-    --hash=sha256:1df3659d26f539ac74fb3b0c481cdf9d725386e3552c6fa2974f4d33d78e544b \
-    --hash=sha256:22806714311a69fd0af9b35b7be97c18a0fc2826e6827dbb3a8c94eac6cf7eeb \
-    --hash=sha256:2644e47de560eb7bd55c20fc59f6daa04682655c58d08185a9b95c1970fa1e07 \
-    --hash=sha256:2e6d75ab12b0bbab7215e5d40f1e5b738aa539598db27ef83b2ec46747df90e1 \
-    --hash=sha256:30f43887bbae0d49113cbaab729a112251a940e9b274536613097ab8b4899cf6 \
-    --hash=sha256:34b18ba135c687f4dac449aa5157d36e2cbb7c03cbea4ddbd88604e076aa836e \
-    --hash=sha256:36b3ee798c58ace201289024b52788161e1ea133e4ac93fba7d49da5fec0ef9e \
-    --hash=sha256:39514da80f971362f9267c600b6d459bfbbc549cffc2cef8e47474fddc9b45b1 \
-    --hash=sha256:39f5441553f1c2aed4de4377178ad8ff8f9d733723d6c66d983d75341de265ab \
-    --hash=sha256:3a96e0c6a41dcdba3a0a581bbf6c44bb863f27c541547fb4b9711fd8cf0ffad4 \
-    --hash=sha256:3f26b5bd1079acdb0c7a5645e350fe54d16b17bfc5e71f371c449383d3342e17 \
-    --hash=sha256:41ef53e7c58aa4ef281da975f62c258950f54b76ec8e45941e93a3d1d8580594 \
-    --hash=sha256:42821446ee7a76f5d9f71f9e33a4fb2ffd724bb3e7f93386150b61a43115788d \
-    --hash=sha256:43fbac5f22e25bee1d482c97474f930a353542855f05c1161fd804c9dc74a09d \
-    --hash=sha256:4457a94da0d5c53dc4b3e4de1158bdab077db23c53232f37a3cb7afdb053a4e3 \
-    --hash=sha256:465a3eb5659338cf2a9243e50ad9b2296fa15061736d6e26240e713522b6235c \
-    --hash=sha256:482103aed1dfe2f3b71a58eff35ba105289b8d862551ea576bd15479aba01f66 \
-    --hash=sha256:4832d7d380477521a8c1644bbab6588dfedea5e30a7d967b5fb75977c45fd77f \
-    --hash=sha256:4901165d170a5fde6f589acb90a6b33629ad1ec976d4529e769c6f3d885e3e80 \
-    --hash=sha256:5307def11a35f5ae4581a0b658b0af8178c65c530e94893345bebf41cc139d33 \
-    --hash=sha256:5417558f6887e9b6b65b4527232553c139b57ec42c64570569b155262ac0754f \
-    --hash=sha256:56a737287efecafc16f6d067c2ea0117abadcd078d58721f967952db329a3e5c \
-    --hash=sha256:586f8204935b9ec884500498ccc91aa869fc652c40c093bd9e1471fbcc25c022 \
-    --hash=sha256:5b4e7d8d6c9b2e8ee2d55c90b59c707ca59bc30058269b3db7b1f8df5763557e \
-    --hash=sha256:5ddcba87675b6d509139d1b521e0c8250e967e63b5909a7e8f8944d0f90ff36f \
-    --hash=sha256:618a3d6cae6ef8ec88bb76dd80b83cfe415ad4f1d942ca2a903bf6b6ff97a2da \
-    --hash=sha256:635dc434ff724b178cb192c70016cc0ad25a275228f749ee0daf0eddbc8183b1 \
-    --hash=sha256:661d25cbffaf8cc42e971dd570d87cb29a665f49f4abe1f9e76be9a5182c4688 \
-    --hash=sha256:66e6a3af5a75363d2c9a48b07cb27c4ea542938b1a2e93b15a503cdfa8490795 \
-    --hash=sha256:67071a6171e92b6da534b8ae326505f7c18022c6f19072a81dcf40db2638767c \
-    --hash=sha256:685537e07897f173abcf67258bee3c05c374fa6fff89d4c7e42fb391b0605e98 \
-    --hash=sha256:69e64831e22a6b377772e7fb337533c365085b31619005802a79242fee620bc1 \
-    --hash=sha256:6b0817e34942b2ca527b0e9298373e7cc75f429e8da2055607f4931fded23e20 \
-    --hash=sha256:6c81e5f372cd0dc5dc4809553d34f832f60a46034a5f187756d9b90586c2c307 \
-    --hash=sha256:6d7faa6f14017c0b1e69f5e2c357b998731ea75a442ab3841c0dbbbfe902d2c4 \
-    --hash=sha256:6ef0befbb5d79cf32d0266f5cff01545602344eda89480e1dd88aca964260b18 \
-    --hash=sha256:6ef687afab047554a2d366e112dd187b62d261d49eb79b77e386f94644363294 \
-    --hash=sha256:7223a2a5fe0d217e60a60cdae28d6949140dde9c3bcc714063c5b463065e3d66 \
-    --hash=sha256:77f195baa60a54ef9d2de16fbbfd3ff8b04edc0c0140a761b56c267ac11aa467 \
-    --hash=sha256:793968759cd0d96cac1e367afd70c235867831983f876a53389ad869b043c948 \
-    --hash=sha256:7bd339195d84439cbe5771546fe8a4e8a7a045417d8f9de9a368c434e42a721e \
-    --hash=sha256:7cd863afe7336c62ec78d7d1349a2f34c007a3cc6c2369d667c65aeec412a5b1 \
-    --hash=sha256:7f2facbd386dd60cbbf1a794181e6aa0bd429bd78bfdf775436020172e2a23f0 \
-    --hash=sha256:84ffab12db93b5f6bad84c712c92060a2d321b35c3c9960b43d08d0f639d60d7 \
-    --hash=sha256:8c8370641f1a7f0e0669ddccca22f1da893cef7628396431eb445d46d893e5cd \
-    --hash=sha256:8db715ebe3bb7d86d77ac1826f7d67ec11a70dbd2376b7cc214199360517b641 \
-    --hash=sha256:8e8916ae4c720529e18afa0b879473049e95949bf97042e938530e072fde061d \
-    --hash=sha256:8f03bccbd8586e9dd37219bce4d4e0d3ab492e6b3b533e973fa08a112cb2ffc9 \
-    --hash=sha256:8f2fc11e8fe034ee3c34d316d0ad8808f45bc3b9ce5857ff29d513f3ff2923a1 \
-    --hash=sha256:923d39efa3cfb7279a0327e337a7958bff00cc447fd07a25cddb0a1cc9a6d2da \
-    --hash=sha256:93df1de2f7f7239dc9cc5a4a12408ee1598725036bd2dedadc14d94525192fc3 \
-    --hash=sha256:998e33ad22dc7ec7e030b3df701c43630b5bc0d8fbc2267653577e3fec279afa \
-    --hash=sha256:99f70b740dc04d09e6b2699b675874367885217a2e9f782bdf5395632ac663b7 \
-    --hash=sha256:9a00312dea9310d4cb7dbd7787e722d2e86a95c2db92fbd7d0155f97127bcb40 \
-    --hash=sha256:9d54553c1136b50fd12cc17e5b11ad07374c316df307e4cfd6441bea5fb68496 \
-    --hash=sha256:9dbbeb27f4e70bfd9eec1be5477517365afe05a9b2c441a0b21929ee61048124 \
-    --hash=sha256:a1ce3ba137ed54f83e56fb983a5859a27d43a40188ba798993812fed73c70836 \
-    --hash=sha256:a34d557a42aa28bd5c48a023c570219ba2593bcbbb8dc1b98d8cf5d529ab1434 \
-    --hash=sha256:a5f446dd5055667aabaee78487f2b5ab72e244f9bc0b2ffebfeec79051679984 \
-    --hash=sha256:ad36cfb355e24f1bd37cac88c112cd7730873f20fb0bdaf8ba59eedf8216079f \
-    --hash=sha256:aec493917dd45e3c69d00a8874e7cbed844efd935595ef78a0f25f14312e33c6 \
-    --hash=sha256:b316144e85316da2723f9d8dc75bada12fa58489a527091fa1d5a612643d1a0e \
-    --hash=sha256:b34ae4636dfc4e76a438ab826a0d1eed2589ca7d9a1b2d5bb546978ac6485461 \
-    --hash=sha256:b34b7aa8b261c1dbf7720b5d6f01f38243e9b9daf7e6b8bc1fd4657000062f2c \
-    --hash=sha256:bc362ee4e314870a70f4ae88772d72d877246537d9f8cb8f7eacf10884862432 \
-    --hash=sha256:bed88b9a458e354014d662d47e7a5baafd7ff81c780fd91584a10d6ec842cb73 \
-    --hash=sha256:c0013fe6b46aa496a6749c77e00a3eb07952832ad6166bd481c74bda0dcb6d58 \
-    --hash=sha256:c0b5dcf9193625afd8ecc92312d6ed78781c46ecbf39af9ad4681fc9f464af88 \
-    --hash=sha256:c4325ff0442a12113a6379af66978c3fe562f846763287ef66bdc1d57925d337 \
-    --hash=sha256:c463ed05f9dfb9baebef68048aed8dcdc94411e4bf3d33a39ba97e271624f8f7 \
-    --hash=sha256:c8362467a0fdeccd47935f22c256bec5e6abe543bf0d66e3d3d57a8fb5731863 \
-    --hash=sha256:cd5bf1af8efe569654bbef5a3e0a56eca45f87cfcffab31dd8dde70da5982475 \
-    --hash=sha256:cf1ea2e34868f6fbf070e1af291c8180480310173de0b0c43fc38a02929fc0e3 \
-    --hash=sha256:d62dec4976954a23d7f91f2f4530852b0c7608116c257833922a896101336c51 \
-    --hash=sha256:d68c93e381010662ab873fea609bf6c0f428b6d0bb00f2c6939782e0818d37bf \
-    --hash=sha256:d7c36232a90d4755b720fbd76739d8891732b18cf240a9c645d75f00639a9024 \
-    --hash=sha256:dd18772815d5f008fa03d2b9a681ae38d5ae9f0e599f7dda233c439fcaa00d40 \
-    --hash=sha256:ddc2f4dfd396c7bfa18e6ce371cba60e4cf9d2e5cdb71376aa2da264605b60b9 \
-    --hash=sha256:e003b002ec72c8d5a3e3da2989c7d6065b47d9eaa70cd8808b5384fbb970f4ec \
-    --hash=sha256:e32a92116d4f2a80b629778280103d2a510a5b3f6314ceccd6e38006b5e92dcb \
-    --hash=sha256:e4461d0f003a0aa9be2bdd1b798a041f177189c1a0f7619fe8c95ad08d9a45d7 \
-    --hash=sha256:e541ec6f2ec456934fd279a3120f856cd0aedd209fc3852eca563f81738f6861 \
-    --hash=sha256:e546e768d08ad55b20b11dbb78a745151acbd938f8f00d0cfbabe8b0199b9880 \
-    --hash=sha256:ea7d4a99f3b38c37eac212dbd6ec42b7a5ec51e2c74b5d3223e43c811609e65f \
-    --hash=sha256:ed4eb745efbff0a8e9587d22a84be94a5eb7d2d99c02dacf7bd0911713ed14dd \
-    --hash=sha256:f8a2f084546cc59ea99fda8e070be2fd140c3092dc11524a71aa8f0f3d5a55ca \
-    --hash=sha256:fcb25daa9219b4cf3a0ab24b0eb9a5cc8949ed4dc72acb8fa16b7e1681aa3c58 \
-    --hash=sha256:fdea4952db2793c4ad0bdccd27c1d8fdd1423a92f04598bc39425bcc2b8ee46e
+rpds-py==0.22.3 \
+    --hash=sha256:009de23c9c9ee54bf11303a966edf4d9087cd43a6003672e6aa7def643d06518 \
+    --hash=sha256:02fbb9c288ae08bcb34fb41d516d5eeb0455ac35b5512d03181d755d80810059 \
+    --hash=sha256:0a0461200769ab3b9ab7e513f6013b7a97fdeee41c29b9db343f3c5a8e2b9e61 \
+    --hash=sha256:0b09865a9abc0ddff4e50b5ef65467cd94176bf1e0004184eb915cbc10fc05c5 \
+    --hash=sha256:0b8db6b5b2d4491ad5b6bdc2bc7c017eec108acbf4e6785f42a9eb0ba234f4c9 \
+    --hash=sha256:0c150c7a61ed4a4f4955a96626574e9baf1adf772c2fb61ef6a5027e52803543 \
+    --hash=sha256:0f3cec041684de9a4684b1572fe28c7267410e02450f4561700ca5a3bc6695a2 \
+    --hash=sha256:1352ae4f7c717ae8cba93421a63373e582d19d55d2ee2cbb184344c82d2ae55a \
+    --hash=sha256:177c7c0fce2855833819c98e43c262007f42ce86651ffbb84f37883308cb0e7d \
+    --hash=sha256:1978d0021e943aae58b9b0b196fb4895a25cc53d3956b8e35e0b7682eefb6d56 \
+    --hash=sha256:1a60bce91f81ddaac922a40bbb571a12c1070cb20ebd6d49c48e0b101d87300d \
+    --hash=sha256:1aef18820ef3e4587ebe8b3bc9ba6e55892a6d7b93bac6d29d9f631a3b4befbd \
+    --hash=sha256:1e9663daaf7a63ceccbbb8e3808fe90415b0757e2abddbfc2e06c857bf8c5e2b \
+    --hash=sha256:20070c65396f7373f5df4005862fa162db5d25d56150bddd0b3e8214e8ef45b4 \
+    --hash=sha256:214b7a953d73b5e87f0ebece4a32a5bd83c60a3ecc9d4ec8f1dca968a2d91e99 \
+    --hash=sha256:22bebe05a9ffc70ebfa127efbc429bc26ec9e9b4ee4d15a740033efda515cf3d \
+    --hash=sha256:24e8abb5878e250f2eb0d7859a8e561846f98910326d06c0d51381fed59357bd \
+    --hash=sha256:26fd7cac7dd51011a245f29a2cc6489c4608b5a8ce8d75661bb4a1066c52dfbe \
+    --hash=sha256:27b1d3b3915a99208fee9ab092b8184c420f2905b7d7feb4aeb5e4a9c509b8a1 \
+    --hash=sha256:27e98004595899949bd7a7b34e91fa7c44d7a97c40fcaf1d874168bb652ec67e \
+    --hash=sha256:2b8f60e1b739a74bab7e01fcbe3dddd4657ec685caa04681df9d562ef15b625f \
+    --hash=sha256:2de29005e11637e7a2361fa151f780ff8eb2543a0da1413bb951e9f14b699ef3 \
+    --hash=sha256:2e8b55d8517a2fda8d95cb45d62a5a8bbf9dd0ad39c5b25c8833efea07b880ca \
+    --hash=sha256:2fa4331c200c2521512595253f5bb70858b90f750d39b8cbfd67465f8d1b596d \
+    --hash=sha256:3445e07bf2e8ecfeef6ef67ac83de670358abf2996916039b16a218e3d95e97e \
+    --hash=sha256:3453e8d41fe5f17d1f8e9c383a7473cd46a63661628ec58e07777c2fff7196dc \
+    --hash=sha256:378753b4a4de2a7b34063d6f95ae81bfa7b15f2c1a04a9518e8644e81807ebea \
+    --hash=sha256:3af6e48651c4e0d2d166dc1b033b7042ea3f871504b6805ba5f4fe31581d8d38 \
+    --hash=sha256:3dfcbc95bd7992b16f3f7ba05af8a64ca694331bd24f9157b49dadeeb287493b \
+    --hash=sha256:3f21f0495edea7fdbaaa87e633a8689cd285f8f4af5c869f27bc8074638ad69c \
+    --hash=sha256:4041711832360a9b75cfb11b25a6a97c8fb49c07b8bd43d0d02b45d0b499a4ff \
+    --hash=sha256:44d61b4b7d0c2c9ac019c314e52d7cbda0ae31078aabd0f22e583af3e0d79723 \
+    --hash=sha256:4617e1915a539a0d9a9567795023de41a87106522ff83fbfaf1f6baf8e85437e \
+    --hash=sha256:4b232061ca880db21fa14defe219840ad9b74b6158adb52ddf0e87bead9e8493 \
+    --hash=sha256:5246b14ca64a8675e0a7161f7af68fe3e910e6b90542b4bfb5439ba752191df6 \
+    --hash=sha256:5725dd9cc02068996d4438d397e255dcb1df776b7ceea3b9cb972bdb11260a83 \
+    --hash=sha256:583f6a1993ca3369e0f80ba99d796d8e6b1a3a2a442dd4e1a79e652116413091 \
+    --hash=sha256:59259dc58e57b10e7e18ce02c311804c10c5a793e6568f8af4dead03264584d1 \
+    --hash=sha256:593eba61ba0c3baae5bc9be2f5232430453fb4432048de28399ca7376de9c627 \
+    --hash=sha256:59f4a79c19232a5774aee369a0c296712ad0e77f24e62cad53160312b1c1eaa1 \
+    --hash=sha256:5f0e260eaf54380380ac3808aa4ebe2d8ca28b9087cf411649f96bad6900c728 \
+    --hash=sha256:62d9cfcf4948683a18a9aff0ab7e1474d407b7bab2ca03116109f8464698ab16 \
+    --hash=sha256:64607d4cbf1b7e3c3c8a14948b99345eda0e161b852e122c6bb71aab6d1d798c \
+    --hash=sha256:655ca44a831ecb238d124e0402d98f6212ac527a0ba6c55ca26f616604e60a45 \
+    --hash=sha256:666ecce376999bf619756a24ce15bb14c5bfaf04bf00abc7e663ce17c3f34fe7 \
+    --hash=sha256:68049202f67380ff9aa52f12e92b1c30115f32e6895cd7198fa2a7961621fc5a \
+    --hash=sha256:69803198097467ee7282750acb507fba35ca22cc3b85f16cf45fb01cb9097730 \
+    --hash=sha256:6c7b99ca52c2c1752b544e310101b98a659b720b21db00e65edca34483259967 \
+    --hash=sha256:6dd9412824c4ce1aca56c47b0991e65bebb7ac3f4edccfd3f156150c96a7bf25 \
+    --hash=sha256:70eb60b3ae9245ddea20f8a4190bd79c705a22f8028aaf8bbdebe4716c3fab24 \
+    --hash=sha256:70fb28128acbfd264eda9bf47015537ba3fe86e40d046eb2963d75024be4d055 \
+    --hash=sha256:7b2513ba235829860b13faa931f3b6846548021846ac808455301c23a101689d \
+    --hash=sha256:7ef9d9da710be50ff6809fed8f1963fecdfecc8b86656cadfca3bc24289414b0 \
+    --hash=sha256:81e69b0a0e2537f26d73b4e43ad7bc8c8efb39621639b4434b76a3de50c6966e \
+    --hash=sha256:8633e471c6207a039eff6aa116e35f69f3156b3989ea3e2d755f7bc41754a4a7 \
+    --hash=sha256:8bd7c8cfc0b8247c8799080fbff54e0b9619e17cdfeb0478ba7295d43f635d7c \
+    --hash=sha256:9253fc214112405f0afa7db88739294295f0e08466987f1d70e29930262b4c8f \
+    --hash=sha256:99b37292234e61325e7a5bb9689e55e48c3f5f603af88b1642666277a81f1fbd \
+    --hash=sha256:9bd7228827ec7bb817089e2eb301d907c0d9827a9e558f22f762bb690b131652 \
+    --hash=sha256:9beeb01d8c190d7581a4d59522cd3d4b6887040dcfc744af99aa59fef3e041a8 \
+    --hash=sha256:a63cbdd98acef6570c62b92a1e43266f9e8b21e699c363c0fef13bd530799c11 \
+    --hash=sha256:a76e42402542b1fae59798fab64432b2d015ab9d0c8c47ba7addddbaf7952333 \
+    --hash=sha256:ac0a03221cdb5058ce0167ecc92a8c89e8d0decdc9e99a2ec23380793c4dcb96 \
+    --hash=sha256:b0b4136a252cadfa1adb705bb81524eee47d9f6aab4f2ee4fa1e9d3cd4581f64 \
+    --hash=sha256:b25bc607423935079e05619d7de556c91fb6adeae9d5f80868dde3468657994b \
+    --hash=sha256:b3d504047aba448d70cf6fa22e06cb09f7cbd761939fdd47604f5e007675c24e \
+    --hash=sha256:bb47271f60660803ad11f4c61b42242b8c1312a31c98c578f79ef9387bbde21c \
+    --hash=sha256:bbb232860e3d03d544bc03ac57855cd82ddf19c7a07651a7c0fdb95e9efea8b9 \
+    --hash=sha256:bc27863442d388870c1809a87507727b799c8460573cfbb6dc0eeaef5a11b5ec \
+    --hash=sha256:bc51abd01f08117283c5ebf64844a35144a0843ff7b2983e0648e4d3d9f10dbb \
+    --hash=sha256:be2eb3f2495ba669d2a985f9b426c1797b7d48d6963899276d22f23e33d47e37 \
+    --hash=sha256:bf9db5488121b596dbfc6718c76092fda77b703c1f7533a226a5a9f65248f8ad \
+    --hash=sha256:c58e2339def52ef6b71b8f36d13c3688ea23fa093353f3a4fee2556e62086ec9 \
+    --hash=sha256:cfbc454a2880389dbb9b5b398e50d439e2e58669160f27b60e5eca11f68ae17c \
+    --hash=sha256:cff63a0272fcd259dcc3be1657b07c929c466b067ceb1c20060e8d10af56f5bf \
+    --hash=sha256:d115bffdd417c6d806ea9069237a4ae02f513b778e3789a359bc5856e0404cc4 \
+    --hash=sha256:d20cfb4e099748ea39e6f7b16c91ab057989712d31761d3300d43134e26e165f \
+    --hash=sha256:d48424e39c2611ee1b84ad0f44fb3b2b53d473e65de061e3f460fc0be5f1939d \
+    --hash=sha256:e0fa2d4ec53dc51cf7d3bb22e0aa0143966119f42a0c3e4998293a3dd2856b09 \
+    --hash=sha256:e32fee8ab45d3c2db6da19a5323bc3362237c8b653c70194414b892fd06a080d \
+    --hash=sha256:e35ba67d65d49080e8e5a1dd40101fccdd9798adb9b050ff670b7d74fa41c566 \
+    --hash=sha256:e3fb866d9932a3d7d0c82da76d816996d1667c44891bd861a0f97ba27e84fc74 \
+    --hash=sha256:e61b02c3f7a1e0b75e20c3978f7135fd13cb6cf551bf4a6d29b999a88830a338 \
+    --hash=sha256:e67ba3c290821343c192f7eae1d8fd5999ca2dc99994114643e2f2d3e6138b15 \
+    --hash=sha256:e79dd39f1e8c3504be0607e5fc6e86bb60fe3584bec8b782578c3b0fde8d932c \
+    --hash=sha256:e89391e6d60251560f0a8f4bd32137b077a80d9b7dbe6d5cab1cd80d2746f648 \
+    --hash=sha256:ea7433ce7e4bfc3a85654aeb6747babe3f66eaf9a1d0c1e7a4435bbdf27fea84 \
+    --hash=sha256:eaf16ae9ae519a0e237a0f528fd9f0197b9bb70f40263ee57ae53c2b8d48aeb3 \
+    --hash=sha256:eb0c341fa71df5a4595f9501df4ac5abfb5a09580081dffbd1ddd4654e6e9123 \
+    --hash=sha256:f276b245347e6e36526cbd4a266a417796fc531ddf391e43574cf6466c492520 \
+    --hash=sha256:f47ad3d5f3258bd7058d2d506852217865afefe6153a36eb4b6928758041d831 \
+    --hash=sha256:f56a6b404f74ab372da986d240e2e002769a7d7102cc73eb238a4f72eec5284e \
+    --hash=sha256:f5cf2a0c2bdadf3791b5c205d55a37a54025c6e18a71c71f82bb536cf9a454bf \
+    --hash=sha256:f5d36399a1b96e1a5fdc91e0522544580dbebeb1f77f27b2b0ab25559e103b8b \
+    --hash=sha256:f60bd8423be1d9d833f230fdbccf8f57af322d96bcad6599e5a771b151398eb2 \
+    --hash=sha256:f612463ac081803f243ff13cccc648578e2279295048f2a8d5eb430af2bae6e3 \
+    --hash=sha256:f73d3fef726b3243a811121de45193c0ca75f6407fe66f3f4e183c983573e130 \
+    --hash=sha256:f82a116a1d03628a8ace4859556fb39fd1424c933341a08ea3ed6de1edb0283b \
+    --hash=sha256:fb0ba113b4983beac1a2eb16faffd76cb41e176bf58c4afe3e14b9c681f702de \
+    --hash=sha256:fb4f868f712b2dd4bcc538b0a0c1f63a2b1d584c925e69a224d759e7070a12d5 \
+    --hash=sha256:fb6116dfb8d1925cbdb52595560584db42a7f664617a1f7d7f6e32f138cdf37d \
+    --hash=sha256:fda7cb070f442bf80b642cd56483b5548e43d366fe3f39b98e67cce780cded00 \
+    --hash=sha256:feea821ee2a9273771bae61194004ee2fc33f8ec7db08117ef9147d4bbcbca8e
     # via
     #   -r requirements.txt
     #   jsonschema
@@ -432,13 +427,43 @@ ruff==0.3.4 \
     --hash=sha256:df52972138318bc7546d92348a1ee58449bc3f9eaf0db278906eb511889c4b50 \
     --hash=sha256:f0f4484c6541a99862b693e13a151435a279b271cff20e37101116a21e2a1ad1
     # via -r requirements.dev.in
-six==1.16.0 \
-    --hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 \
-    --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254
+six==1.17.0 \
+    --hash=sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274 \
+    --hash=sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81
     # via -r requirements.txt
-tomli==2.0.1 \
-    --hash=sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc \
-    --hash=sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f
+tomli==2.2.1 \
+    --hash=sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6 \
+    --hash=sha256:02abe224de6ae62c19f090f68da4e27b10af2b93213d36cf44e6e1c5abd19fdd \
+    --hash=sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c \
+    --hash=sha256:2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b \
+    --hash=sha256:33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8 \
+    --hash=sha256:400e720fe168c0f8521520190686ef8ef033fb19fc493da09779e592861b78c6 \
+    --hash=sha256:40741994320b232529c802f8bc86da4e1aa9f413db394617b9a256ae0f9a7f77 \
+    --hash=sha256:465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff \
+    --hash=sha256:4a8f6e44de52d5e6c657c9fe83b562f5f4256d8ebbfe4ff922c495620a7f6cea \
+    --hash=sha256:4e340144ad7ae1533cb897d406382b4b6fede8890a03738ff1683af800d54192 \
+    --hash=sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249 \
+    --hash=sha256:6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee \
+    --hash=sha256:7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4 \
+    --hash=sha256:889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98 \
+    --hash=sha256:8d57ca8095a641b8237d5b079147646153d22552f1c637fd3ba7f4b0b29167a8 \
+    --hash=sha256:8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4 \
+    --hash=sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281 \
+    --hash=sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744 \
+    --hash=sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69 \
+    --hash=sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13 \
+    --hash=sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140 \
+    --hash=sha256:b82ebccc8c8a36f2094e969560a1b836758481f3dc360ce9a3277c65f374285e \
+    --hash=sha256:c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e \
+    --hash=sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc \
+    --hash=sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff \
+    --hash=sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec \
+    --hash=sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2 \
+    --hash=sha256:db2b95f9de79181805df90bedc5a5ab4c165e6ec3fe99f970d0e302f384ad222 \
+    --hash=sha256:e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106 \
+    --hash=sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272 \
+    --hash=sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a \
+    --hash=sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7
     # via -r requirements.txt
 types-jinja2==2.11.9 \
     --hash=sha256:60a1e21e8296979db32f9374d8a239af4cb541ff66447bb915d8ad398f9c63b2 \
@@ -447,9 +472,7 @@ types-jinja2==2.11.9 \
 types-jsonschema==4.21.0.20240118 \
     --hash=sha256:31aae1b5adc0176c1155c2d4f58348b22d92ae64315e9cc83bd6902168839232 \
     --hash=sha256:77a4ac36b0be4f24274d5b9bf0b66208ee771c05f80e34c4641de7d63e8a872d
-    # via
-    #   -r requirements.dev.in
-    #   -r requirements.txt
+    # via -r requirements.dev.in
 types-markupsafe==1.1.10 \
     --hash=sha256:85b3a872683d02aea3a5ac2a8ef590193c344092032f58457287fbf8e06711b1 \
     --hash=sha256:ca2bee0f4faafc45250602567ef38d533e877d2ddca13003b319c551ff5b3cc5
@@ -457,67 +480,114 @@ types-markupsafe==1.1.10 \
 types-pyyaml==6.0.12.12 \
     --hash=sha256:334373d392fde0fdf95af5c3f1661885fa10c52167b14593eb856289e1855062 \
     --hash=sha256:c05bc6c158facb0676674b7f11fe3960db4f389718e19e62bd2b84d6205cfd24
-    # via
-    #   -r requirements.dev.in
-    #   -r requirements.txt
+    # via -r requirements.dev.in
 typing-extensions==4.9.0 \
     --hash=sha256:23478f88c37f27d76ac8aee6c905017a143b0b1b886c3c9f66bc2fd94f9f5783 \
     --hash=sha256:af72aea155e91adfc61c3ae9e0e342dbc0cba726d6cba4b6c72c1f34e47291cd
-    # via
-    #   -r requirements.txt
-    #   mypy
-urllib3==2.2.1 \
-    --hash=sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d \
-    --hash=sha256:d0570876c61ab9e520d776c38acbbb5b05a776d3f9ff98a5c8fd5162a444cf19
+    # via mypy
+urllib3==2.3.0 \
+    --hash=sha256:1cee9ad369867bfdbbb48b7dd50374c0967a0bb7710050facf0dd6911440e3df \
+    --hash=sha256:f8c5449b3cf0861679ce7e0503c7b44b5ec981bec0d1d3795a07f1ba96f0204d
     # via
     #   -r requirements.txt
     #   docker
     #   requests
-zstandard==0.22.0 \
-    --hash=sha256:11f0d1aab9516a497137b41e3d3ed4bbf7b2ee2abc79e5c8b010ad286d7464bd \
-    --hash=sha256:1958100b8a1cc3f27fa21071a55cb2ed32e9e5df4c3c6e661c193437f171cba2 \
-    --hash=sha256:1a90ba9a4c9c884bb876a14be2b1d216609385efb180393df40e5172e7ecf356 \
-    --hash=sha256:1d43501f5f31e22baf822720d82b5547f8a08f5386a883b32584a185675c8fbf \
-    --hash=sha256:23d2b3c2b8e7e5a6cb7922f7c27d73a9a615f0a5ab5d0e03dd533c477de23004 \
-    --hash=sha256:2612e9bb4977381184bb2463150336d0f7e014d6bb5d4a370f9a372d21916f69 \
-    --hash=sha256:275df437ab03f8c033b8a2c181e51716c32d831082d93ce48002a5227ec93019 \
-    --hash=sha256:2ac9957bc6d2403c4772c890916bf181b2653640da98f32e04b96e4d6fb3252a \
-    --hash=sha256:2b11ea433db22e720758cba584c9d661077121fcf60ab43351950ded20283440 \
-    --hash=sha256:2fdd53b806786bd6112d97c1f1e7841e5e4daa06810ab4b284026a1a0e484c0b \
-    --hash=sha256:33591d59f4956c9812f8063eff2e2c0065bc02050837f152574069f5f9f17775 \
-    --hash=sha256:36a47636c3de227cd765e25a21dc5dace00539b82ddd99ee36abae38178eff9e \
-    --hash=sha256:39b2853efc9403927f9065cc48c9980649462acbdf81cd4f0cb773af2fd734bc \
-    --hash=sha256:3db41c5e49ef73641d5111554e1d1d3af106410a6c1fb52cf68912ba7a343a0d \
-    --hash=sha256:445b47bc32de69d990ad0f34da0e20f535914623d1e506e74d6bc5c9dc40bb09 \
-    --hash=sha256:466e6ad8caefb589ed281c076deb6f0cd330e8bc13c5035854ffb9c2014b118c \
-    --hash=sha256:48f260e4c7294ef275744210a4010f116048e0c95857befb7462e033f09442fe \
-    --hash=sha256:4ac59d5d6910b220141c1737b79d4a5aa9e57466e7469a012ed42ce2d3995e88 \
-    --hash=sha256:53866a9d8ab363271c9e80c7c2e9441814961d47f88c9bc3b248142c32141d94 \
-    --hash=sha256:589402548251056878d2e7c8859286eb91bd841af117dbe4ab000e6450987e08 \
-    --hash=sha256:68953dc84b244b053c0d5f137a21ae8287ecf51b20872eccf8eaac0302d3e3b0 \
-    --hash=sha256:6c25b8eb733d4e741246151d895dd0308137532737f337411160ff69ca24f93a \
-    --hash=sha256:7034d381789f45576ec3f1fa0e15d741828146439228dc3f7c59856c5bcd3292 \
-    --hash=sha256:73a1d6bd01961e9fd447162e137ed949c01bdb830dfca487c4a14e9742dccc93 \
-    --hash=sha256:8226a33c542bcb54cd6bd0a366067b610b41713b64c9abec1bc4533d69f51e70 \
-    --hash=sha256:888196c9c8893a1e8ff5e89b8f894e7f4f0e64a5af4d8f3c410f0319128bb2f8 \
-    --hash=sha256:88c5b4b47a8a138338a07fc94e2ba3b1535f69247670abfe422de4e0b344aae2 \
-    --hash=sha256:8a1b2effa96a5f019e72874969394edd393e2fbd6414a8208fea363a22803b45 \
-    --hash=sha256:93e1856c8313bc688d5df069e106a4bc962eef3d13372020cc6e3ebf5e045202 \
-    --hash=sha256:9501f36fac6b875c124243a379267d879262480bf85b1dbda61f5ad4d01b75a3 \
-    --hash=sha256:959665072bd60f45c5b6b5d711f15bdefc9849dd5da9fb6c873e35f5d34d8cfb \
-    --hash=sha256:a1d67d0d53d2a138f9e29d8acdabe11310c185e36f0a848efa104d4e40b808e4 \
-    --hash=sha256:a493d470183ee620a3df1e6e55b3e4de8143c0ba1b16f3ded83208ea8ddfd91d \
-    --hash=sha256:a7ccf5825fd71d4542c8ab28d4d482aace885f5ebe4b40faaa290eed8e095a4c \
-    --hash=sha256:a88b7df61a292603e7cd662d92565d915796b094ffb3d206579aaebac6b85d5f \
-    --hash=sha256:a97079b955b00b732c6f280d5023e0eefe359045e8b83b08cf0333af9ec78f26 \
-    --hash=sha256:d22fdef58976457c65e2796e6730a3ea4a254f3ba83777ecfc8592ff8d77d303 \
-    --hash=sha256:d75f693bb4e92c335e0645e8845e553cd09dc91616412d1d4650da835b5449df \
-    --hash=sha256:d8593f8464fb64d58e8cb0b905b272d40184eac9a18d83cf8c10749c3eafcd7e \
-    --hash=sha256:d8fff0f0c1d8bc5d866762ae95bd99d53282337af1be9dc0d88506b340e74b73 \
-    --hash=sha256:de20a212ef3d00d609d0b22eb7cc798d5a69035e81839f549b538eff4105d01c \
-    --hash=sha256:e9e9d4e2e336c529d4c435baad846a181e39a982f823f7e4495ec0b0ec8538d2 \
-    --hash=sha256:f058a77ef0ece4e210bb0450e68408d4223f728b109764676e1a13537d056bb0 \
-    --hash=sha256:f1a4b358947a65b94e2501ce3e078bbc929b039ede4679ddb0460829b12f7375 \
-    --hash=sha256:f9b2cde1cd1b2a10246dbc143ba49d942d14fb3d2b4bccf4618d475c65464912 \
-    --hash=sha256:fe3390c538f12437b859d815040763abc728955a52ca6ff9c5d4ac707c4ad98e
+zstandard==0.23.0 \
+    --hash=sha256:034b88913ecc1b097f528e42b539453fa82c3557e414b3de9d5632c80439a473 \
+    --hash=sha256:0a7f0804bb3799414af278e9ad51be25edf67f78f916e08afdb983e74161b916 \
+    --hash=sha256:11e3bf3c924853a2d5835b24f03eeba7fc9b07d8ca499e247e06ff5676461a15 \
+    --hash=sha256:12a289832e520c6bd4dcaad68e944b86da3bad0d339ef7989fb7e88f92e96072 \
+    --hash=sha256:1516c8c37d3a053b01c1c15b182f3b5f5eef19ced9b930b684a73bad121addf4 \
+    --hash=sha256:157e89ceb4054029a289fb504c98c6a9fe8010f1680de0201b3eb5dc20aa6d9e \
+    --hash=sha256:1bfe8de1da6d104f15a60d4a8a768288f66aa953bbe00d027398b93fb9680b26 \
+    --hash=sha256:1e172f57cd78c20f13a3415cc8dfe24bf388614324d25539146594c16d78fcc8 \
+    --hash=sha256:1fd7e0f1cfb70eb2f95a19b472ee7ad6d9a0a992ec0ae53286870c104ca939e5 \
+    --hash=sha256:203d236f4c94cd8379d1ea61db2fce20730b4c38d7f1c34506a31b34edc87bdd \
+    --hash=sha256:27d3ef2252d2e62476389ca8f9b0cf2bbafb082a3b6bfe9d90cbcbb5529ecf7c \
+    --hash=sha256:29a2bc7c1b09b0af938b7a8343174b987ae021705acabcbae560166567f5a8db \
+    --hash=sha256:2ef230a8fd217a2015bc91b74f6b3b7d6522ba48be29ad4ea0ca3a3775bf7dd5 \
+    --hash=sha256:2ef3775758346d9ac6214123887d25c7061c92afe1f2b354f9388e9e4d48acfc \
+    --hash=sha256:2f146f50723defec2975fb7e388ae3a024eb7151542d1599527ec2aa9cacb152 \
+    --hash=sha256:2fb4535137de7e244c230e24f9d1ec194f61721c86ebea04e1581d9d06ea1269 \
+    --hash=sha256:32ba3b5ccde2d581b1e6aa952c836a6291e8435d788f656fe5976445865ae045 \
+    --hash=sha256:34895a41273ad33347b2fc70e1bff4240556de3c46c6ea430a7ed91f9042aa4e \
+    --hash=sha256:379b378ae694ba78cef921581ebd420c938936a153ded602c4fea612b7eaa90d \
+    --hash=sha256:38302b78a850ff82656beaddeb0bb989a0322a8bbb1bf1ab10c17506681d772a \
+    --hash=sha256:3aa014d55c3af933c1315eb4bb06dd0459661cc0b15cd61077afa6489bec63bb \
+    --hash=sha256:4051e406288b8cdbb993798b9a45c59a4896b6ecee2f875424ec10276a895740 \
+    --hash=sha256:40b33d93c6eddf02d2c19f5773196068d875c41ca25730e8288e9b672897c105 \
+    --hash=sha256:43da0f0092281bf501f9c5f6f3b4c975a8a0ea82de49ba3f7100e64d422a1274 \
+    --hash=sha256:445e4cb5048b04e90ce96a79b4b63140e3f4ab5f662321975679b5f6360b90e2 \
+    --hash=sha256:48ef6a43b1846f6025dde6ed9fee0c24e1149c1c25f7fb0a0585572b2f3adc58 \
+    --hash=sha256:50a80baba0285386f97ea36239855f6020ce452456605f262b2d33ac35c7770b \
+    --hash=sha256:519fbf169dfac1222a76ba8861ef4ac7f0530c35dd79ba5727014613f91613d4 \
+    --hash=sha256:53dd9d5e3d29f95acd5de6802e909ada8d8d8cfa37a3ac64836f3bc4bc5512db \
+    --hash=sha256:53ea7cdc96c6eb56e76bb06894bcfb5dfa93b7adcf59d61c6b92674e24e2dd5e \
+    --hash=sha256:576856e8594e6649aee06ddbfc738fec6a834f7c85bf7cadd1c53d4a58186ef9 \
+    --hash=sha256:59556bf80a7094d0cfb9f5e50bb2db27fefb75d5138bb16fb052b61b0e0eeeb0 \
+    --hash=sha256:5d41d5e025f1e0bccae4928981e71b2334c60f580bdc8345f824e7c0a4c2a813 \
+    --hash=sha256:61062387ad820c654b6a6b5f0b94484fa19515e0c5116faf29f41a6bc91ded6e \
+    --hash=sha256:61f89436cbfede4bc4e91b4397eaa3e2108ebe96d05e93d6ccc95ab5714be512 \
+    --hash=sha256:62136da96a973bd2557f06ddd4e8e807f9e13cbb0bfb9cc06cfe6d98ea90dfe0 \
+    --hash=sha256:64585e1dba664dc67c7cdabd56c1e5685233fbb1fc1966cfba2a340ec0dfff7b \
+    --hash=sha256:65308f4b4890aa12d9b6ad9f2844b7ee42c7f7a4fd3390425b242ffc57498f48 \
+    --hash=sha256:66b689c107857eceabf2cf3d3fc699c3c0fe8ccd18df2219d978c0283e4c508a \
+    --hash=sha256:6a41c120c3dbc0d81a8e8adc73312d668cd34acd7725f036992b1b72d22c1772 \
+    --hash=sha256:6f77fa49079891a4aab203d0b1744acc85577ed16d767b52fc089d83faf8d8ed \
+    --hash=sha256:72c68dda124a1a138340fb62fa21b9bf4848437d9ca60bd35db36f2d3345f373 \
+    --hash=sha256:752bf8a74412b9892f4e5b58f2f890a039f57037f52c89a740757ebd807f33ea \
+    --hash=sha256:76e79bc28a65f467e0409098fa2c4376931fd3207fbeb6b956c7c476d53746dd \
+    --hash=sha256:774d45b1fac1461f48698a9d4b5fa19a69d47ece02fa469825b442263f04021f \
+    --hash=sha256:77da4c6bfa20dd5ea25cbf12c76f181a8e8cd7ea231c673828d0386b1740b8dc \
+    --hash=sha256:77ea385f7dd5b5676d7fd943292ffa18fbf5c72ba98f7d09fc1fb9e819b34c23 \
+    --hash=sha256:80080816b4f52a9d886e67f1f96912891074903238fe54f2de8b786f86baded2 \
+    --hash=sha256:80a539906390591dd39ebb8d773771dc4db82ace6372c4d41e2d293f8e32b8db \
+    --hash=sha256:82d17e94d735c99621bf8ebf9995f870a6b3e6d14543b99e201ae046dfe7de70 \
+    --hash=sha256:837bb6764be6919963ef41235fd56a6486b132ea64afe5fafb4cb279ac44f259 \
+    --hash=sha256:84433dddea68571a6d6bd4fbf8ff398236031149116a7fff6f777ff95cad3df9 \
+    --hash=sha256:8c24f21fa2af4bb9f2c492a86fe0c34e6d2c63812a839590edaf177b7398f700 \
+    --hash=sha256:8ed7d27cb56b3e058d3cf684d7200703bcae623e1dcc06ed1e18ecda39fee003 \
+    --hash=sha256:9206649ec587e6b02bd124fb7799b86cddec350f6f6c14bc82a2b70183e708ba \
+    --hash=sha256:983b6efd649723474f29ed42e1467f90a35a74793437d0bc64a5bf482bedfa0a \
+    --hash=sha256:98da17ce9cbf3bfe4617e836d561e433f871129e3a7ac16d6ef4c680f13a839c \
+    --hash=sha256:9c236e635582742fee16603042553d276cca506e824fa2e6489db04039521e90 \
+    --hash=sha256:9da6bc32faac9a293ddfdcb9108d4b20416219461e4ec64dfea8383cac186690 \
+    --hash=sha256:a05e6d6218461eb1b4771d973728f0133b2a4613a6779995df557f70794fd60f \
+    --hash=sha256:a0817825b900fcd43ac5d05b8b3079937073d2b1ff9cf89427590718b70dd840 \
+    --hash=sha256:a4ae99c57668ca1e78597d8b06d5af837f377f340f4cce993b551b2d7731778d \
+    --hash=sha256:a8c86881813a78a6f4508ef9daf9d4995b8ac2d147dcb1a450448941398091c9 \
+    --hash=sha256:a8fffdbd9d1408006baaf02f1068d7dd1f016c6bcb7538682622c556e7b68e35 \
+    --hash=sha256:a9b07268d0c3ca5c170a385a0ab9fb7fdd9f5fd866be004c4ea39e44edce47dd \
+    --hash=sha256:ab19a2d91963ed9e42b4e8d77cd847ae8381576585bad79dbd0a8837a9f6620a \
+    --hash=sha256:ac184f87ff521f4840e6ea0b10c0ec90c6b1dcd0bad2f1e4a9a1b4fa177982ea \
+    --hash=sha256:b0e166f698c5a3e914947388c162be2583e0c638a4703fc6a543e23a88dea3c1 \
+    --hash=sha256:b2170c7e0367dde86a2647ed5b6f57394ea7f53545746104c6b09fc1f4223573 \
+    --hash=sha256:b2d8c62d08e7255f68f7a740bae85b3c9b8e5466baa9cbf7f57f1cde0ac6bc09 \
+    --hash=sha256:b4567955a6bc1b20e9c31612e615af6b53733491aeaa19a6b3b37f3b65477094 \
+    --hash=sha256:b69bb4f51daf461b15e7b3db033160937d3ff88303a7bc808c67bbc1eaf98c78 \
+    --hash=sha256:b8c0bd73aeac689beacd4e7667d48c299f61b959475cdbb91e7d3d88d27c56b9 \
+    --hash=sha256:be9b5b8659dff1f913039c2feee1aca499cfbc19e98fa12bc85e037c17ec6ca5 \
+    --hash=sha256:bf0a05b6059c0528477fba9054d09179beb63744355cab9f38059548fedd46a9 \
+    --hash=sha256:c16842b846a8d2a145223f520b7e18b57c8f476924bda92aeee3a88d11cfc391 \
+    --hash=sha256:c363b53e257246a954ebc7c488304b5592b9c53fbe74d03bc1c64dda153fb847 \
+    --hash=sha256:c7c517d74bea1a6afd39aa612fa025e6b8011982a0897768a2f7c8ab4ebb78a2 \
+    --hash=sha256:d20fd853fbb5807c8e84c136c278827b6167ded66c72ec6f9a14b863d809211c \
+    --hash=sha256:d2240ddc86b74966c34554c49d00eaafa8200a18d3a5b6ffbf7da63b11d74ee2 \
+    --hash=sha256:d477ed829077cd945b01fc3115edd132c47e6540ddcd96ca169facff28173057 \
+    --hash=sha256:d50d31bfedd53a928fed6707b15a8dbeef011bb6366297cc435accc888b27c20 \
+    --hash=sha256:dc1d33abb8a0d754ea4763bad944fd965d3d95b5baef6b121c0c9013eaf1907d \
+    --hash=sha256:dc5d1a49d3f8262be192589a4b72f0d03b72dcf46c51ad5852a4fdc67be7b9e4 \
+    --hash=sha256:e2d1a054f8f0a191004675755448d12be47fa9bebbcffa3cdf01db19f2d30a54 \
+    --hash=sha256:e7792606d606c8df5277c32ccb58f29b9b8603bf83b48639b7aedf6df4fe8171 \
+    --hash=sha256:ed1708dbf4d2e3a1c5c69110ba2b4eb6678262028afd6c6fbcc5a8dac9cda68e \
+    --hash=sha256:f2d4380bf5f62daabd7b751ea2339c1a21d1c9463f1feb7fc2bdcea2c29c3160 \
+    --hash=sha256:f3513916e8c645d0610815c257cbfd3242adfd5c4cfa78be514e5a3ebb42a41b \
+    --hash=sha256:f8346bfa098532bc1fb6c7ef06783e969d87a99dd1d2a5a18a892c1d7a643c58 \
+    --hash=sha256:f83fa6cae3fff8e98691248c9320356971b59678a17f20656a9e59cd32cee6d8 \
+    --hash=sha256:fa6ce8b52c5987b3e34d5674b0ab529a4602b632ebab0a93b07bfb4dfc8f8a33 \
+    --hash=sha256:fb2b1ecfef1e67897d336de3a0e3f52478182d6a47eda86cbd42504c5cbd009a \
+    --hash=sha256:fc9ca1c9718cb3b06634c7c8dec57d24e9438b2aa9a0f02b8bb36bf478538880 \
+    --hash=sha256:fd30d9c67d13d891f2360b2a120186729c111238ac63b43dbd37a5a40670b8ca \
+    --hash=sha256:fd7699e8fd9969f455ef2926221e0233f81a2542921471382e77a9e2f2b57f4b \
+    --hash=sha256:fe3b385d996ee0822fd46528d9f0443b880d4d05528fd26a9119a54ec3f91c69
     # via -r requirements.txt
diff --git a/requirements.txt b/requirements.txt
index 2bc39eb7..2baa3444 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,468 +1,504 @@
-#
-# This file is autogenerated by pip-compile with Python 3.11
-# by the following command:
-#
-#    pip-compile --generate-hashes requirements.in
-#
-attrs==23.2.0 \
-    --hash=sha256:935dc3b529c262f6cf76e50877d35a4bd3c1de194fd41f47a2b7ae8f19971f30 \
-    --hash=sha256:99b87a485a5820b23b879f04c2305b44b951b502fd64be915879d77a7e8fc6f1
+# This file was autogenerated by uv via the following command:
+#    uv pip compile --generate-hashes requirements.in -o requirements.txt
+attrs==24.3.0 \
+    --hash=sha256:8f5c07333d543103541ba7be0e2ce16eeee8130cb0b3f9238ab904ce1e85baff \
+    --hash=sha256:ac96cd038792094f438ad1f6ff80837353805ac950cd2aa0e0625ef19850c308
     # via
     #   jsonschema
     #   referencing
-certifi==2024.2.2 \
-    --hash=sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f \
-    --hash=sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1
+certifi==2024.12.14 \
+    --hash=sha256:1275f7a45be9464efc1173084eaa30f866fe2e47d389406136d332ed4967ec56 \
+    --hash=sha256:b650d30f370c2b724812bee08008be0c4163b163ddaec3f2546c1caf65f191db
     # via requests
-charset-normalizer==3.3.2 \
-    --hash=sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027 \
-    --hash=sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087 \
-    --hash=sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786 \
-    --hash=sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8 \
-    --hash=sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09 \
-    --hash=sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185 \
-    --hash=sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574 \
-    --hash=sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e \
-    --hash=sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519 \
-    --hash=sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898 \
-    --hash=sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269 \
-    --hash=sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3 \
-    --hash=sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f \
-    --hash=sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6 \
-    --hash=sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8 \
-    --hash=sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a \
-    --hash=sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73 \
-    --hash=sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc \
-    --hash=sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714 \
-    --hash=sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2 \
-    --hash=sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc \
-    --hash=sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce \
-    --hash=sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d \
-    --hash=sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e \
-    --hash=sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6 \
-    --hash=sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269 \
-    --hash=sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96 \
-    --hash=sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d \
-    --hash=sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a \
-    --hash=sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4 \
-    --hash=sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77 \
-    --hash=sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d \
-    --hash=sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0 \
-    --hash=sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed \
-    --hash=sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068 \
-    --hash=sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac \
-    --hash=sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25 \
-    --hash=sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8 \
-    --hash=sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab \
-    --hash=sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26 \
-    --hash=sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2 \
-    --hash=sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db \
-    --hash=sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f \
-    --hash=sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5 \
-    --hash=sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99 \
-    --hash=sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c \
-    --hash=sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d \
-    --hash=sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811 \
-    --hash=sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa \
-    --hash=sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a \
-    --hash=sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03 \
-    --hash=sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b \
-    --hash=sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04 \
-    --hash=sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c \
-    --hash=sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001 \
-    --hash=sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458 \
-    --hash=sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389 \
-    --hash=sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99 \
-    --hash=sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985 \
-    --hash=sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537 \
-    --hash=sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238 \
-    --hash=sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f \
-    --hash=sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d \
-    --hash=sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796 \
-    --hash=sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a \
-    --hash=sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143 \
-    --hash=sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8 \
-    --hash=sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c \
-    --hash=sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5 \
-    --hash=sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5 \
-    --hash=sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711 \
-    --hash=sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4 \
-    --hash=sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6 \
-    --hash=sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c \
-    --hash=sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7 \
-    --hash=sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4 \
-    --hash=sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b \
-    --hash=sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae \
-    --hash=sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12 \
-    --hash=sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c \
-    --hash=sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae \
-    --hash=sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8 \
-    --hash=sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887 \
-    --hash=sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b \
-    --hash=sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4 \
-    --hash=sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f \
-    --hash=sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5 \
-    --hash=sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33 \
-    --hash=sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519 \
-    --hash=sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561
+charset-normalizer==3.4.1 \
+    --hash=sha256:0167ddc8ab6508fe81860a57dd472b2ef4060e8d378f0cc555707126830f2537 \
+    --hash=sha256:01732659ba9b5b873fc117534143e4feefecf3b2078b0a6a2e925271bb6f4cfa \
+    --hash=sha256:01ad647cdd609225c5350561d084b42ddf732f4eeefe6e678765636791e78b9a \
+    --hash=sha256:04432ad9479fa40ec0f387795ddad4437a2b50417c69fa275e212933519ff294 \
+    --hash=sha256:0907f11d019260cdc3f94fbdb23ff9125f6b5d1039b76003b5b0ac9d6a6c9d5b \
+    --hash=sha256:0924e81d3d5e70f8126529951dac65c1010cdf117bb75eb02dd12339b57749dd \
+    --hash=sha256:09b26ae6b1abf0d27570633b2b078a2a20419c99d66fb2823173d73f188ce601 \
+    --hash=sha256:09b5e6733cbd160dcc09589227187e242a30a49ca5cefa5a7edd3f9d19ed53fd \
+    --hash=sha256:0af291f4fe114be0280cdd29d533696a77b5b49cfde5467176ecab32353395c4 \
+    --hash=sha256:0f55e69f030f7163dffe9fd0752b32f070566451afe180f99dbeeb81f511ad8d \
+    --hash=sha256:1a2bc9f351a75ef49d664206d51f8e5ede9da246602dc2d2726837620ea034b2 \
+    --hash=sha256:22e14b5d70560b8dd51ec22863f370d1e595ac3d024cb8ad7d308b4cd95f8313 \
+    --hash=sha256:234ac59ea147c59ee4da87a0c0f098e9c8d169f4dc2a159ef720f1a61bbe27cd \
+    --hash=sha256:2369eea1ee4a7610a860d88f268eb39b95cb588acd7235e02fd5a5601773d4fa \
+    --hash=sha256:237bdbe6159cff53b4f24f397d43c6336c6b0b42affbe857970cefbb620911c8 \
+    --hash=sha256:28bf57629c75e810b6ae989f03c0828d64d6b26a5e205535585f96093e405ed1 \
+    --hash=sha256:2967f74ad52c3b98de4c3b32e1a44e32975e008a9cd2a8cc8966d6a5218c5cb2 \
+    --hash=sha256:2a75d49014d118e4198bcee5ee0a6f25856b29b12dbf7cd012791f8a6cc5c496 \
+    --hash=sha256:2bdfe3ac2e1bbe5b59a1a63721eb3b95fc9b6817ae4a46debbb4e11f6232428d \
+    --hash=sha256:2d074908e1aecee37a7635990b2c6d504cd4766c7bc9fc86d63f9c09af3fa11b \
+    --hash=sha256:2fb9bd477fdea8684f78791a6de97a953c51831ee2981f8e4f583ff3b9d9687e \
+    --hash=sha256:311f30128d7d333eebd7896965bfcfbd0065f1716ec92bd5638d7748eb6f936a \
+    --hash=sha256:329ce159e82018d646c7ac45b01a430369d526569ec08516081727a20e9e4af4 \
+    --hash=sha256:345b0426edd4e18138d6528aed636de7a9ed169b4aaf9d61a8c19e39d26838ca \
+    --hash=sha256:363e2f92b0f0174b2f8238240a1a30142e3db7b957a5dd5689b0e75fb717cc78 \
+    --hash=sha256:3a3bd0dcd373514dcec91c411ddb9632c0d7d92aed7093b8c3bbb6d69ca74408 \
+    --hash=sha256:3bed14e9c89dcb10e8f3a29f9ccac4955aebe93c71ae803af79265c9ca5644c5 \
+    --hash=sha256:44251f18cd68a75b56585dd00dae26183e102cd5e0f9f1466e6df5da2ed64ea3 \
+    --hash=sha256:44ecbf16649486d4aebafeaa7ec4c9fed8b88101f4dd612dcaf65d5e815f837f \
+    --hash=sha256:4532bff1b8421fd0a320463030c7520f56a79c9024a4e88f01c537316019005a \
+    --hash=sha256:49402233c892a461407c512a19435d1ce275543138294f7ef013f0b63d5d3765 \
+    --hash=sha256:4c0907b1928a36d5a998d72d64d8eaa7244989f7aaaf947500d3a800c83a3fd6 \
+    --hash=sha256:4d86f7aff21ee58f26dcf5ae81a9addbd914115cdebcbb2217e4f0ed8982e146 \
+    --hash=sha256:5777ee0881f9499ed0f71cc82cf873d9a0ca8af166dfa0af8ec4e675b7df48e6 \
+    --hash=sha256:5df196eb874dae23dcfb968c83d4f8fdccb333330fe1fc278ac5ceeb101003a9 \
+    --hash=sha256:619a609aa74ae43d90ed2e89bdd784765de0a25ca761b93e196d938b8fd1dbbd \
+    --hash=sha256:6e27f48bcd0957c6d4cb9d6fa6b61d192d0b13d5ef563e5f2ae35feafc0d179c \
+    --hash=sha256:6ff8a4a60c227ad87030d76e99cd1698345d4491638dfa6673027c48b3cd395f \
+    --hash=sha256:73d94b58ec7fecbc7366247d3b0b10a21681004153238750bb67bd9012414545 \
+    --hash=sha256:7461baadb4dc00fd9e0acbe254e3d7d2112e7f92ced2adc96e54ef6501c5f176 \
+    --hash=sha256:75832c08354f595c760a804588b9357d34ec00ba1c940c15e31e96d902093770 \
+    --hash=sha256:7709f51f5f7c853f0fb938bcd3bc59cdfdc5203635ffd18bf354f6967ea0f824 \
+    --hash=sha256:78baa6d91634dfb69ec52a463534bc0df05dbd546209b79a3880a34487f4b84f \
+    --hash=sha256:7974a0b5ecd505609e3b19742b60cee7aa2aa2fb3151bc917e6e2646d7667dcf \
+    --hash=sha256:7a4f97a081603d2050bfaffdefa5b02a9ec823f8348a572e39032caa8404a487 \
+    --hash=sha256:7b1bef6280950ee6c177b326508f86cad7ad4dff12454483b51d8b7d673a2c5d \
+    --hash=sha256:7d053096f67cd1241601111b698f5cad775f97ab25d81567d3f59219b5f1adbd \
+    --hash=sha256:804a4d582ba6e5b747c625bf1255e6b1507465494a40a2130978bda7b932c90b \
+    --hash=sha256:807f52c1f798eef6cf26beb819eeb8819b1622ddfeef9d0977a8502d4db6d534 \
+    --hash=sha256:80ed5e856eb7f30115aaf94e4a08114ccc8813e6ed1b5efa74f9f82e8509858f \
+    --hash=sha256:8417cb1f36cc0bc7eaba8ccb0e04d55f0ee52df06df3ad55259b9a323555fc8b \
+    --hash=sha256:8436c508b408b82d87dc5f62496973a1805cd46727c34440b0d29d8a2f50a6c9 \
+    --hash=sha256:89149166622f4db9b4b6a449256291dc87a99ee53151c74cbd82a53c8c2f6ccd \
+    --hash=sha256:8bfa33f4f2672964266e940dd22a195989ba31669bd84629f05fab3ef4e2d125 \
+    --hash=sha256:8c60ca7339acd497a55b0ea5d506b2a2612afb2826560416f6894e8b5770d4a9 \
+    --hash=sha256:91b36a978b5ae0ee86c394f5a54d6ef44db1de0815eb43de826d41d21e4af3de \
+    --hash=sha256:955f8851919303c92343d2f66165294848d57e9bba6cf6e3625485a70a038d11 \
+    --hash=sha256:97f68b8d6831127e4787ad15e6757232e14e12060bec17091b85eb1486b91d8d \
+    --hash=sha256:9b23ca7ef998bc739bf6ffc077c2116917eabcc901f88da1b9856b210ef63f35 \
+    --hash=sha256:9f0b8b1c6d84c8034a44893aba5e767bf9c7a211e313a9605d9c617d7083829f \
+    --hash=sha256:aabfa34badd18f1da5ec1bc2715cadc8dca465868a4e73a0173466b688f29dda \
+    --hash=sha256:ab36c8eb7e454e34e60eb55ca5d241a5d18b2c6244f6827a30e451c42410b5f7 \
+    --hash=sha256:b010a7a4fd316c3c484d482922d13044979e78d1861f0e0650423144c616a46a \
+    --hash=sha256:b1ac5992a838106edb89654e0aebfc24f5848ae2547d22c2c3f66454daa11971 \
+    --hash=sha256:b7b2d86dd06bfc2ade3312a83a5c364c7ec2e3498f8734282c6c3d4b07b346b8 \
+    --hash=sha256:b97e690a2118911e39b4042088092771b4ae3fc3aa86518f84b8cf6888dbdb41 \
+    --hash=sha256:bc2722592d8998c870fa4e290c2eec2c1569b87fe58618e67d38b4665dfa680d \
+    --hash=sha256:c0429126cf75e16c4f0ad00ee0eae4242dc652290f940152ca8c75c3a4b6ee8f \
+    --hash=sha256:c30197aa96e8eed02200a83fba2657b4c3acd0f0aa4bdc9f6c1af8e8962e0757 \
+    --hash=sha256:c4c3e6da02df6fa1410a7680bd3f63d4f710232d3139089536310d027950696a \
+    --hash=sha256:c75cb2a3e389853835e84a2d8fb2b81a10645b503eca9bcb98df6b5a43eb8886 \
+    --hash=sha256:c96836c97b1238e9c9e3fe90844c947d5afbf4f4c92762679acfe19927d81d77 \
+    --hash=sha256:d7f50a1f8c450f3925cb367d011448c39239bb3eb4117c36a6d354794de4ce76 \
+    --hash=sha256:d973f03c0cb71c5ed99037b870f2be986c3c05e63622c017ea9816881d2dd247 \
+    --hash=sha256:d98b1668f06378c6dbefec3b92299716b931cd4e6061f3c875a71ced1780ab85 \
+    --hash=sha256:d9c3cdf5390dcd29aa8056d13e8e99526cda0305acc038b96b30352aff5ff2bb \
+    --hash=sha256:dad3e487649f498dd991eeb901125411559b22e8d7ab25d3aeb1af367df5efd7 \
+    --hash=sha256:dccbe65bd2f7f7ec22c4ff99ed56faa1e9f785482b9bbd7c717e26fd723a1d1e \
+    --hash=sha256:dd78cfcda14a1ef52584dbb008f7ac81c1328c0f58184bf9a84c49c605002da6 \
+    --hash=sha256:e218488cd232553829be0664c2292d3af2eeeb94b32bea483cf79ac6a694e037 \
+    --hash=sha256:e358e64305fe12299a08e08978f51fc21fac060dcfcddd95453eabe5b93ed0e1 \
+    --hash=sha256:ea0d8d539afa5eb2728aa1932a988a9a7af94f18582ffae4bc10b3fbdad0626e \
+    --hash=sha256:eab677309cdb30d047996b36d34caeda1dc91149e4fdca0b1a039b3f79d9a807 \
+    --hash=sha256:eb8178fe3dba6450a3e024e95ac49ed3400e506fd4e9e5c32d30adda88cbd407 \
+    --hash=sha256:ecddf25bee22fe4fe3737a399d0d177d72bc22be6913acfab364b40bce1ba83c \
+    --hash=sha256:eea6ee1db730b3483adf394ea72f808b6e18cf3cb6454b4d86e04fa8c4327a12 \
+    --hash=sha256:f08ff5e948271dc7e18a35641d2f11a4cd8dfd5634f55228b691e62b37125eb3 \
+    --hash=sha256:f30bf9fd9be89ecb2360c7d94a711f00c09b976258846efe40db3d05828e8089 \
+    --hash=sha256:fa88b843d6e211393a37219e6a1c1df99d35e8fd90446f1118f4216e307e48cd \
+    --hash=sha256:fc54db6c8593ef7d4b2a331b58653356cf04f67c960f584edb7c3d8c97e8f39e \
+    --hash=sha256:fd4ec41f914fa74ad1b8304bbc634b3de73d2a0889bd32076342a573e0779e00 \
+    --hash=sha256:ffc9202a29ab3920fa812879e95a9e78b2465fd10be7fcbd042899695d75e616
     # via requests
-docker==7.0.0 \
-    --hash=sha256:12ba681f2777a0ad28ffbcc846a69c31b4dfd9752b47eb425a274ee269c5e14b \
-    --hash=sha256:323736fb92cd9418fc5e7133bc953e11a9da04f4483f828b527db553f1e7e5a3
+docker==7.1.0 \
+    --hash=sha256:ad8c70e6e3f8926cb8a92619b832b4ea5299e2831c14284663184e200546fa6c \
+    --hash=sha256:c96b93b7f0a746f9e77d325bcfb87422a3d8bd4f03136ae8a85b37f1898d5fc0
     # via -r requirements.in
-idna==3.6 \
-    --hash=sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca \
-    --hash=sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f
+idna==3.10 \
+    --hash=sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9 \
+    --hash=sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3
     # via requests
-jinja2==3.1.3 \
-    --hash=sha256:7d6d50dd97d52cbc355597bd845fabfbac3f551e1f99619e39a35ce8c370b5fa \
-    --hash=sha256:ac8bd6544d4bb2c9792bf3a159e80bba8fda7f07e81bc3aed565432d5925ba90
+jinja2==3.1.5 \
+    --hash=sha256:8fefff8dc3034e27bb80d67c671eb8a9bc424c0ef4c0826edbff304cceff43bb \
+    --hash=sha256:aba0f4dc9ed8013c424088f68a5c226f7d6097ed89b246d7749c2ec4175c6adb
     # via -r requirements.in
-jsonschema==4.21.1 \
-    --hash=sha256:7996507afae316306f9e2290407761157c6f78002dcf7419acb99822143d1c6f \
-    --hash=sha256:85727c00279f5fa6bedbe6238d2aa6403bedd8b4864ab11207d07df3cc1b2ee5
+jsonschema==4.23.0 \
+    --hash=sha256:d71497fef26351a33265337fa77ffeb82423f3ea21283cd9467bb03999266bc4 \
+    --hash=sha256:fbadb6f8b144a8f8cf9f0b89ba94501d143e50411a1278633f56a7acf7fd5566
     # via -r requirements.in
-jsonschema-specifications==2023.12.1 \
-    --hash=sha256:48a76787b3e70f5ed53f1160d2b81f586e4ca6d1548c5de7085d1682674764cc \
-    --hash=sha256:87e4fdf3a94858b8a2ba2778d9ba57d8a9cafca7c7489c46ba0d30a8bc6a9c3c
+jsonschema-specifications==2024.10.1 \
+    --hash=sha256:0f38b83639958ce1152d02a7f062902c41c8fd20d558b0c34344292d417ae272 \
+    --hash=sha256:a09a0680616357d9a0ecf05c12ad234479f549239d0f5b55f3deea67475da9bf
     # via jsonschema
-markupsafe==2.1.5 \
-    --hash=sha256:00e046b6dd71aa03a41079792f8473dc494d564611a8f89bbbd7cb93295ebdcf \
-    --hash=sha256:075202fa5b72c86ad32dc7d0b56024ebdbcf2048c0ba09f1cde31bfdd57bcfff \
-    --hash=sha256:0e397ac966fdf721b2c528cf028494e86172b4feba51d65f81ffd65c63798f3f \
-    --hash=sha256:17b950fccb810b3293638215058e432159d2b71005c74371d784862b7e4683f3 \
-    --hash=sha256:1f3fbcb7ef1f16e48246f704ab79d79da8a46891e2da03f8783a5b6fa41a9532 \
-    --hash=sha256:2174c595a0d73a3080ca3257b40096db99799265e1c27cc5a610743acd86d62f \
-    --hash=sha256:2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617 \
-    --hash=sha256:2d2d793e36e230fd32babe143b04cec8a8b3eb8a3122d2aceb4a371e6b09b8df \
-    --hash=sha256:30b600cf0a7ac9234b2638fbc0fb6158ba5bdcdf46aeb631ead21248b9affbc4 \
-    --hash=sha256:397081c1a0bfb5124355710fe79478cdbeb39626492b15d399526ae53422b906 \
-    --hash=sha256:3a57fdd7ce31c7ff06cdfbf31dafa96cc533c21e443d57f5b1ecc6cdc668ec7f \
-    --hash=sha256:3c6b973f22eb18a789b1460b4b91bf04ae3f0c4234a0a6aa6b0a92f6f7b951d4 \
-    --hash=sha256:3e53af139f8579a6d5f7b76549125f0d94d7e630761a2111bc431fd820e163b8 \
-    --hash=sha256:4096e9de5c6fdf43fb4f04c26fb114f61ef0bf2e5604b6ee3019d51b69e8c371 \
-    --hash=sha256:4275d846e41ecefa46e2015117a9f491e57a71ddd59bbead77e904dc02b1bed2 \
-    --hash=sha256:4c31f53cdae6ecfa91a77820e8b151dba54ab528ba65dfd235c80b086d68a465 \
-    --hash=sha256:4f11aa001c540f62c6166c7726f71f7573b52c68c31f014c25cc7901deea0b52 \
-    --hash=sha256:5049256f536511ee3f7e1b3f87d1d1209d327e818e6ae1365e8653d7e3abb6a6 \
-    --hash=sha256:58c98fee265677f63a4385256a6d7683ab1832f3ddd1e66fe948d5880c21a169 \
-    --hash=sha256:598e3276b64aff0e7b3451b72e94fa3c238d452e7ddcd893c3ab324717456bad \
-    --hash=sha256:5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2 \
-    --hash=sha256:5dedb4db619ba5a2787a94d877bc8ffc0566f92a01c0ef214865e54ecc9ee5e0 \
-    --hash=sha256:619bc166c4f2de5caa5a633b8b7326fbe98e0ccbfacabd87268a2b15ff73a029 \
-    --hash=sha256:629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f \
-    --hash=sha256:656f7526c69fac7f600bd1f400991cc282b417d17539a1b228617081106feb4a \
-    --hash=sha256:6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced \
-    --hash=sha256:72b6be590cc35924b02c78ef34b467da4ba07e4e0f0454a2c5907f473fc50ce5 \
-    --hash=sha256:7502934a33b54030eaf1194c21c692a534196063db72176b0c4028e140f8f32c \
-    --hash=sha256:7a68b554d356a91cce1236aa7682dc01df0edba8d043fd1ce607c49dd3c1edcf \
-    --hash=sha256:7b2e5a267c855eea6b4283940daa6e88a285f5f2a67f2220203786dfa59b37e9 \
-    --hash=sha256:823b65d8706e32ad2df51ed89496147a42a2a6e01c13cfb6ffb8b1e92bc910bb \
-    --hash=sha256:8590b4ae07a35970728874632fed7bd57b26b0102df2d2b233b6d9d82f6c62ad \
-    --hash=sha256:8dd717634f5a044f860435c1d8c16a270ddf0ef8588d4887037c5028b859b0c3 \
-    --hash=sha256:8dec4936e9c3100156f8a2dc89c4b88d5c435175ff03413b443469c7c8c5f4d1 \
-    --hash=sha256:97cafb1f3cbcd3fd2b6fbfb99ae11cdb14deea0736fc2b0952ee177f2b813a46 \
-    --hash=sha256:a17a92de5231666cfbe003f0e4b9b3a7ae3afb1ec2845aadc2bacc93ff85febc \
-    --hash=sha256:a549b9c31bec33820e885335b451286e2969a2d9e24879f83fe904a5ce59d70a \
-    --hash=sha256:ac07bad82163452a6884fe8fa0963fb98c2346ba78d779ec06bd7a6262132aee \
-    --hash=sha256:ae2ad8ae6ebee9d2d94b17fb62763125f3f374c25618198f40cbb8b525411900 \
-    --hash=sha256:b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5 \
-    --hash=sha256:bc1667f8b83f48511b94671e0e441401371dfd0f0a795c7daa4a3cd1dde55bea \
-    --hash=sha256:bec0a414d016ac1a18862a519e54b2fd0fc8bbfd6890376898a6c0891dd82e9f \
-    --hash=sha256:bf50cd79a75d181c9181df03572cdce0fbb75cc353bc350712073108cba98de5 \
-    --hash=sha256:bff1b4290a66b490a2f4719358c0cdcd9bafb6b8f061e45c7a2460866bf50c2e \
-    --hash=sha256:c061bb86a71b42465156a3ee7bd58c8c2ceacdbeb95d05a99893e08b8467359a \
-    --hash=sha256:c8b29db45f8fe46ad280a7294f5c3ec36dbac9491f2d1c17345be8e69cc5928f \
-    --hash=sha256:ce409136744f6521e39fd8e2a24c53fa18ad67aa5bc7c2cf83645cce5b5c4e50 \
-    --hash=sha256:d050b3361367a06d752db6ead6e7edeb0009be66bc3bae0ee9d97fb326badc2a \
-    --hash=sha256:d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b \
-    --hash=sha256:d9fad5155d72433c921b782e58892377c44bd6252b5af2f67f16b194987338a4 \
-    --hash=sha256:daa4ee5a243f0f20d528d939d06670a298dd39b1ad5f8a72a4275124a7819eff \
-    --hash=sha256:db0b55e0f3cc0be60c1f19efdde9a637c32740486004f20d1cff53c3c0ece4d2 \
-    --hash=sha256:e61659ba32cf2cf1481e575d0462554625196a1f2fc06a1c777d3f48e8865d46 \
-    --hash=sha256:ea3d8a3d18833cf4304cd2fc9cbb1efe188ca9b5efef2bdac7adc20594a0e46b \
-    --hash=sha256:ec6a563cff360b50eed26f13adc43e61bc0c04d94b8be985e6fb24b81f6dcfdf \
-    --hash=sha256:f5dfb42c4604dddc8e4305050aa6deb084540643ed5804d7455b5df8fe16f5e5 \
-    --hash=sha256:fa173ec60341d6bb97a89f5ea19c85c5643c1e7dedebc22f5181eb73573142c5 \
-    --hash=sha256:fa9db3f79de01457b03d4f01b34cf91bc0048eb2c3846ff26f66687c2f6d16ab \
-    --hash=sha256:fce659a462a1be54d2ffcacea5e3ba2d74daa74f30f5f143fe0c58636e355fdd \
-    --hash=sha256:ffee1f21e5ef0d712f9033568f8344d5da8cc2869dbd08d87c84656e6a2d2f68
+markupsafe==3.0.2 \
+    --hash=sha256:0bff5e0ae4ef2e1ae4fdf2dfd5b76c75e5c2fa4132d05fc1b0dabcd20c7e28c4 \
+    --hash=sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30 \
+    --hash=sha256:1225beacc926f536dc82e45f8a4d68502949dc67eea90eab715dea3a21c1b5f0 \
+    --hash=sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9 \
+    --hash=sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396 \
+    --hash=sha256:1a9d3f5f0901fdec14d8d2f66ef7d035f2157240a433441719ac9a3fba440b13 \
+    --hash=sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028 \
+    --hash=sha256:1e084f686b92e5b83186b07e8a17fc09e38fff551f3602b249881fec658d3eca \
+    --hash=sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557 \
+    --hash=sha256:2cb8438c3cbb25e220c2ab33bb226559e7afb3baec11c4f218ffa7308603c832 \
+    --hash=sha256:3169b1eefae027567d1ce6ee7cae382c57fe26e82775f460f0b2778beaad66c0 \
+    --hash=sha256:3809ede931876f5b2ec92eef964286840ed3540dadf803dd570c3b7e13141a3b \
+    --hash=sha256:38a9ef736c01fccdd6600705b09dc574584b89bea478200c5fbf112a6b0d5579 \
+    --hash=sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a \
+    --hash=sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c \
+    --hash=sha256:48032821bbdf20f5799ff537c7ac3d1fba0ba032cfc06194faffa8cda8b560ff \
+    --hash=sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c \
+    --hash=sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22 \
+    --hash=sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094 \
+    --hash=sha256:57cb5a3cf367aeb1d316576250f65edec5bb3be939e9247ae594b4bcbc317dfb \
+    --hash=sha256:5b02fb34468b6aaa40dfc198d813a641e3a63b98c2b05a16b9f80b7ec314185e \
+    --hash=sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5 \
+    --hash=sha256:6af100e168aa82a50e186c82875a5893c5597a0c1ccdb0d8b40240b1f28b969a \
+    --hash=sha256:6c89876f41da747c8d3677a2b540fb32ef5715f97b66eeb0c6b66f5e3ef6f59d \
+    --hash=sha256:6e296a513ca3d94054c2c881cc913116e90fd030ad1c656b3869762b754f5f8a \
+    --hash=sha256:70a87b411535ccad5ef2f1df5136506a10775d267e197e4cf531ced10537bd6b \
+    --hash=sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8 \
+    --hash=sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225 \
+    --hash=sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c \
+    --hash=sha256:88b49a3b9ff31e19998750c38e030fc7bb937398b1f78cfa599aaef92d693144 \
+    --hash=sha256:8c4e8c3ce11e1f92f6536ff07154f9d49677ebaaafc32db9db4620bc11ed480f \
+    --hash=sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87 \
+    --hash=sha256:9025b4018f3a1314059769c7bf15441064b2207cb3f065e6ea1e7359cb46db9d \
+    --hash=sha256:93335ca3812df2f366e80509ae119189886b0f3c2b81325d39efdb84a1e2ae93 \
+    --hash=sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf \
+    --hash=sha256:9e2d922824181480953426608b81967de705c3cef4d1af983af849d7bd619158 \
+    --hash=sha256:a123e330ef0853c6e822384873bef7507557d8e4a082961e1defa947aa59ba84 \
+    --hash=sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb \
+    --hash=sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48 \
+    --hash=sha256:b424c77b206d63d500bcb69fa55ed8d0e6a3774056bdc4839fc9298a7edca171 \
+    --hash=sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c \
+    --hash=sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6 \
+    --hash=sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd \
+    --hash=sha256:bbcb445fa71794da8f178f0f6d66789a28d7319071af7a496d4d507ed566270d \
+    --hash=sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1 \
+    --hash=sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d \
+    --hash=sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca \
+    --hash=sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a \
+    --hash=sha256:cfad01eed2c2e0c01fd0ecd2ef42c492f7f93902e39a42fc9ee1692961443a29 \
+    --hash=sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe \
+    --hash=sha256:d8213e09c917a951de9d09ecee036d5c7d36cb6cb7dbaece4c71a60d79fb9798 \
+    --hash=sha256:e07c3764494e3776c602c1e78e298937c3315ccc9043ead7e685b7f2b8d47b3c \
+    --hash=sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8 \
+    --hash=sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f \
+    --hash=sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f \
+    --hash=sha256:eaa0a10b7f72326f1372a713e73c3f739b524b3af41feb43e4921cb529f5929a \
+    --hash=sha256:eb7972a85c54febfb25b5c4b4f3af4dcc731994c7da0d8a0b4a6eb0640e1d178 \
+    --hash=sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0 \
+    --hash=sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79 \
+    --hash=sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430 \
+    --hash=sha256:fcabf5ff6eea076f859677f5f0b6b5c1a51e70a376b0579e0eadef8db48c6b50
     # via jinja2
-mypy==1.8.0 \
-    --hash=sha256:028cf9f2cae89e202d7b6593cd98db6759379f17a319b5faf4f9978d7084cdc6 \
-    --hash=sha256:2afecd6354bbfb6e0160f4e4ad9ba6e4e003b767dd80d85516e71f2e955ab50d \
-    --hash=sha256:2b5b6c721bd4aabaadead3a5e6fa85c11c6c795e0c81a7215776ef8afc66de02 \
-    --hash=sha256:42419861b43e6962a649068a61f4a4839205a3ef525b858377a960b9e2de6e0d \
-    --hash=sha256:42c6680d256ab35637ef88891c6bd02514ccb7e1122133ac96055ff458f93fc3 \
-    --hash=sha256:485a8942f671120f76afffff70f259e1cd0f0cfe08f81c05d8816d958d4577d3 \
-    --hash=sha256:4c886c6cce2d070bd7df4ec4a05a13ee20c0aa60cb587e8d1265b6c03cf91da3 \
-    --hash=sha256:4e6d97288757e1ddba10dd9549ac27982e3e74a49d8d0179fc14d4365c7add66 \
-    --hash=sha256:4ef4be7baf08a203170f29e89d79064463b7fc7a0908b9d0d5114e8009c3a259 \
-    --hash=sha256:51720c776d148bad2372ca21ca29256ed483aa9a4cdefefcef49006dff2a6835 \
-    --hash=sha256:52825b01f5c4c1c4eb0db253ec09c7aa17e1a7304d247c48b6f3599ef40db8bd \
-    --hash=sha256:538fd81bb5e430cc1381a443971c0475582ff9f434c16cd46d2c66763ce85d9d \
-    --hash=sha256:5c1538c38584029352878a0466f03a8ee7547d7bd9f641f57a0f3017a7c905b8 \
-    --hash=sha256:6ff8b244d7085a0b425b56d327b480c3b29cafbd2eff27316a004f9a7391ae07 \
-    --hash=sha256:7178def594014aa6c35a8ff411cf37d682f428b3b5617ca79029d8ae72f5402b \
-    --hash=sha256:720a5ca70e136b675af3af63db533c1c8c9181314d207568bbe79051f122669e \
-    --hash=sha256:7f1478736fcebb90f97e40aff11a5f253af890c845ee0c850fe80aa060a267c6 \
-    --hash=sha256:855fe27b80375e5c5878492f0729540db47b186509c98dae341254c8f45f42ae \
-    --hash=sha256:8963b83d53ee733a6e4196954502b33567ad07dfd74851f32be18eb932fb1cb9 \
-    --hash=sha256:9261ed810972061388918c83c3f5cd46079d875026ba97380f3e3978a72f503d \
-    --hash=sha256:99b00bc72855812a60d253420d8a2eae839b0afa4938f09f4d2aa9bb4654263a \
-    --hash=sha256:ab3c84fa13c04aeeeabb2a7f67a25ef5d77ac9d6486ff33ded762ef353aa5592 \
-    --hash=sha256:afe3fe972c645b4632c563d3f3eff1cdca2fa058f730df2b93a35e3b0c538218 \
-    --hash=sha256:d19c413b3c07cbecf1f991e2221746b0d2a9410b59cb3f4fb9557f0365a1a817 \
-    --hash=sha256:df9824ac11deaf007443e7ed2a4a26bebff98d2bc43c6da21b2b64185da011c4 \
-    --hash=sha256:e46f44b54ebddbeedbd3d5b289a893219065ef805d95094d16a0af6630f5d410 \
-    --hash=sha256:f5ac9a4eeb1ec0f1ccdc6f326bcdb464de5f80eb07fb38b5ddd7b0de6bc61e55
+pyyaml==6.0.2 \
+    --hash=sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff \
+    --hash=sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48 \
+    --hash=sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086 \
+    --hash=sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e \
+    --hash=sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133 \
+    --hash=sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5 \
+    --hash=sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484 \
+    --hash=sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee \
+    --hash=sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5 \
+    --hash=sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68 \
+    --hash=sha256:24471b829b3bf607e04e88d79542a9d48bb037c2267d7927a874e6c205ca7e9a \
+    --hash=sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf \
+    --hash=sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99 \
+    --hash=sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8 \
+    --hash=sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85 \
+    --hash=sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19 \
+    --hash=sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc \
+    --hash=sha256:43fa96a3ca0d6b1812e01ced1044a003533c47f6ee8aca31724f78e93ccc089a \
+    --hash=sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1 \
+    --hash=sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317 \
+    --hash=sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c \
+    --hash=sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631 \
+    --hash=sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d \
+    --hash=sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652 \
+    --hash=sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5 \
+    --hash=sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e \
+    --hash=sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b \
+    --hash=sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8 \
+    --hash=sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476 \
+    --hash=sha256:82d09873e40955485746739bcb8b4586983670466c23382c19cffecbf1fd8706 \
+    --hash=sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563 \
+    --hash=sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237 \
+    --hash=sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b \
+    --hash=sha256:9056c1ecd25795207ad294bcf39f2db3d845767be0ea6e6a34d856f006006083 \
+    --hash=sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180 \
+    --hash=sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425 \
+    --hash=sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e \
+    --hash=sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f \
+    --hash=sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725 \
+    --hash=sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183 \
+    --hash=sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab \
+    --hash=sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774 \
+    --hash=sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725 \
+    --hash=sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e \
+    --hash=sha256:d7fded462629cfa4b685c5416b949ebad6cec74af5e2d42905d41e257e0869f5 \
+    --hash=sha256:d84a1718ee396f54f3a086ea0a66d8e552b2ab2017ef8b420e92edbc841c352d \
+    --hash=sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290 \
+    --hash=sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44 \
+    --hash=sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed \
+    --hash=sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4 \
+    --hash=sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba \
+    --hash=sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12 \
+    --hash=sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4
     # via -r requirements.in
-mypy-extensions==1.0.0 \
-    --hash=sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d \
-    --hash=sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782
-    # via mypy
-packaging==23.2 \
-    --hash=sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5 \
-    --hash=sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7
-    # via docker
-pyyaml==6.0.1 \
-    --hash=sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5 \
-    --hash=sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc \
-    --hash=sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df \
-    --hash=sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741 \
-    --hash=sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206 \
-    --hash=sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27 \
-    --hash=sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595 \
-    --hash=sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62 \
-    --hash=sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98 \
-    --hash=sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696 \
-    --hash=sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290 \
-    --hash=sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9 \
-    --hash=sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d \
-    --hash=sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6 \
-    --hash=sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867 \
-    --hash=sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47 \
-    --hash=sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486 \
-    --hash=sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6 \
-    --hash=sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3 \
-    --hash=sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007 \
-    --hash=sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938 \
-    --hash=sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0 \
-    --hash=sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c \
-    --hash=sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735 \
-    --hash=sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d \
-    --hash=sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28 \
-    --hash=sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4 \
-    --hash=sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba \
-    --hash=sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8 \
-    --hash=sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef \
-    --hash=sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5 \
-    --hash=sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd \
-    --hash=sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3 \
-    --hash=sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0 \
-    --hash=sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515 \
-    --hash=sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c \
-    --hash=sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c \
-    --hash=sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924 \
-    --hash=sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34 \
-    --hash=sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43 \
-    --hash=sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859 \
-    --hash=sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673 \
-    --hash=sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54 \
-    --hash=sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a \
-    --hash=sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b \
-    --hash=sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab \
-    --hash=sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa \
-    --hash=sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c \
-    --hash=sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585 \
-    --hash=sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d \
-    --hash=sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f
-    # via -r requirements.in
-referencing==0.33.0 \
-    --hash=sha256:39240f2ecc770258f28b642dd47fd74bc8b02484de54e1882b74b35ebd779bd5 \
-    --hash=sha256:c775fedf74bc0f9189c2a3be1c12fd03e8c23f4d371dce795df44e06c5b412f7
+referencing==0.35.1 \
+    --hash=sha256:25b42124a6c8b632a425174f24087783efb348a6f1e0008e63cd4466fedf703c \
+    --hash=sha256:eda6d3234d62814d1c64e305c1331c9a3a6132da475ab6382eaa997b21ee75de
     # via
     #   jsonschema
     #   jsonschema-specifications
-    #   types-jsonschema
-requests==2.31.0 \
-    --hash=sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f \
-    --hash=sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1
+requests==2.32.3 \
+    --hash=sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760 \
+    --hash=sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6
     # via docker
-rpds-py==0.18.0 \
-    --hash=sha256:01e36a39af54a30f28b73096dd39b6802eddd04c90dbe161c1b8dbe22353189f \
-    --hash=sha256:044a3e61a7c2dafacae99d1e722cc2d4c05280790ec5a05031b3876809d89a5c \
-    --hash=sha256:08231ac30a842bd04daabc4d71fddd7e6d26189406d5a69535638e4dcb88fe76 \
-    --hash=sha256:08f9ad53c3f31dfb4baa00da22f1e862900f45908383c062c27628754af2e88e \
-    --hash=sha256:0ab39c1ba9023914297dd88ec3b3b3c3f33671baeb6acf82ad7ce883f6e8e157 \
-    --hash=sha256:0af039631b6de0397ab2ba16eaf2872e9f8fca391b44d3d8cac317860a700a3f \
-    --hash=sha256:0b8612cd233543a3781bc659c731b9d607de65890085098986dfd573fc2befe5 \
-    --hash=sha256:11a8c85ef4a07a7638180bf04fe189d12757c696eb41f310d2426895356dcf05 \
-    --hash=sha256:1374f4129f9bcca53a1bba0bb86bf78325a0374577cf7e9e4cd046b1e6f20e24 \
-    --hash=sha256:1d4acf42190d449d5e89654d5c1ed3a4f17925eec71f05e2a41414689cda02d1 \
-    --hash=sha256:1d9a5be316c15ffb2b3c405c4ff14448c36b4435be062a7f578ccd8b01f0c4d8 \
-    --hash=sha256:1df3659d26f539ac74fb3b0c481cdf9d725386e3552c6fa2974f4d33d78e544b \
-    --hash=sha256:22806714311a69fd0af9b35b7be97c18a0fc2826e6827dbb3a8c94eac6cf7eeb \
-    --hash=sha256:2644e47de560eb7bd55c20fc59f6daa04682655c58d08185a9b95c1970fa1e07 \
-    --hash=sha256:2e6d75ab12b0bbab7215e5d40f1e5b738aa539598db27ef83b2ec46747df90e1 \
-    --hash=sha256:30f43887bbae0d49113cbaab729a112251a940e9b274536613097ab8b4899cf6 \
-    --hash=sha256:34b18ba135c687f4dac449aa5157d36e2cbb7c03cbea4ddbd88604e076aa836e \
-    --hash=sha256:36b3ee798c58ace201289024b52788161e1ea133e4ac93fba7d49da5fec0ef9e \
-    --hash=sha256:39514da80f971362f9267c600b6d459bfbbc549cffc2cef8e47474fddc9b45b1 \
-    --hash=sha256:39f5441553f1c2aed4de4377178ad8ff8f9d733723d6c66d983d75341de265ab \
-    --hash=sha256:3a96e0c6a41dcdba3a0a581bbf6c44bb863f27c541547fb4b9711fd8cf0ffad4 \
-    --hash=sha256:3f26b5bd1079acdb0c7a5645e350fe54d16b17bfc5e71f371c449383d3342e17 \
-    --hash=sha256:41ef53e7c58aa4ef281da975f62c258950f54b76ec8e45941e93a3d1d8580594 \
-    --hash=sha256:42821446ee7a76f5d9f71f9e33a4fb2ffd724bb3e7f93386150b61a43115788d \
-    --hash=sha256:43fbac5f22e25bee1d482c97474f930a353542855f05c1161fd804c9dc74a09d \
-    --hash=sha256:4457a94da0d5c53dc4b3e4de1158bdab077db23c53232f37a3cb7afdb053a4e3 \
-    --hash=sha256:465a3eb5659338cf2a9243e50ad9b2296fa15061736d6e26240e713522b6235c \
-    --hash=sha256:482103aed1dfe2f3b71a58eff35ba105289b8d862551ea576bd15479aba01f66 \
-    --hash=sha256:4832d7d380477521a8c1644bbab6588dfedea5e30a7d967b5fb75977c45fd77f \
-    --hash=sha256:4901165d170a5fde6f589acb90a6b33629ad1ec976d4529e769c6f3d885e3e80 \
-    --hash=sha256:5307def11a35f5ae4581a0b658b0af8178c65c530e94893345bebf41cc139d33 \
-    --hash=sha256:5417558f6887e9b6b65b4527232553c139b57ec42c64570569b155262ac0754f \
-    --hash=sha256:56a737287efecafc16f6d067c2ea0117abadcd078d58721f967952db329a3e5c \
-    --hash=sha256:586f8204935b9ec884500498ccc91aa869fc652c40c093bd9e1471fbcc25c022 \
-    --hash=sha256:5b4e7d8d6c9b2e8ee2d55c90b59c707ca59bc30058269b3db7b1f8df5763557e \
-    --hash=sha256:5ddcba87675b6d509139d1b521e0c8250e967e63b5909a7e8f8944d0f90ff36f \
-    --hash=sha256:618a3d6cae6ef8ec88bb76dd80b83cfe415ad4f1d942ca2a903bf6b6ff97a2da \
-    --hash=sha256:635dc434ff724b178cb192c70016cc0ad25a275228f749ee0daf0eddbc8183b1 \
-    --hash=sha256:661d25cbffaf8cc42e971dd570d87cb29a665f49f4abe1f9e76be9a5182c4688 \
-    --hash=sha256:66e6a3af5a75363d2c9a48b07cb27c4ea542938b1a2e93b15a503cdfa8490795 \
-    --hash=sha256:67071a6171e92b6da534b8ae326505f7c18022c6f19072a81dcf40db2638767c \
-    --hash=sha256:685537e07897f173abcf67258bee3c05c374fa6fff89d4c7e42fb391b0605e98 \
-    --hash=sha256:69e64831e22a6b377772e7fb337533c365085b31619005802a79242fee620bc1 \
-    --hash=sha256:6b0817e34942b2ca527b0e9298373e7cc75f429e8da2055607f4931fded23e20 \
-    --hash=sha256:6c81e5f372cd0dc5dc4809553d34f832f60a46034a5f187756d9b90586c2c307 \
-    --hash=sha256:6d7faa6f14017c0b1e69f5e2c357b998731ea75a442ab3841c0dbbbfe902d2c4 \
-    --hash=sha256:6ef0befbb5d79cf32d0266f5cff01545602344eda89480e1dd88aca964260b18 \
-    --hash=sha256:6ef687afab047554a2d366e112dd187b62d261d49eb79b77e386f94644363294 \
-    --hash=sha256:7223a2a5fe0d217e60a60cdae28d6949140dde9c3bcc714063c5b463065e3d66 \
-    --hash=sha256:77f195baa60a54ef9d2de16fbbfd3ff8b04edc0c0140a761b56c267ac11aa467 \
-    --hash=sha256:793968759cd0d96cac1e367afd70c235867831983f876a53389ad869b043c948 \
-    --hash=sha256:7bd339195d84439cbe5771546fe8a4e8a7a045417d8f9de9a368c434e42a721e \
-    --hash=sha256:7cd863afe7336c62ec78d7d1349a2f34c007a3cc6c2369d667c65aeec412a5b1 \
-    --hash=sha256:7f2facbd386dd60cbbf1a794181e6aa0bd429bd78bfdf775436020172e2a23f0 \
-    --hash=sha256:84ffab12db93b5f6bad84c712c92060a2d321b35c3c9960b43d08d0f639d60d7 \
-    --hash=sha256:8c8370641f1a7f0e0669ddccca22f1da893cef7628396431eb445d46d893e5cd \
-    --hash=sha256:8db715ebe3bb7d86d77ac1826f7d67ec11a70dbd2376b7cc214199360517b641 \
-    --hash=sha256:8e8916ae4c720529e18afa0b879473049e95949bf97042e938530e072fde061d \
-    --hash=sha256:8f03bccbd8586e9dd37219bce4d4e0d3ab492e6b3b533e973fa08a112cb2ffc9 \
-    --hash=sha256:8f2fc11e8fe034ee3c34d316d0ad8808f45bc3b9ce5857ff29d513f3ff2923a1 \
-    --hash=sha256:923d39efa3cfb7279a0327e337a7958bff00cc447fd07a25cddb0a1cc9a6d2da \
-    --hash=sha256:93df1de2f7f7239dc9cc5a4a12408ee1598725036bd2dedadc14d94525192fc3 \
-    --hash=sha256:998e33ad22dc7ec7e030b3df701c43630b5bc0d8fbc2267653577e3fec279afa \
-    --hash=sha256:99f70b740dc04d09e6b2699b675874367885217a2e9f782bdf5395632ac663b7 \
-    --hash=sha256:9a00312dea9310d4cb7dbd7787e722d2e86a95c2db92fbd7d0155f97127bcb40 \
-    --hash=sha256:9d54553c1136b50fd12cc17e5b11ad07374c316df307e4cfd6441bea5fb68496 \
-    --hash=sha256:9dbbeb27f4e70bfd9eec1be5477517365afe05a9b2c441a0b21929ee61048124 \
-    --hash=sha256:a1ce3ba137ed54f83e56fb983a5859a27d43a40188ba798993812fed73c70836 \
-    --hash=sha256:a34d557a42aa28bd5c48a023c570219ba2593bcbbb8dc1b98d8cf5d529ab1434 \
-    --hash=sha256:a5f446dd5055667aabaee78487f2b5ab72e244f9bc0b2ffebfeec79051679984 \
-    --hash=sha256:ad36cfb355e24f1bd37cac88c112cd7730873f20fb0bdaf8ba59eedf8216079f \
-    --hash=sha256:aec493917dd45e3c69d00a8874e7cbed844efd935595ef78a0f25f14312e33c6 \
-    --hash=sha256:b316144e85316da2723f9d8dc75bada12fa58489a527091fa1d5a612643d1a0e \
-    --hash=sha256:b34ae4636dfc4e76a438ab826a0d1eed2589ca7d9a1b2d5bb546978ac6485461 \
-    --hash=sha256:b34b7aa8b261c1dbf7720b5d6f01f38243e9b9daf7e6b8bc1fd4657000062f2c \
-    --hash=sha256:bc362ee4e314870a70f4ae88772d72d877246537d9f8cb8f7eacf10884862432 \
-    --hash=sha256:bed88b9a458e354014d662d47e7a5baafd7ff81c780fd91584a10d6ec842cb73 \
-    --hash=sha256:c0013fe6b46aa496a6749c77e00a3eb07952832ad6166bd481c74bda0dcb6d58 \
-    --hash=sha256:c0b5dcf9193625afd8ecc92312d6ed78781c46ecbf39af9ad4681fc9f464af88 \
-    --hash=sha256:c4325ff0442a12113a6379af66978c3fe562f846763287ef66bdc1d57925d337 \
-    --hash=sha256:c463ed05f9dfb9baebef68048aed8dcdc94411e4bf3d33a39ba97e271624f8f7 \
-    --hash=sha256:c8362467a0fdeccd47935f22c256bec5e6abe543bf0d66e3d3d57a8fb5731863 \
-    --hash=sha256:cd5bf1af8efe569654bbef5a3e0a56eca45f87cfcffab31dd8dde70da5982475 \
-    --hash=sha256:cf1ea2e34868f6fbf070e1af291c8180480310173de0b0c43fc38a02929fc0e3 \
-    --hash=sha256:d62dec4976954a23d7f91f2f4530852b0c7608116c257833922a896101336c51 \
-    --hash=sha256:d68c93e381010662ab873fea609bf6c0f428b6d0bb00f2c6939782e0818d37bf \
-    --hash=sha256:d7c36232a90d4755b720fbd76739d8891732b18cf240a9c645d75f00639a9024 \
-    --hash=sha256:dd18772815d5f008fa03d2b9a681ae38d5ae9f0e599f7dda233c439fcaa00d40 \
-    --hash=sha256:ddc2f4dfd396c7bfa18e6ce371cba60e4cf9d2e5cdb71376aa2da264605b60b9 \
-    --hash=sha256:e003b002ec72c8d5a3e3da2989c7d6065b47d9eaa70cd8808b5384fbb970f4ec \
-    --hash=sha256:e32a92116d4f2a80b629778280103d2a510a5b3f6314ceccd6e38006b5e92dcb \
-    --hash=sha256:e4461d0f003a0aa9be2bdd1b798a041f177189c1a0f7619fe8c95ad08d9a45d7 \
-    --hash=sha256:e541ec6f2ec456934fd279a3120f856cd0aedd209fc3852eca563f81738f6861 \
-    --hash=sha256:e546e768d08ad55b20b11dbb78a745151acbd938f8f00d0cfbabe8b0199b9880 \
-    --hash=sha256:ea7d4a99f3b38c37eac212dbd6ec42b7a5ec51e2c74b5d3223e43c811609e65f \
-    --hash=sha256:ed4eb745efbff0a8e9587d22a84be94a5eb7d2d99c02dacf7bd0911713ed14dd \
-    --hash=sha256:f8a2f084546cc59ea99fda8e070be2fd140c3092dc11524a71aa8f0f3d5a55ca \
-    --hash=sha256:fcb25daa9219b4cf3a0ab24b0eb9a5cc8949ed4dc72acb8fa16b7e1681aa3c58 \
-    --hash=sha256:fdea4952db2793c4ad0bdccd27c1d8fdd1423a92f04598bc39425bcc2b8ee46e
+rpds-py==0.22.3 \
+    --hash=sha256:009de23c9c9ee54bf11303a966edf4d9087cd43a6003672e6aa7def643d06518 \
+    --hash=sha256:02fbb9c288ae08bcb34fb41d516d5eeb0455ac35b5512d03181d755d80810059 \
+    --hash=sha256:0a0461200769ab3b9ab7e513f6013b7a97fdeee41c29b9db343f3c5a8e2b9e61 \
+    --hash=sha256:0b09865a9abc0ddff4e50b5ef65467cd94176bf1e0004184eb915cbc10fc05c5 \
+    --hash=sha256:0b8db6b5b2d4491ad5b6bdc2bc7c017eec108acbf4e6785f42a9eb0ba234f4c9 \
+    --hash=sha256:0c150c7a61ed4a4f4955a96626574e9baf1adf772c2fb61ef6a5027e52803543 \
+    --hash=sha256:0f3cec041684de9a4684b1572fe28c7267410e02450f4561700ca5a3bc6695a2 \
+    --hash=sha256:1352ae4f7c717ae8cba93421a63373e582d19d55d2ee2cbb184344c82d2ae55a \
+    --hash=sha256:177c7c0fce2855833819c98e43c262007f42ce86651ffbb84f37883308cb0e7d \
+    --hash=sha256:1978d0021e943aae58b9b0b196fb4895a25cc53d3956b8e35e0b7682eefb6d56 \
+    --hash=sha256:1a60bce91f81ddaac922a40bbb571a12c1070cb20ebd6d49c48e0b101d87300d \
+    --hash=sha256:1aef18820ef3e4587ebe8b3bc9ba6e55892a6d7b93bac6d29d9f631a3b4befbd \
+    --hash=sha256:1e9663daaf7a63ceccbbb8e3808fe90415b0757e2abddbfc2e06c857bf8c5e2b \
+    --hash=sha256:20070c65396f7373f5df4005862fa162db5d25d56150bddd0b3e8214e8ef45b4 \
+    --hash=sha256:214b7a953d73b5e87f0ebece4a32a5bd83c60a3ecc9d4ec8f1dca968a2d91e99 \
+    --hash=sha256:22bebe05a9ffc70ebfa127efbc429bc26ec9e9b4ee4d15a740033efda515cf3d \
+    --hash=sha256:24e8abb5878e250f2eb0d7859a8e561846f98910326d06c0d51381fed59357bd \
+    --hash=sha256:26fd7cac7dd51011a245f29a2cc6489c4608b5a8ce8d75661bb4a1066c52dfbe \
+    --hash=sha256:27b1d3b3915a99208fee9ab092b8184c420f2905b7d7feb4aeb5e4a9c509b8a1 \
+    --hash=sha256:27e98004595899949bd7a7b34e91fa7c44d7a97c40fcaf1d874168bb652ec67e \
+    --hash=sha256:2b8f60e1b739a74bab7e01fcbe3dddd4657ec685caa04681df9d562ef15b625f \
+    --hash=sha256:2de29005e11637e7a2361fa151f780ff8eb2543a0da1413bb951e9f14b699ef3 \
+    --hash=sha256:2e8b55d8517a2fda8d95cb45d62a5a8bbf9dd0ad39c5b25c8833efea07b880ca \
+    --hash=sha256:2fa4331c200c2521512595253f5bb70858b90f750d39b8cbfd67465f8d1b596d \
+    --hash=sha256:3445e07bf2e8ecfeef6ef67ac83de670358abf2996916039b16a218e3d95e97e \
+    --hash=sha256:3453e8d41fe5f17d1f8e9c383a7473cd46a63661628ec58e07777c2fff7196dc \
+    --hash=sha256:378753b4a4de2a7b34063d6f95ae81bfa7b15f2c1a04a9518e8644e81807ebea \
+    --hash=sha256:3af6e48651c4e0d2d166dc1b033b7042ea3f871504b6805ba5f4fe31581d8d38 \
+    --hash=sha256:3dfcbc95bd7992b16f3f7ba05af8a64ca694331bd24f9157b49dadeeb287493b \
+    --hash=sha256:3f21f0495edea7fdbaaa87e633a8689cd285f8f4af5c869f27bc8074638ad69c \
+    --hash=sha256:4041711832360a9b75cfb11b25a6a97c8fb49c07b8bd43d0d02b45d0b499a4ff \
+    --hash=sha256:44d61b4b7d0c2c9ac019c314e52d7cbda0ae31078aabd0f22e583af3e0d79723 \
+    --hash=sha256:4617e1915a539a0d9a9567795023de41a87106522ff83fbfaf1f6baf8e85437e \
+    --hash=sha256:4b232061ca880db21fa14defe219840ad9b74b6158adb52ddf0e87bead9e8493 \
+    --hash=sha256:5246b14ca64a8675e0a7161f7af68fe3e910e6b90542b4bfb5439ba752191df6 \
+    --hash=sha256:5725dd9cc02068996d4438d397e255dcb1df776b7ceea3b9cb972bdb11260a83 \
+    --hash=sha256:583f6a1993ca3369e0f80ba99d796d8e6b1a3a2a442dd4e1a79e652116413091 \
+    --hash=sha256:59259dc58e57b10e7e18ce02c311804c10c5a793e6568f8af4dead03264584d1 \
+    --hash=sha256:593eba61ba0c3baae5bc9be2f5232430453fb4432048de28399ca7376de9c627 \
+    --hash=sha256:59f4a79c19232a5774aee369a0c296712ad0e77f24e62cad53160312b1c1eaa1 \
+    --hash=sha256:5f0e260eaf54380380ac3808aa4ebe2d8ca28b9087cf411649f96bad6900c728 \
+    --hash=sha256:62d9cfcf4948683a18a9aff0ab7e1474d407b7bab2ca03116109f8464698ab16 \
+    --hash=sha256:64607d4cbf1b7e3c3c8a14948b99345eda0e161b852e122c6bb71aab6d1d798c \
+    --hash=sha256:655ca44a831ecb238d124e0402d98f6212ac527a0ba6c55ca26f616604e60a45 \
+    --hash=sha256:666ecce376999bf619756a24ce15bb14c5bfaf04bf00abc7e663ce17c3f34fe7 \
+    --hash=sha256:68049202f67380ff9aa52f12e92b1c30115f32e6895cd7198fa2a7961621fc5a \
+    --hash=sha256:69803198097467ee7282750acb507fba35ca22cc3b85f16cf45fb01cb9097730 \
+    --hash=sha256:6c7b99ca52c2c1752b544e310101b98a659b720b21db00e65edca34483259967 \
+    --hash=sha256:6dd9412824c4ce1aca56c47b0991e65bebb7ac3f4edccfd3f156150c96a7bf25 \
+    --hash=sha256:70eb60b3ae9245ddea20f8a4190bd79c705a22f8028aaf8bbdebe4716c3fab24 \
+    --hash=sha256:70fb28128acbfd264eda9bf47015537ba3fe86e40d046eb2963d75024be4d055 \
+    --hash=sha256:7b2513ba235829860b13faa931f3b6846548021846ac808455301c23a101689d \
+    --hash=sha256:7ef9d9da710be50ff6809fed8f1963fecdfecc8b86656cadfca3bc24289414b0 \
+    --hash=sha256:81e69b0a0e2537f26d73b4e43ad7bc8c8efb39621639b4434b76a3de50c6966e \
+    --hash=sha256:8633e471c6207a039eff6aa116e35f69f3156b3989ea3e2d755f7bc41754a4a7 \
+    --hash=sha256:8bd7c8cfc0b8247c8799080fbff54e0b9619e17cdfeb0478ba7295d43f635d7c \
+    --hash=sha256:9253fc214112405f0afa7db88739294295f0e08466987f1d70e29930262b4c8f \
+    --hash=sha256:99b37292234e61325e7a5bb9689e55e48c3f5f603af88b1642666277a81f1fbd \
+    --hash=sha256:9bd7228827ec7bb817089e2eb301d907c0d9827a9e558f22f762bb690b131652 \
+    --hash=sha256:9beeb01d8c190d7581a4d59522cd3d4b6887040dcfc744af99aa59fef3e041a8 \
+    --hash=sha256:a63cbdd98acef6570c62b92a1e43266f9e8b21e699c363c0fef13bd530799c11 \
+    --hash=sha256:a76e42402542b1fae59798fab64432b2d015ab9d0c8c47ba7addddbaf7952333 \
+    --hash=sha256:ac0a03221cdb5058ce0167ecc92a8c89e8d0decdc9e99a2ec23380793c4dcb96 \
+    --hash=sha256:b0b4136a252cadfa1adb705bb81524eee47d9f6aab4f2ee4fa1e9d3cd4581f64 \
+    --hash=sha256:b25bc607423935079e05619d7de556c91fb6adeae9d5f80868dde3468657994b \
+    --hash=sha256:b3d504047aba448d70cf6fa22e06cb09f7cbd761939fdd47604f5e007675c24e \
+    --hash=sha256:bb47271f60660803ad11f4c61b42242b8c1312a31c98c578f79ef9387bbde21c \
+    --hash=sha256:bbb232860e3d03d544bc03ac57855cd82ddf19c7a07651a7c0fdb95e9efea8b9 \
+    --hash=sha256:bc27863442d388870c1809a87507727b799c8460573cfbb6dc0eeaef5a11b5ec \
+    --hash=sha256:bc51abd01f08117283c5ebf64844a35144a0843ff7b2983e0648e4d3d9f10dbb \
+    --hash=sha256:be2eb3f2495ba669d2a985f9b426c1797b7d48d6963899276d22f23e33d47e37 \
+    --hash=sha256:bf9db5488121b596dbfc6718c76092fda77b703c1f7533a226a5a9f65248f8ad \
+    --hash=sha256:c58e2339def52ef6b71b8f36d13c3688ea23fa093353f3a4fee2556e62086ec9 \
+    --hash=sha256:cfbc454a2880389dbb9b5b398e50d439e2e58669160f27b60e5eca11f68ae17c \
+    --hash=sha256:cff63a0272fcd259dcc3be1657b07c929c466b067ceb1c20060e8d10af56f5bf \
+    --hash=sha256:d115bffdd417c6d806ea9069237a4ae02f513b778e3789a359bc5856e0404cc4 \
+    --hash=sha256:d20cfb4e099748ea39e6f7b16c91ab057989712d31761d3300d43134e26e165f \
+    --hash=sha256:d48424e39c2611ee1b84ad0f44fb3b2b53d473e65de061e3f460fc0be5f1939d \
+    --hash=sha256:e0fa2d4ec53dc51cf7d3bb22e0aa0143966119f42a0c3e4998293a3dd2856b09 \
+    --hash=sha256:e32fee8ab45d3c2db6da19a5323bc3362237c8b653c70194414b892fd06a080d \
+    --hash=sha256:e35ba67d65d49080e8e5a1dd40101fccdd9798adb9b050ff670b7d74fa41c566 \
+    --hash=sha256:e3fb866d9932a3d7d0c82da76d816996d1667c44891bd861a0f97ba27e84fc74 \
+    --hash=sha256:e61b02c3f7a1e0b75e20c3978f7135fd13cb6cf551bf4a6d29b999a88830a338 \
+    --hash=sha256:e67ba3c290821343c192f7eae1d8fd5999ca2dc99994114643e2f2d3e6138b15 \
+    --hash=sha256:e79dd39f1e8c3504be0607e5fc6e86bb60fe3584bec8b782578c3b0fde8d932c \
+    --hash=sha256:e89391e6d60251560f0a8f4bd32137b077a80d9b7dbe6d5cab1cd80d2746f648 \
+    --hash=sha256:ea7433ce7e4bfc3a85654aeb6747babe3f66eaf9a1d0c1e7a4435bbdf27fea84 \
+    --hash=sha256:eaf16ae9ae519a0e237a0f528fd9f0197b9bb70f40263ee57ae53c2b8d48aeb3 \
+    --hash=sha256:eb0c341fa71df5a4595f9501df4ac5abfb5a09580081dffbd1ddd4654e6e9123 \
+    --hash=sha256:f276b245347e6e36526cbd4a266a417796fc531ddf391e43574cf6466c492520 \
+    --hash=sha256:f47ad3d5f3258bd7058d2d506852217865afefe6153a36eb4b6928758041d831 \
+    --hash=sha256:f56a6b404f74ab372da986d240e2e002769a7d7102cc73eb238a4f72eec5284e \
+    --hash=sha256:f5cf2a0c2bdadf3791b5c205d55a37a54025c6e18a71c71f82bb536cf9a454bf \
+    --hash=sha256:f5d36399a1b96e1a5fdc91e0522544580dbebeb1f77f27b2b0ab25559e103b8b \
+    --hash=sha256:f60bd8423be1d9d833f230fdbccf8f57af322d96bcad6599e5a771b151398eb2 \
+    --hash=sha256:f612463ac081803f243ff13cccc648578e2279295048f2a8d5eb430af2bae6e3 \
+    --hash=sha256:f73d3fef726b3243a811121de45193c0ca75f6407fe66f3f4e183c983573e130 \
+    --hash=sha256:f82a116a1d03628a8ace4859556fb39fd1424c933341a08ea3ed6de1edb0283b \
+    --hash=sha256:fb0ba113b4983beac1a2eb16faffd76cb41e176bf58c4afe3e14b9c681f702de \
+    --hash=sha256:fb4f868f712b2dd4bcc538b0a0c1f63a2b1d584c925e69a224d759e7070a12d5 \
+    --hash=sha256:fb6116dfb8d1925cbdb52595560584db42a7f664617a1f7d7f6e32f138cdf37d \
+    --hash=sha256:fda7cb070f442bf80b642cd56483b5548e43d366fe3f39b98e67cce780cded00 \
+    --hash=sha256:feea821ee2a9273771bae61194004ee2fc33f8ec7db08117ef9147d4bbcbca8e
     # via
     #   jsonschema
     #   referencing
-six==1.16.0 \
-    --hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 \
-    --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254
-    # via -r requirements.in
-tomli==2.0.1 \
-    --hash=sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc \
-    --hash=sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f
-    # via -r requirements.in
-types-jsonschema==4.21.0.20240118 \
-    --hash=sha256:31aae1b5adc0176c1155c2d4f58348b22d92ae64315e9cc83bd6902168839232 \
-    --hash=sha256:77a4ac36b0be4f24274d5b9bf0b66208ee771c05f80e34c4641de7d63e8a872d
+six==1.17.0 \
+    --hash=sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274 \
+    --hash=sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81
     # via -r requirements.in
-types-pyyaml==6.0.12.12 \
-    --hash=sha256:334373d392fde0fdf95af5c3f1661885fa10c52167b14593eb856289e1855062 \
-    --hash=sha256:c05bc6c158facb0676674b7f11fe3960db4f389718e19e62bd2b84d6205cfd24
+tomli==2.2.1 \
+    --hash=sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6 \
+    --hash=sha256:02abe224de6ae62c19f090f68da4e27b10af2b93213d36cf44e6e1c5abd19fdd \
+    --hash=sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c \
+    --hash=sha256:2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b \
+    --hash=sha256:33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8 \
+    --hash=sha256:400e720fe168c0f8521520190686ef8ef033fb19fc493da09779e592861b78c6 \
+    --hash=sha256:40741994320b232529c802f8bc86da4e1aa9f413db394617b9a256ae0f9a7f77 \
+    --hash=sha256:465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff \
+    --hash=sha256:4a8f6e44de52d5e6c657c9fe83b562f5f4256d8ebbfe4ff922c495620a7f6cea \
+    --hash=sha256:4e340144ad7ae1533cb897d406382b4b6fede8890a03738ff1683af800d54192 \
+    --hash=sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249 \
+    --hash=sha256:6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee \
+    --hash=sha256:7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4 \
+    --hash=sha256:889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98 \
+    --hash=sha256:8d57ca8095a641b8237d5b079147646153d22552f1c637fd3ba7f4b0b29167a8 \
+    --hash=sha256:8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4 \
+    --hash=sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281 \
+    --hash=sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744 \
+    --hash=sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69 \
+    --hash=sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13 \
+    --hash=sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140 \
+    --hash=sha256:b82ebccc8c8a36f2094e969560a1b836758481f3dc360ce9a3277c65f374285e \
+    --hash=sha256:c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e \
+    --hash=sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc \
+    --hash=sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff \
+    --hash=sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec \
+    --hash=sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2 \
+    --hash=sha256:db2b95f9de79181805df90bedc5a5ab4c165e6ec3fe99f970d0e302f384ad222 \
+    --hash=sha256:e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106 \
+    --hash=sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272 \
+    --hash=sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a \
+    --hash=sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7
     # via -r requirements.in
-typing-extensions==4.9.0 \
-    --hash=sha256:23478f88c37f27d76ac8aee6c905017a143b0b1b886c3c9f66bc2fd94f9f5783 \
-    --hash=sha256:af72aea155e91adfc61c3ae9e0e342dbc0cba726d6cba4b6c72c1f34e47291cd
-    # via mypy
-urllib3==2.2.1 \
-    --hash=sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d \
-    --hash=sha256:d0570876c61ab9e520d776c38acbbb5b05a776d3f9ff98a5c8fd5162a444cf19
+urllib3==2.3.0 \
+    --hash=sha256:1cee9ad369867bfdbbb48b7dd50374c0967a0bb7710050facf0dd6911440e3df \
+    --hash=sha256:f8c5449b3cf0861679ce7e0503c7b44b5ec981bec0d1d3795a07f1ba96f0204d
     # via
     #   docker
     #   requests
-zstandard==0.22.0 \
-    --hash=sha256:11f0d1aab9516a497137b41e3d3ed4bbf7b2ee2abc79e5c8b010ad286d7464bd \
-    --hash=sha256:1958100b8a1cc3f27fa21071a55cb2ed32e9e5df4c3c6e661c193437f171cba2 \
-    --hash=sha256:1a90ba9a4c9c884bb876a14be2b1d216609385efb180393df40e5172e7ecf356 \
-    --hash=sha256:1d43501f5f31e22baf822720d82b5547f8a08f5386a883b32584a185675c8fbf \
-    --hash=sha256:23d2b3c2b8e7e5a6cb7922f7c27d73a9a615f0a5ab5d0e03dd533c477de23004 \
-    --hash=sha256:2612e9bb4977381184bb2463150336d0f7e014d6bb5d4a370f9a372d21916f69 \
-    --hash=sha256:275df437ab03f8c033b8a2c181e51716c32d831082d93ce48002a5227ec93019 \
-    --hash=sha256:2ac9957bc6d2403c4772c890916bf181b2653640da98f32e04b96e4d6fb3252a \
-    --hash=sha256:2b11ea433db22e720758cba584c9d661077121fcf60ab43351950ded20283440 \
-    --hash=sha256:2fdd53b806786bd6112d97c1f1e7841e5e4daa06810ab4b284026a1a0e484c0b \
-    --hash=sha256:33591d59f4956c9812f8063eff2e2c0065bc02050837f152574069f5f9f17775 \
-    --hash=sha256:36a47636c3de227cd765e25a21dc5dace00539b82ddd99ee36abae38178eff9e \
-    --hash=sha256:39b2853efc9403927f9065cc48c9980649462acbdf81cd4f0cb773af2fd734bc \
-    --hash=sha256:3db41c5e49ef73641d5111554e1d1d3af106410a6c1fb52cf68912ba7a343a0d \
-    --hash=sha256:445b47bc32de69d990ad0f34da0e20f535914623d1e506e74d6bc5c9dc40bb09 \
-    --hash=sha256:466e6ad8caefb589ed281c076deb6f0cd330e8bc13c5035854ffb9c2014b118c \
-    --hash=sha256:48f260e4c7294ef275744210a4010f116048e0c95857befb7462e033f09442fe \
-    --hash=sha256:4ac59d5d6910b220141c1737b79d4a5aa9e57466e7469a012ed42ce2d3995e88 \
-    --hash=sha256:53866a9d8ab363271c9e80c7c2e9441814961d47f88c9bc3b248142c32141d94 \
-    --hash=sha256:589402548251056878d2e7c8859286eb91bd841af117dbe4ab000e6450987e08 \
-    --hash=sha256:68953dc84b244b053c0d5f137a21ae8287ecf51b20872eccf8eaac0302d3e3b0 \
-    --hash=sha256:6c25b8eb733d4e741246151d895dd0308137532737f337411160ff69ca24f93a \
-    --hash=sha256:7034d381789f45576ec3f1fa0e15d741828146439228dc3f7c59856c5bcd3292 \
-    --hash=sha256:73a1d6bd01961e9fd447162e137ed949c01bdb830dfca487c4a14e9742dccc93 \
-    --hash=sha256:8226a33c542bcb54cd6bd0a366067b610b41713b64c9abec1bc4533d69f51e70 \
-    --hash=sha256:888196c9c8893a1e8ff5e89b8f894e7f4f0e64a5af4d8f3c410f0319128bb2f8 \
-    --hash=sha256:88c5b4b47a8a138338a07fc94e2ba3b1535f69247670abfe422de4e0b344aae2 \
-    --hash=sha256:8a1b2effa96a5f019e72874969394edd393e2fbd6414a8208fea363a22803b45 \
-    --hash=sha256:93e1856c8313bc688d5df069e106a4bc962eef3d13372020cc6e3ebf5e045202 \
-    --hash=sha256:9501f36fac6b875c124243a379267d879262480bf85b1dbda61f5ad4d01b75a3 \
-    --hash=sha256:959665072bd60f45c5b6b5d711f15bdefc9849dd5da9fb6c873e35f5d34d8cfb \
-    --hash=sha256:a1d67d0d53d2a138f9e29d8acdabe11310c185e36f0a848efa104d4e40b808e4 \
-    --hash=sha256:a493d470183ee620a3df1e6e55b3e4de8143c0ba1b16f3ded83208ea8ddfd91d \
-    --hash=sha256:a7ccf5825fd71d4542c8ab28d4d482aace885f5ebe4b40faaa290eed8e095a4c \
-    --hash=sha256:a88b7df61a292603e7cd662d92565d915796b094ffb3d206579aaebac6b85d5f \
-    --hash=sha256:a97079b955b00b732c6f280d5023e0eefe359045e8b83b08cf0333af9ec78f26 \
-    --hash=sha256:d22fdef58976457c65e2796e6730a3ea4a254f3ba83777ecfc8592ff8d77d303 \
-    --hash=sha256:d75f693bb4e92c335e0645e8845e553cd09dc91616412d1d4650da835b5449df \
-    --hash=sha256:d8593f8464fb64d58e8cb0b905b272d40184eac9a18d83cf8c10749c3eafcd7e \
-    --hash=sha256:d8fff0f0c1d8bc5d866762ae95bd99d53282337af1be9dc0d88506b340e74b73 \
-    --hash=sha256:de20a212ef3d00d609d0b22eb7cc798d5a69035e81839f549b538eff4105d01c \
-    --hash=sha256:e9e9d4e2e336c529d4c435baad846a181e39a982f823f7e4495ec0b0ec8538d2 \
-    --hash=sha256:f058a77ef0ece4e210bb0450e68408d4223f728b109764676e1a13537d056bb0 \
-    --hash=sha256:f1a4b358947a65b94e2501ce3e078bbc929b039ede4679ddb0460829b12f7375 \
-    --hash=sha256:f9b2cde1cd1b2a10246dbc143ba49d942d14fb3d2b4bccf4618d475c65464912 \
-    --hash=sha256:fe3390c538f12437b859d815040763abc728955a52ca6ff9c5d4ac707c4ad98e
+zstandard==0.23.0 \
+    --hash=sha256:034b88913ecc1b097f528e42b539453fa82c3557e414b3de9d5632c80439a473 \
+    --hash=sha256:0a7f0804bb3799414af278e9ad51be25edf67f78f916e08afdb983e74161b916 \
+    --hash=sha256:11e3bf3c924853a2d5835b24f03eeba7fc9b07d8ca499e247e06ff5676461a15 \
+    --hash=sha256:12a289832e520c6bd4dcaad68e944b86da3bad0d339ef7989fb7e88f92e96072 \
+    --hash=sha256:1516c8c37d3a053b01c1c15b182f3b5f5eef19ced9b930b684a73bad121addf4 \
+    --hash=sha256:157e89ceb4054029a289fb504c98c6a9fe8010f1680de0201b3eb5dc20aa6d9e \
+    --hash=sha256:1bfe8de1da6d104f15a60d4a8a768288f66aa953bbe00d027398b93fb9680b26 \
+    --hash=sha256:1e172f57cd78c20f13a3415cc8dfe24bf388614324d25539146594c16d78fcc8 \
+    --hash=sha256:1fd7e0f1cfb70eb2f95a19b472ee7ad6d9a0a992ec0ae53286870c104ca939e5 \
+    --hash=sha256:203d236f4c94cd8379d1ea61db2fce20730b4c38d7f1c34506a31b34edc87bdd \
+    --hash=sha256:27d3ef2252d2e62476389ca8f9b0cf2bbafb082a3b6bfe9d90cbcbb5529ecf7c \
+    --hash=sha256:29a2bc7c1b09b0af938b7a8343174b987ae021705acabcbae560166567f5a8db \
+    --hash=sha256:2ef230a8fd217a2015bc91b74f6b3b7d6522ba48be29ad4ea0ca3a3775bf7dd5 \
+    --hash=sha256:2ef3775758346d9ac6214123887d25c7061c92afe1f2b354f9388e9e4d48acfc \
+    --hash=sha256:2f146f50723defec2975fb7e388ae3a024eb7151542d1599527ec2aa9cacb152 \
+    --hash=sha256:2fb4535137de7e244c230e24f9d1ec194f61721c86ebea04e1581d9d06ea1269 \
+    --hash=sha256:32ba3b5ccde2d581b1e6aa952c836a6291e8435d788f656fe5976445865ae045 \
+    --hash=sha256:34895a41273ad33347b2fc70e1bff4240556de3c46c6ea430a7ed91f9042aa4e \
+    --hash=sha256:379b378ae694ba78cef921581ebd420c938936a153ded602c4fea612b7eaa90d \
+    --hash=sha256:38302b78a850ff82656beaddeb0bb989a0322a8bbb1bf1ab10c17506681d772a \
+    --hash=sha256:3aa014d55c3af933c1315eb4bb06dd0459661cc0b15cd61077afa6489bec63bb \
+    --hash=sha256:4051e406288b8cdbb993798b9a45c59a4896b6ecee2f875424ec10276a895740 \
+    --hash=sha256:40b33d93c6eddf02d2c19f5773196068d875c41ca25730e8288e9b672897c105 \
+    --hash=sha256:43da0f0092281bf501f9c5f6f3b4c975a8a0ea82de49ba3f7100e64d422a1274 \
+    --hash=sha256:445e4cb5048b04e90ce96a79b4b63140e3f4ab5f662321975679b5f6360b90e2 \
+    --hash=sha256:48ef6a43b1846f6025dde6ed9fee0c24e1149c1c25f7fb0a0585572b2f3adc58 \
+    --hash=sha256:50a80baba0285386f97ea36239855f6020ce452456605f262b2d33ac35c7770b \
+    --hash=sha256:519fbf169dfac1222a76ba8861ef4ac7f0530c35dd79ba5727014613f91613d4 \
+    --hash=sha256:53dd9d5e3d29f95acd5de6802e909ada8d8d8cfa37a3ac64836f3bc4bc5512db \
+    --hash=sha256:53ea7cdc96c6eb56e76bb06894bcfb5dfa93b7adcf59d61c6b92674e24e2dd5e \
+    --hash=sha256:576856e8594e6649aee06ddbfc738fec6a834f7c85bf7cadd1c53d4a58186ef9 \
+    --hash=sha256:59556bf80a7094d0cfb9f5e50bb2db27fefb75d5138bb16fb052b61b0e0eeeb0 \
+    --hash=sha256:5d41d5e025f1e0bccae4928981e71b2334c60f580bdc8345f824e7c0a4c2a813 \
+    --hash=sha256:61062387ad820c654b6a6b5f0b94484fa19515e0c5116faf29f41a6bc91ded6e \
+    --hash=sha256:61f89436cbfede4bc4e91b4397eaa3e2108ebe96d05e93d6ccc95ab5714be512 \
+    --hash=sha256:62136da96a973bd2557f06ddd4e8e807f9e13cbb0bfb9cc06cfe6d98ea90dfe0 \
+    --hash=sha256:64585e1dba664dc67c7cdabd56c1e5685233fbb1fc1966cfba2a340ec0dfff7b \
+    --hash=sha256:65308f4b4890aa12d9b6ad9f2844b7ee42c7f7a4fd3390425b242ffc57498f48 \
+    --hash=sha256:66b689c107857eceabf2cf3d3fc699c3c0fe8ccd18df2219d978c0283e4c508a \
+    --hash=sha256:6a41c120c3dbc0d81a8e8adc73312d668cd34acd7725f036992b1b72d22c1772 \
+    --hash=sha256:6f77fa49079891a4aab203d0b1744acc85577ed16d767b52fc089d83faf8d8ed \
+    --hash=sha256:72c68dda124a1a138340fb62fa21b9bf4848437d9ca60bd35db36f2d3345f373 \
+    --hash=sha256:752bf8a74412b9892f4e5b58f2f890a039f57037f52c89a740757ebd807f33ea \
+    --hash=sha256:76e79bc28a65f467e0409098fa2c4376931fd3207fbeb6b956c7c476d53746dd \
+    --hash=sha256:774d45b1fac1461f48698a9d4b5fa19a69d47ece02fa469825b442263f04021f \
+    --hash=sha256:77da4c6bfa20dd5ea25cbf12c76f181a8e8cd7ea231c673828d0386b1740b8dc \
+    --hash=sha256:77ea385f7dd5b5676d7fd943292ffa18fbf5c72ba98f7d09fc1fb9e819b34c23 \
+    --hash=sha256:80080816b4f52a9d886e67f1f96912891074903238fe54f2de8b786f86baded2 \
+    --hash=sha256:80a539906390591dd39ebb8d773771dc4db82ace6372c4d41e2d293f8e32b8db \
+    --hash=sha256:82d17e94d735c99621bf8ebf9995f870a6b3e6d14543b99e201ae046dfe7de70 \
+    --hash=sha256:837bb6764be6919963ef41235fd56a6486b132ea64afe5fafb4cb279ac44f259 \
+    --hash=sha256:84433dddea68571a6d6bd4fbf8ff398236031149116a7fff6f777ff95cad3df9 \
+    --hash=sha256:8c24f21fa2af4bb9f2c492a86fe0c34e6d2c63812a839590edaf177b7398f700 \
+    --hash=sha256:8ed7d27cb56b3e058d3cf684d7200703bcae623e1dcc06ed1e18ecda39fee003 \
+    --hash=sha256:9206649ec587e6b02bd124fb7799b86cddec350f6f6c14bc82a2b70183e708ba \
+    --hash=sha256:983b6efd649723474f29ed42e1467f90a35a74793437d0bc64a5bf482bedfa0a \
+    --hash=sha256:98da17ce9cbf3bfe4617e836d561e433f871129e3a7ac16d6ef4c680f13a839c \
+    --hash=sha256:9c236e635582742fee16603042553d276cca506e824fa2e6489db04039521e90 \
+    --hash=sha256:9da6bc32faac9a293ddfdcb9108d4b20416219461e4ec64dfea8383cac186690 \
+    --hash=sha256:a05e6d6218461eb1b4771d973728f0133b2a4613a6779995df557f70794fd60f \
+    --hash=sha256:a0817825b900fcd43ac5d05b8b3079937073d2b1ff9cf89427590718b70dd840 \
+    --hash=sha256:a4ae99c57668ca1e78597d8b06d5af837f377f340f4cce993b551b2d7731778d \
+    --hash=sha256:a8c86881813a78a6f4508ef9daf9d4995b8ac2d147dcb1a450448941398091c9 \
+    --hash=sha256:a8fffdbd9d1408006baaf02f1068d7dd1f016c6bcb7538682622c556e7b68e35 \
+    --hash=sha256:a9b07268d0c3ca5c170a385a0ab9fb7fdd9f5fd866be004c4ea39e44edce47dd \
+    --hash=sha256:ab19a2d91963ed9e42b4e8d77cd847ae8381576585bad79dbd0a8837a9f6620a \
+    --hash=sha256:ac184f87ff521f4840e6ea0b10c0ec90c6b1dcd0bad2f1e4a9a1b4fa177982ea \
+    --hash=sha256:b0e166f698c5a3e914947388c162be2583e0c638a4703fc6a543e23a88dea3c1 \
+    --hash=sha256:b2170c7e0367dde86a2647ed5b6f57394ea7f53545746104c6b09fc1f4223573 \
+    --hash=sha256:b2d8c62d08e7255f68f7a740bae85b3c9b8e5466baa9cbf7f57f1cde0ac6bc09 \
+    --hash=sha256:b4567955a6bc1b20e9c31612e615af6b53733491aeaa19a6b3b37f3b65477094 \
+    --hash=sha256:b69bb4f51daf461b15e7b3db033160937d3ff88303a7bc808c67bbc1eaf98c78 \
+    --hash=sha256:b8c0bd73aeac689beacd4e7667d48c299f61b959475cdbb91e7d3d88d27c56b9 \
+    --hash=sha256:be9b5b8659dff1f913039c2feee1aca499cfbc19e98fa12bc85e037c17ec6ca5 \
+    --hash=sha256:bf0a05b6059c0528477fba9054d09179beb63744355cab9f38059548fedd46a9 \
+    --hash=sha256:c16842b846a8d2a145223f520b7e18b57c8f476924bda92aeee3a88d11cfc391 \
+    --hash=sha256:c363b53e257246a954ebc7c488304b5592b9c53fbe74d03bc1c64dda153fb847 \
+    --hash=sha256:c7c517d74bea1a6afd39aa612fa025e6b8011982a0897768a2f7c8ab4ebb78a2 \
+    --hash=sha256:d20fd853fbb5807c8e84c136c278827b6167ded66c72ec6f9a14b863d809211c \
+    --hash=sha256:d2240ddc86b74966c34554c49d00eaafa8200a18d3a5b6ffbf7da63b11d74ee2 \
+    --hash=sha256:d477ed829077cd945b01fc3115edd132c47e6540ddcd96ca169facff28173057 \
+    --hash=sha256:d50d31bfedd53a928fed6707b15a8dbeef011bb6366297cc435accc888b27c20 \
+    --hash=sha256:dc1d33abb8a0d754ea4763bad944fd965d3d95b5baef6b121c0c9013eaf1907d \
+    --hash=sha256:dc5d1a49d3f8262be192589a4b72f0d03b72dcf46c51ad5852a4fdc67be7b9e4 \
+    --hash=sha256:e2d1a054f8f0a191004675755448d12be47fa9bebbcffa3cdf01db19f2d30a54 \
+    --hash=sha256:e7792606d606c8df5277c32ccb58f29b9b8603bf83b48639b7aedf6df4fe8171 \
+    --hash=sha256:ed1708dbf4d2e3a1c5c69110ba2b4eb6678262028afd6c6fbcc5a8dac9cda68e \
+    --hash=sha256:f2d4380bf5f62daabd7b751ea2339c1a21d1c9463f1feb7fc2bdcea2c29c3160 \
+    --hash=sha256:f3513916e8c645d0610815c257cbfd3242adfd5c4cfa78be514e5a3ebb42a41b \
+    --hash=sha256:f8346bfa098532bc1fb6c7ef06783e969d87a99dd1d2a5a18a892c1d7a643c58 \
+    --hash=sha256:f83fa6cae3fff8e98691248c9320356971b59678a17f20656a9e59cd32cee6d8 \
+    --hash=sha256:fa6ce8b52c5987b3e34d5674b0ab529a4602b632ebab0a93b07bfb4dfc8f8a33 \
+    --hash=sha256:fb2b1ecfef1e67897d336de3a0e3f52478182d6a47eda86cbd42504c5cbd009a \
+    --hash=sha256:fc9ca1c9718cb3b06634c7c8dec57d24e9438b2aa9a0f02b8bb36bf478538880 \
+    --hash=sha256:fd30d9c67d13d891f2360b2a120186729c111238ac63b43dbd37a5a40670b8ca \
+    --hash=sha256:fd7699e8fd9969f455ef2926221e0233f81a2542921471382e77a9e2f2b57f4b \
+    --hash=sha256:fe3b385d996ee0822fd46528d9f0443b880d4d05528fd26a9119a54ec3f91c69
     # via -r requirements.in
diff --git a/requirements.win.txt b/requirements.win.txt
old mode 100755
new mode 100644
index ae6d1a0f..aa1a25c6
--- a/requirements.win.txt
+++ b/requirements.win.txt
@@ -1,9 +1,5 @@
-#
-# This file is autogenerated by pip-compile with Python 3.11
-# by the following command:
-#
-#    pip-compile --generate-hashes --output-file=requirements.win.txt requirements.in
-#
+# This file was autogenerated by uv via the following command:
+#    uv pip compile --python-platform windows --generate-hashes requirements.in -o requirements.win.txt
 attrs==23.2.0 \
     --hash=sha256:935dc3b529c262f6cf76e50877d35a4bd3c1de194fd41f47a2b7ae8f19971f30 \
     --hash=sha256:99b87a485a5820b23b879f04c2305b44b951b502fd64be915879d77a7e8fc6f1
@@ -188,58 +184,29 @@ markupsafe==2.1.5 \
     --hash=sha256:fce659a462a1be54d2ffcacea5e3ba2d74daa74f30f5f143fe0c58636e355fdd \
     --hash=sha256:ffee1f21e5ef0d712f9033568f8344d5da8cc2869dbd08d87c84656e6a2d2f68
     # via jinja2
-mypy==1.8.0 \
-    --hash=sha256:028cf9f2cae89e202d7b6593cd98db6759379f17a319b5faf4f9978d7084cdc6 \
-    --hash=sha256:2afecd6354bbfb6e0160f4e4ad9ba6e4e003b767dd80d85516e71f2e955ab50d \
-    --hash=sha256:2b5b6c721bd4aabaadead3a5e6fa85c11c6c795e0c81a7215776ef8afc66de02 \
-    --hash=sha256:42419861b43e6962a649068a61f4a4839205a3ef525b858377a960b9e2de6e0d \
-    --hash=sha256:42c6680d256ab35637ef88891c6bd02514ccb7e1122133ac96055ff458f93fc3 \
-    --hash=sha256:485a8942f671120f76afffff70f259e1cd0f0cfe08f81c05d8816d958d4577d3 \
-    --hash=sha256:4c886c6cce2d070bd7df4ec4a05a13ee20c0aa60cb587e8d1265b6c03cf91da3 \
-    --hash=sha256:4e6d97288757e1ddba10dd9549ac27982e3e74a49d8d0179fc14d4365c7add66 \
-    --hash=sha256:4ef4be7baf08a203170f29e89d79064463b7fc7a0908b9d0d5114e8009c3a259 \
-    --hash=sha256:51720c776d148bad2372ca21ca29256ed483aa9a4cdefefcef49006dff2a6835 \
-    --hash=sha256:52825b01f5c4c1c4eb0db253ec09c7aa17e1a7304d247c48b6f3599ef40db8bd \
-    --hash=sha256:538fd81bb5e430cc1381a443971c0475582ff9f434c16cd46d2c66763ce85d9d \
-    --hash=sha256:5c1538c38584029352878a0466f03a8ee7547d7bd9f641f57a0f3017a7c905b8 \
-    --hash=sha256:6ff8b244d7085a0b425b56d327b480c3b29cafbd2eff27316a004f9a7391ae07 \
-    --hash=sha256:7178def594014aa6c35a8ff411cf37d682f428b3b5617ca79029d8ae72f5402b \
-    --hash=sha256:720a5ca70e136b675af3af63db533c1c8c9181314d207568bbe79051f122669e \
-    --hash=sha256:7f1478736fcebb90f97e40aff11a5f253af890c845ee0c850fe80aa060a267c6 \
-    --hash=sha256:855fe27b80375e5c5878492f0729540db47b186509c98dae341254c8f45f42ae \
-    --hash=sha256:8963b83d53ee733a6e4196954502b33567ad07dfd74851f32be18eb932fb1cb9 \
-    --hash=sha256:9261ed810972061388918c83c3f5cd46079d875026ba97380f3e3978a72f503d \
-    --hash=sha256:99b00bc72855812a60d253420d8a2eae839b0afa4938f09f4d2aa9bb4654263a \
-    --hash=sha256:ab3c84fa13c04aeeeabb2a7f67a25ef5d77ac9d6486ff33ded762ef353aa5592 \
-    --hash=sha256:afe3fe972c645b4632c563d3f3eff1cdca2fa058f730df2b93a35e3b0c538218 \
-    --hash=sha256:d19c413b3c07cbecf1f991e2221746b0d2a9410b59cb3f4fb9557f0365a1a817 \
-    --hash=sha256:df9824ac11deaf007443e7ed2a4a26bebff98d2bc43c6da21b2b64185da011c4 \
-    --hash=sha256:e46f44b54ebddbeedbd3d5b289a893219065ef805d95094d16a0af6630f5d410 \
-    --hash=sha256:f5ac9a4eeb1ec0f1ccdc6f326bcdb464de5f80eb07fb38b5ddd7b0de6bc61e55
-    # via -r requirements.in
-mypy-extensions==1.0.0 \
-    --hash=sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d \
-    --hash=sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782
-    # via mypy
 packaging==23.2 \
     --hash=sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5 \
     --hash=sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7
     # via docker
-pywin32==306 \
-    --hash=sha256:06d3420a5155ba65f0b72f2699b5bacf3109f36acbe8923765c22938a69dfc8d \
-    --hash=sha256:1c73ea9a0d2283d889001998059f5eaaba3b6238f767c9cf2833b13e6a685f65 \
-    --hash=sha256:37257794c1ad39ee9be652da0462dc2e394c8159dfd913a8a4e8eb6fd346da0e \
-    --hash=sha256:383229d515657f4e3ed1343da8be101000562bf514591ff383ae940cad65458b \
-    --hash=sha256:39b61c15272833b5c329a2989999dcae836b1eed650252ab1b7bfbe1d59f30f4 \
-    --hash=sha256:5821ec52f6d321aa59e2db7e0a35b997de60c201943557d108af9d4ae1ec7040 \
-    --hash=sha256:70dba0c913d19f942a2db25217d9a1b726c278f483a919f1abfed79c9cf64d3a \
-    --hash=sha256:72c5f621542d7bdd4fdb716227be0dd3f8565c11b280be6315b06ace35487d36 \
-    --hash=sha256:84f4471dbca1887ea3803d8848a1616429ac94a4a8d05f4bc9c5dcfd42ca99c8 \
-    --hash=sha256:a7639f51c184c0272e93f244eb24dafca9b1855707d94c192d4a0b4c01e1100e \
-    --hash=sha256:e25fd5b485b55ac9c057f67d94bc203f3f6595078d1fb3b458c9c28b7153a802 \
-    --hash=sha256:e4c092e2589b5cf0d365849e73e02c391c1349958c5ac3e9d5ccb9a28e017b3a \
-    --hash=sha256:e65028133d15b64d2ed8f06dd9fbc268352478d4f9289e69c190ecd6818b6407 \
-    --hash=sha256:e8ac1ae3601bee6ca9f7cb4b5363bf1c0badb935ef243c4733ff9a393b1690c0
+pywin32==308 \
+    --hash=sha256:00b3e11ef09ede56c6a43c71f2d31857cf7c54b0ab6e78ac659497abd2834f47 \
+    --hash=sha256:100a5442b7332070983c4cd03f2e906a5648a5104b8a7f50175f7906efd16bb6 \
+    --hash=sha256:13dcb914ed4347019fbec6697a01a0aec61019c1046c2b905410d197856326a6 \
+    --hash=sha256:1c44539a37a5b7b21d02ab34e6a4d314e0788f1690d65b48e9b0b89f31abbbed \
+    --hash=sha256:1f696ab352a2ddd63bd07430080dd598e6369152ea13a25ebcdd2f503a38f1ff \
+    --hash=sha256:3b92622e29d651c6b783e368ba7d6722b1634b8e70bd376fd7610fe1992e19de \
+    --hash=sha256:4fc888c59b3c0bef905ce7eb7e2106a07712015ea1c8234b703a088d46110e8e \
+    --hash=sha256:575621b90f0dc2695fec346b2d6302faebd4f0f45c05ea29404cefe35d89442b \
+    --hash=sha256:5794e764ebcabf4ff08c555b31bd348c9025929371763b2183172ff4708152f0 \
+    --hash=sha256:587f3e19696f4bf96fde9d8a57cec74a57021ad5f204c9e627e15c33ff568897 \
+    --hash=sha256:5d8c8015b24a7d6855b1550d8e660d8daa09983c80e5daf89a273e5c6fb5095a \
+    --hash=sha256:71b3322d949b4cc20776436a9c9ba0eeedcbc9c650daa536df63f0ff111bb920 \
+    --hash=sha256:7873ca4dc60ab3287919881a7d4f88baee4a6e639aa6962de25a98ba6b193341 \
+    --hash=sha256:796ff4426437896550d2981b9c2ac0ffd75238ad9ea2d3bfa67a1abd546d262e \
+    --hash=sha256:9b4de86c8d909aed15b7011182c8cab38c8850de36e6afb1f0db22b8959e3091 \
+    --hash=sha256:a5ab5381813b40f264fa3495b98af850098f814a25a63589a8e9eb12560f450c \
+    --hash=sha256:ef313c46d4c18dfb82a2431e3051ac8f112ccee1a34f29c263c583c568db63cd \
+    --hash=sha256:fd380990e792eaf6827fcb7e187b2b4b1cede0585e3d0c9e84201ec27b9905e4
     # via docker
 pyyaml==6.0.1 \
     --hash=sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5 \
@@ -300,7 +267,6 @@ referencing==0.33.0 \
     # via
     #   jsonschema
     #   jsonschema-specifications
-    #   types-jsonschema
 requests==2.31.0 \
     --hash=sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f \
     --hash=sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1
@@ -416,18 +382,6 @@ tomli==2.0.1 \
     --hash=sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc \
     --hash=sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f
     # via -r requirements.in
-types-jsonschema==4.21.0.20240118 \
-    --hash=sha256:31aae1b5adc0176c1155c2d4f58348b22d92ae64315e9cc83bd6902168839232 \
-    --hash=sha256:77a4ac36b0be4f24274d5b9bf0b66208ee771c05f80e34c4641de7d63e8a872d
-    # via -r requirements.in
-types-pyyaml==6.0.12.12 \
-    --hash=sha256:334373d392fde0fdf95af5c3f1661885fa10c52167b14593eb856289e1855062 \
-    --hash=sha256:c05bc6c158facb0676674b7f11fe3960db4f389718e19e62bd2b84d6205cfd24
-    # via -r requirements.in
-typing-extensions==4.9.0 \
-    --hash=sha256:23478f88c37f27d76ac8aee6c905017a143b0b1b886c3c9f66bc2fd94f9f5783 \
-    --hash=sha256:af72aea155e91adfc61c3ae9e0e342dbc0cba726d6cba4b6c72c1f34e47291cd
-    # via mypy
 urllib3==2.2.1 \
     --hash=sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d \
     --hash=sha256:d0570876c61ab9e520d776c38acbbb5b05a776d3f9ff98a5c8fd5162a444cf19

From 61e7c99f6d53f5effd3875fa646d7a1c273345ab Mon Sep 17 00:00:00 2001
From: Gregory Szorc <gregory.szorc@gmail.com>
Date: Tue, 7 Jan 2025 21:00:18 -0800
Subject: [PATCH 022/157] unix: call `ulimit -n` to avoid overheads (#468)

See inline comment in `base.Dockerfile` for why this hack is necessary.

When upgrading my machine recently, the `rlim_max` value increased to
~1B, making `apt-get` invocations take multiple minutes to complete.
https://bugs.launchpad.net/ubuntu/+source/apt/+bug/1332440 seems to
describe this issue.

The cross building images have a sufficiently new apt that doesn't seem
impacted.
---
 cpython-unix/base.Dockerfile  | 10 +++++++++-
 cpython-unix/build.Dockerfile |  2 +-
 cpython-unix/gcc.Dockerfile   |  2 +-
 cpython-unix/xcb.Dockerfile   |  2 +-
 4 files changed, 12 insertions(+), 4 deletions(-)

diff --git a/cpython-unix/base.Dockerfile b/cpython-unix/base.Dockerfile
index 76811a5a..58016550 100644
--- a/cpython-unix/base.Dockerfile
+++ b/cpython-unix/base.Dockerfile
@@ -33,4 +33,12 @@ RUN ( echo 'amd64'; \
       echo 'i386'; \
     ) > /var/lib/dpkg/arch
 
-RUN apt-get update
+# apt iterates all available file descriptors up to rlim_max and calls
+# fcntl(fd, F_SETFD, FD_CLOEXEC). This can result in millions of system calls
+# (we've seen 1B in the wild) and cause operations to take seconds to minutes.
+# Setting a fd limit mitigates.
+#
+# Attempts at enforcing the limit globally via /etc/security/limits.conf and
+# /root/.bashrc were not successful. Possibly because container image builds
+# don't perform a login or use a shell the way we expect.
+RUN ulimit -n 10000 && apt-get update
diff --git a/cpython-unix/build.Dockerfile b/cpython-unix/build.Dockerfile
index af077c6b..09e37fab 100644
--- a/cpython-unix/build.Dockerfile
+++ b/cpython-unix/build.Dockerfile
@@ -10,7 +10,7 @@
 # Compression packages are needed to extract archives.
 #
 # Various other build tools are needed for various building.
-RUN apt-get install \
+RUN ulimit -n 10000 && apt-get install \
     bzip2 \
     file \
     libc6-dev \
diff --git a/cpython-unix/gcc.Dockerfile b/cpython-unix/gcc.Dockerfile
index ea6d1030..f3b76ade 100644
--- a/cpython-unix/gcc.Dockerfile
+++ b/cpython-unix/gcc.Dockerfile
@@ -1,5 +1,5 @@
 {% include 'base.Dockerfile' %}
-RUN apt-get install \
+RUN ulimit -n 10000 && apt-get install \
       autoconf \
       automake \
       bison \
diff --git a/cpython-unix/xcb.Dockerfile b/cpython-unix/xcb.Dockerfile
index 0480ecae..33d350e2 100644
--- a/cpython-unix/xcb.Dockerfile
+++ b/cpython-unix/xcb.Dockerfile
@@ -1,3 +1,3 @@
 {% include 'build.Dockerfile' %}
-RUN apt-get install \
+RUN ulimit -n 10000 && apt-get install \
     python

From e0ebbc70ec741cc5ee7c45046046e13b414e1ea1 Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Wed, 8 Jan 2025 12:52:24 -0600
Subject: [PATCH 023/157] Retry on transient failures during artifact upload
 (#486)

Attempting to fix transient release failures, e.g,
https://github.com/astral-sh/python-build-standalone/actions/runs/12637445294/job/35213894154
---
 Cargo.lock    | 296 +++++++++++++++++++++++++++++++++++++++++++++-----
 Cargo.toml    |   2 +
 src/github.rs | 104 ++++++++++++------
 3 files changed, 337 insertions(+), 65 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 9aaecd10..425d307b 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1,6 +1,6 @@
 # This file is automatically @generated by Cargo.
 # It is not intended for manual editing.
-version = 3
+version = 4
 
 [[package]]
 name = "addr2line"
@@ -122,7 +122,7 @@ checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.50",
+ "syn 2.0.95",
 ]
 
 [[package]]
@@ -152,6 +152,12 @@ version = "0.21.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567"
 
+[[package]]
+name = "base64"
+version = "0.22.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
+
 [[package]]
 name = "base64ct"
 version = "1.6.0"
@@ -464,7 +470,7 @@ checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd"
 dependencies = [
  "cfg-if",
  "libc",
- "redox_syscall",
+ "redox_syscall 0.4.1",
  "windows-sys 0.52.0",
 ]
 
@@ -564,7 +570,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.50",
+ "syn 2.0.95",
 ]
 
 [[package]]
@@ -911,6 +917,18 @@ dependencies = [
  "generic-array",
 ]
 
+[[package]]
+name = "instant"
+version = "0.1.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222"
+dependencies = [
+ "cfg-if",
+ "js-sys",
+ "wasm-bindgen",
+ "web-sys",
+]
+
 [[package]]
 name = "ipnet"
 version = "2.9.0"
@@ -948,7 +966,7 @@ version = "9.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "5c7ea04a7c5c055c175f189b6dc6ba036fd62306b58c66c9f6389036c503a3f4"
 dependencies = [
- "base64",
+ "base64 0.21.7",
  "js-sys",
  "pem",
  "ring",
@@ -990,6 +1008,16 @@ version = "0.4.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c"
 
+[[package]]
+name = "lock_api"
+version = "0.4.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17"
+dependencies = [
+ "autocfg",
+ "scopeguard",
+]
+
 [[package]]
 name = "log"
 version = "0.4.20"
@@ -1106,7 +1134,7 @@ checksum = "9fc61913d67d5ed8e04b55c611ec7450ab811f83aa424f3bd00782c6b0296ae7"
 dependencies = [
  "arc-swap",
  "async-trait",
- "base64",
+ "base64 0.21.7",
  "bytes",
  "cfg-if",
  "chrono",
@@ -1167,7 +1195,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.50",
+ "syn 2.0.95",
 ]
 
 [[package]]
@@ -1198,6 +1226,31 @@ dependencies = [
  "windows-sys 0.52.0",
 ]
 
+[[package]]
+name = "parking_lot"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99"
+dependencies = [
+ "instant",
+ "lock_api",
+ "parking_lot_core",
+]
+
+[[package]]
+name = "parking_lot_core"
+version = "0.8.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc"
+dependencies = [
+ "cfg-if",
+ "instant",
+ "libc",
+ "redox_syscall 0.2.16",
+ "smallvec",
+ "winapi",
+]
+
 [[package]]
 name = "password-hash"
 version = "0.4.2"
@@ -1238,7 +1291,7 @@ version = "3.0.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1b8fcc794035347fb64beda2d3b462595dd2753e3f268d89c5aae77e8cf2c310"
 dependencies = [
- "base64",
+ "base64 0.21.7",
  "serde",
 ]
 
@@ -1276,7 +1329,7 @@ checksum = "266c042b60c9c76b8d53061e52b2e0d1116abc57cefc8c5cd671619a56ac3690"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.50",
+ "syn 2.0.95",
 ]
 
 [[package]]
@@ -1309,7 +1362,7 @@ version = "1.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e5699cc8a63d1aa2b1ee8e12b9ad70ac790d65788cd36101fa37f87ea46c4cef"
 dependencies = [
- "base64",
+ "base64 0.21.7",
  "indexmap",
  "line-wrap",
  "quick-xml",
@@ -1323,11 +1376,20 @@ version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
 
+[[package]]
+name = "ppv-lite86"
+version = "0.2.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04"
+dependencies = [
+ "zerocopy",
+]
+
 [[package]]
 name = "proc-macro2"
-version = "1.0.78"
+version = "1.0.92"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae"
+checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0"
 dependencies = [
  "unicode-ident",
 ]
@@ -1356,7 +1418,9 @@ dependencies = [
  "pdb",
  "pep440_rs",
  "rayon",
- "reqwest",
+ "reqwest 0.11.24",
+ "reqwest-middleware",
+ "reqwest-retry",
  "scroll 0.12.0",
  "semver",
  "serde",
@@ -1390,11 +1454,35 @@ dependencies = [
  "proc-macro2",
 ]
 
+[[package]]
+name = "rand"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
+dependencies = [
+ "libc",
+ "rand_chacha",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
+dependencies = [
+ "ppv-lite86",
+ "rand_core",
+]
+
 [[package]]
 name = "rand_core"
 version = "0.6.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
+dependencies = [
+ "getrandom",
+]
 
 [[package]]
 name = "rayon"
@@ -1416,6 +1504,15 @@ dependencies = [
  "crossbeam-utils",
 ]
 
+[[package]]
+name = "redox_syscall"
+version = "0.2.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
+dependencies = [
+ "bitflags 1.3.2",
+]
+
 [[package]]
 name = "redox_syscall"
 version = "0.4.1"
@@ -1431,7 +1528,7 @@ version = "0.11.24"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c6920094eb85afde5e4a138be3f2de8bbdf28000f0029e72c45025a56b042251"
 dependencies = [
- "base64",
+ "base64 0.21.7",
  "bytes",
  "encoding_rs",
  "futures-core",
@@ -1454,7 +1551,7 @@ dependencies = [
  "serde",
  "serde_json",
  "serde_urlencoded",
- "sync_wrapper",
+ "sync_wrapper 0.1.2",
  "system-configuration",
  "tokio",
  "tokio-native-tls",
@@ -1465,7 +1562,88 @@ dependencies = [
  "wasm-bindgen-futures",
  "wasm-streams",
  "web-sys",
- "winreg",
+ "winreg 0.50.0",
+]
+
+[[package]]
+name = "reqwest"
+version = "0.12.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c7d6d2a27d57148378eb5e111173f4276ad26340ecc5c49a4a2152167a2d6a37"
+dependencies = [
+ "base64 0.22.1",
+ "bytes",
+ "futures-core",
+ "futures-util",
+ "http 1.0.0",
+ "http-body 1.0.0",
+ "http-body-util",
+ "hyper 1.2.0",
+ "hyper-util",
+ "ipnet",
+ "js-sys",
+ "log",
+ "mime",
+ "once_cell",
+ "percent-encoding",
+ "pin-project-lite",
+ "serde",
+ "serde_json",
+ "serde_urlencoded",
+ "sync_wrapper 1.0.2",
+ "tokio",
+ "tower-service",
+ "url",
+ "wasm-bindgen",
+ "wasm-bindgen-futures",
+ "web-sys",
+ "winreg 0.52.0",
+]
+
+[[package]]
+name = "reqwest-middleware"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d1ccd3b55e711f91a9885a2fa6fbbb2e39db1776420b062efc058c6410f7e5e3"
+dependencies = [
+ "anyhow",
+ "async-trait",
+ "http 1.0.0",
+ "reqwest 0.12.5",
+ "serde",
+ "thiserror",
+ "tower-service",
+]
+
+[[package]]
+name = "reqwest-retry"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "29c73e4195a6bfbcb174b790d9b3407ab90646976c55de58a6515da25d851178"
+dependencies = [
+ "anyhow",
+ "async-trait",
+ "futures",
+ "getrandom",
+ "http 1.0.0",
+ "hyper 1.2.0",
+ "parking_lot",
+ "reqwest 0.12.5",
+ "reqwest-middleware",
+ "retry-policies",
+ "thiserror",
+ "tokio",
+ "tracing",
+ "wasm-timer",
+]
+
+[[package]]
+name = "retry-policies"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5875471e6cab2871bc150ecb8c727db5113c9338cc3354dc5ee3425b6aa40a1c"
+dependencies = [
+ "rand",
 ]
 
 [[package]]
@@ -1547,7 +1725,7 @@ version = "1.0.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c"
 dependencies = [
- "base64",
+ "base64 0.21.7",
 ]
 
 [[package]]
@@ -1556,7 +1734,7 @@ version = "2.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3c333bb734fcdedcea57de1602543590f545f127dc8b533324318fd492c5c70b"
 dependencies = [
- "base64",
+ "base64 0.21.7",
  "rustls-pki-types",
 ]
 
@@ -1619,6 +1797,12 @@ dependencies = [
  "windows-sys 0.52.0",
 ]
 
+[[package]]
+name = "scopeguard"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
+
 [[package]]
 name = "scroll"
 version = "0.11.0"
@@ -1642,7 +1826,7 @@ checksum = "7f81c2fde025af7e69b1d1420531c8a8811ca898919db177141a85313b1cb932"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.50",
+ "syn 2.0.95",
 ]
 
 [[package]]
@@ -1710,7 +1894,7 @@ checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.50",
+ "syn 2.0.95",
 ]
 
 [[package]]
@@ -1888,9 +2072,9 @@ dependencies = [
 
 [[package]]
 name = "syn"
-version = "2.0.50"
+version = "2.0.95"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "74f1bdc9872430ce9b75da68329d1c1746faf50ffac5f19e02b71e37ff881ffb"
+checksum = "46f71c0377baf4ef1cc3e3402ded576dccc315800fbc62dfc7fe04b009773b4a"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -1903,6 +2087,12 @@ version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160"
 
+[[package]]
+name = "sync_wrapper"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263"
+
 [[package]]
 name = "system-configuration"
 version = "0.5.1"
@@ -1960,22 +2150,22 @@ dependencies = [
 
 [[package]]
 name = "thiserror"
-version = "1.0.57"
+version = "1.0.69"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e45bcbe8ed29775f228095caf2cd67af7a4ccf756ebff23a306bf3e8b47b24b"
+checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
 dependencies = [
  "thiserror-impl",
 ]
 
 [[package]]
 name = "thiserror-impl"
-version = "1.0.57"
+version = "1.0.69"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81"
+checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.50",
+ "syn 2.0.95",
 ]
 
 [[package]]
@@ -2143,7 +2333,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.50",
+ "syn 2.0.95",
 ]
 
 [[package]]
@@ -2300,7 +2490,7 @@ dependencies = [
  "once_cell",
  "proc-macro2",
  "quote",
- "syn 2.0.50",
+ "syn 2.0.95",
  "wasm-bindgen-shared",
 ]
 
@@ -2334,7 +2524,7 @@ checksum = "642f325be6301eb8107a83d12a8ac6c1e1c54345a7ef1a9261962dfefda09e66"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.50",
+ "syn 2.0.95",
  "wasm-bindgen-backend",
  "wasm-bindgen-shared",
 ]
@@ -2358,6 +2548,21 @@ dependencies = [
  "web-sys",
 ]
 
+[[package]]
+name = "wasm-timer"
+version = "0.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "be0ecb0db480561e9a7642b5d3e4187c128914e58aa84330b9493e3eb68c5e7f"
+dependencies = [
+ "futures",
+ "js-sys",
+ "parking_lot",
+ "pin-utils",
+ "wasm-bindgen",
+ "wasm-bindgen-futures",
+ "web-sys",
+]
+
 [[package]]
 name = "web-sys"
 version = "0.3.68"
@@ -2541,6 +2746,16 @@ dependencies = [
  "windows-sys 0.48.0",
 ]
 
+[[package]]
+name = "winreg"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a277a57398d4bfa075df44f501a17cfdf8542d224f0d36095a2adc7aee4ef0a5"
+dependencies = [
+ "cfg-if",
+ "windows-sys 0.48.0",
+]
+
 [[package]]
 name = "xattr"
 version = "1.3.1"
@@ -2561,6 +2776,27 @@ dependencies = [
  "linked-hash-map",
 ]
 
+[[package]]
+name = "zerocopy"
+version = "0.7.35"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
+dependencies = [
+ "byteorder",
+ "zerocopy-derive",
+]
+
+[[package]]
+name = "zerocopy-derive"
+version = "0.7.35"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.95",
+]
+
 [[package]]
 name = "zeroize"
 version = "1.7.0"
diff --git a/Cargo.toml b/Cargo.toml
index f8d5bf84..ba5b32ac 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -26,6 +26,8 @@ pdb = "0.8.0"
 pep440_rs = "0.6.6"
 rayon = "1.8.1"
 reqwest = { version = "0.11.24", features = ["rustls", "stream"] }
+reqwest-middleware = "0.4.0"
+reqwest-retry = "0.7.0"
 scroll = "0.12.0"
 semver = "1.0.22"
 serde = { version = "1.0.197", features = ["derive"] }
diff --git a/src/github.rs b/src/github.rs
index 5197e775..bfc03d01 100644
--- a/src/github.rs
+++ b/src/github.rs
@@ -2,8 +2,6 @@
 // License, v. 2.0. If a copy of the MPL was not distributed with this
 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
 
-use std::str::FromStr;
-
 use {
     crate::release::{
         bootstrap_llvm, produce_install_only, produce_install_only_stripped, RELEASE_TRIPLES,
@@ -18,16 +16,39 @@ use {
         Octocrab, OctocrabBuilder,
     },
     rayon::prelude::*,
+    reqwest::StatusCode,
+    reqwest_middleware::{reqwest, ClientBuilder, ClientWithMiddleware},
+    reqwest_retry::{
+        default_on_request_failure, policies::ExponentialBackoff, RetryTransientMiddleware,
+        Retryable, RetryableStrategy,
+    },
     sha2::{Digest, Sha256},
     std::{
         collections::{BTreeMap, BTreeSet, HashMap},
         io::Read,
         path::PathBuf,
+        str::FromStr,
     },
     url::Url,
     zip::ZipArchive,
 };
 
+/// A retry strategy for GitHub uploads.
+struct GitHubUploadRetryStrategy;
+impl RetryableStrategy for GitHubUploadRetryStrategy {
+    fn handle(
+        &self,
+        res: &std::result::Result<reqwest::Response, reqwest_middleware::Error>,
+    ) -> Option<Retryable> {
+        match res {
+            // Retry on 403s, these indicate a transient failure.
+            Ok(success) if success.status() == StatusCode::FORBIDDEN => Some(Retryable::Transient),
+            Ok(_) => None,
+            Err(error) => default_on_request_failure(error),
+        }
+    }
+}
+
 async fn fetch_artifact(
     client: &Octocrab,
     org: &str,
@@ -45,6 +66,7 @@ async fn fetch_artifact(
 }
 
 async fn upload_release_artifact(
+    client: &ClientWithMiddleware,
     auth_token: String,
     release: &Release,
     filename: String,
@@ -74,8 +96,7 @@ async fn upload_release_artifact(
     // Octocrab doesn't yet support release artifact upload. And the low-level HTTP API
     // forces the use of strings on us. So we have to make our own HTTP client.
 
-    let response = reqwest::Client::builder()
-        .build()?
+    let response = client
         .put(url)
         .header("Authorization", format!("Bearer {auth_token}"))
         .header("Content-Length", data.len())
@@ -451,42 +472,54 @@ pub async fn command_upload_release_distributions(args: &ArgMatches) -> Result<(
 
     let mut digests = BTreeMap::new();
 
-    let mut fs = vec![];
-
-    for (source, dest) in wanted_filenames {
-        if !filenames.contains(&source) {
-            continue;
-        }
-
-        let file_data = Bytes::copy_from_slice(&std::fs::read(dist_dir.join(&source))?);
+    let retry_policy = ExponentialBackoff::builder().build_with_max_retries(5);
+    let raw_client = ClientBuilder::new(reqwest_middleware::reqwest::Client::new())
+        .with(RetryTransientMiddleware::new_with_policy_and_strategy(
+            retry_policy,
+            GitHubUploadRetryStrategy,
+        ))
+        .build();
 
-        let mut digest = Sha256::new();
-        digest.update(&file_data);
+    {
+        let mut fs = vec![];
 
-        let digest = hex::encode(digest.finalize());
-
-        digests.insert(dest.clone(), digest.clone());
+        for (source, dest) in wanted_filenames {
+            if !filenames.contains(&source) {
+                continue;
+            }
 
-        fs.push(upload_release_artifact(
-            token.clone(),
-            &release,
-            dest.clone(),
-            file_data,
-            dry_run,
-        ));
-        fs.push(upload_release_artifact(
-            token.clone(),
-            &release,
-            format!("{}.sha256", dest),
-            Bytes::copy_from_slice(format!("{}\n", digest).as_bytes()),
-            dry_run,
-        ));
-    }
+            let file_data = Bytes::copy_from_slice(&std::fs::read(dist_dir.join(&source))?);
+
+            let mut digest = Sha256::new();
+            digest.update(&file_data);
+
+            let digest = hex::encode(digest.finalize());
+
+            digests.insert(dest.clone(), digest.clone());
+
+            fs.push(upload_release_artifact(
+                &raw_client,
+                token.clone(),
+                &release,
+                dest.clone(),
+                file_data,
+                dry_run,
+            ));
+            fs.push(upload_release_artifact(
+                &raw_client,
+                token.clone(),
+                &release,
+                format!("{}.sha256", dest),
+                Bytes::copy_from_slice(format!("{}\n", digest).as_bytes()),
+                dry_run,
+            ));
+        }
 
-    let mut buffered = futures::stream::iter(fs).buffer_unordered(16);
+        let mut buffered = futures::stream::iter(fs).buffer_unordered(16);
 
-    while let Some(res) = buffered.next().await {
-        res?;
+        while let Some(res) = buffered.next().await {
+            res?;
+        }
     }
 
     let shasums = digests
@@ -498,6 +531,7 @@ pub async fn command_upload_release_distributions(args: &ArgMatches) -> Result<(
     std::fs::write(dist_dir.join("SHA256SUMS"), shasums.as_bytes())?;
 
     upload_release_artifact(
+        &raw_client,
         token.clone(),
         &release,
         "SHA256SUMS".to_string(),

From e985fa10745550211eac5a926d1c73f2a3dfbbd6 Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Wed, 8 Jan 2025 13:22:41 -0600
Subject: [PATCH 024/157] Fix check for `--run` in CI (#487)

---
 .github/workflows/linux.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml
index 901233ad..faab0ccb 100644
--- a/.github/workflows/linux.yml
+++ b/.github/workflows/linux.yml
@@ -224,7 +224,7 @@ jobs:
         run: |
           chmod +x build/pythonbuild
 
-          if [ -n "${{ matrix.run }}" ]; then
+          if [ "${{ matrix.run }}" == "true" ]; then
             EXTRA_ARGS="--run"
           fi
 

From e1deaa152a01319f1482a321ed091fca7fdfafdd Mon Sep 17 00:00:00 2001
From: samypr100 <3933065+samypr100@users.noreply.github.com>
Date: Fri, 10 Jan 2025 14:31:54 -0500
Subject: [PATCH 025/157] Add support for build attestations (#481)

Follow up on feedback from #371 and the previous work from @orf which I
cherry-picked.

This adds build attestations for the builds using
[actions/attest-build-provenance](https://github.com/actions/attest-build-provenance).

Closes #343

### Test Plan

Did a trial CI run which results in attestations like below for
`cpython-3.10-aarch64-unknown-linux-gnu-lto`

*
https://github.com/samypr100/python-build-standalone/attestations/4246020
* https://search.sigstore.dev/?logIndex=160192732

Co-authored-by: Thomas Forbes <tom.forbes@gitguardian.com>
Co-authored-by: Zanie Blue <contact@zanie.dev>
---
 .github/workflows/linux.yml   | 14 ++++++++++++--
 .github/workflows/macos.yml   | 12 +++++++++++-
 .github/workflows/windows.yml | 14 ++++++++++++--
 3 files changed, 35 insertions(+), 5 deletions(-)

diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml
index faab0ccb..45bab94b 100644
--- a/.github/workflows/linux.yml
+++ b/.github/workflows/linux.yml
@@ -130,7 +130,7 @@ jobs:
       pythonbuild_changed: ${{ steps.changed.outputs.pythonbuild_any_changed }}
     steps:
       - uses: actions/checkout@v4
-      
+
       - name: Set up Python
         uses: astral-sh/setup-uv@v4
 
@@ -140,7 +140,7 @@ jobs:
           # Convert GitHub labels array to comma-separated string
           LABELS=$(echo '${{ toJson(github.event.pull_request.labels.*.name) }}' | jq -r 'join(",")')
           echo "labels=$LABELS" >> $GITHUB_OUTPUT
-          
+
       - name: Generate build matrix
         id: set-matrix
         run: |
@@ -168,6 +168,10 @@ jobs:
       - generate-matrix
       - pythonbuild
       - image
+    # Permissions used for actions/attest-build-provenance
+    permissions:
+      id-token: write
+      attestations: write
     runs-on: ${{ matrix.runner }}
     strategy:
       matrix: ${{ fromJson(needs.generate-matrix.outputs.matrix) }}
@@ -230,6 +234,12 @@ jobs:
 
           build/pythonbuild validate-distribution ${EXTRA_ARGS} dist/*.tar.zst
 
+      - name: Generate attestations
+        uses: actions/attest-build-provenance@v2
+        if: ${{ github.ref == 'refs/heads/main' }}
+        with:
+          subject-path: dist/*
+
       - name: Upload Distribution
         if: ${{ ! matrix.dry-run }}
         uses: actions/upload-artifact@v4
diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml
index 7aafefa9..50345e0e 100644
--- a/.github/workflows/macos.yml
+++ b/.github/workflows/macos.yml
@@ -87,10 +87,14 @@ jobs:
     needs:
       - generate-matrix
       - pythonbuild
+    # Permissions used for actions/attest-build-provenance
+    permissions:
+      id-token: write
+      attestations: write
+    runs-on: ${{ matrix.runner }}
     strategy:
       matrix: ${{ fromJson(needs.generate-matrix.outputs.matrix) }}
       fail-fast: false
-    runs-on: ${{ matrix.runner }}
     name: ${{ matrix.target_triple }} / ${{ matrix.python }} / ${{ matrix.build_options }}
     steps:
       - uses: actions/checkout@v4
@@ -122,6 +126,12 @@ jobs:
 
           ./build-macos.py --target-triple ${{ matrix.target_triple }} --python cpython-${{ matrix.python }} --options ${{ matrix.build_options }}
 
+      - name: Generate attestations
+        uses: actions/attest-build-provenance@v2
+        if: ${{ github.ref == 'refs/heads/main' }}
+        with:
+          subject-path: dist/*
+
       - name: Upload Distributions
         if: ${{ ! matrix.dry-run }}
         uses: actions/upload-artifact@v4
diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml
index c625b410..179cfb99 100644
--- a/.github/workflows/windows.yml
+++ b/.github/workflows/windows.yml
@@ -51,7 +51,7 @@ jobs:
       pythonbuild_changed: ${{ steps.changed.outputs.pythonbuild_any_changed }}
     steps:
       - uses: actions/checkout@v4
-      
+
       - name: Set up Python
         uses: astral-sh/setup-uv@v4
 
@@ -61,7 +61,7 @@ jobs:
           # Convert GitHub labels array to comma-separated string
           LABELS=$(echo '${{ toJson(github.event.pull_request.labels.*.name) }}' | jq -r 'join(",")')
           echo "labels=$LABELS" >> $GITHUB_OUTPUT
-          
+
       - name: Generate build matrix
         id: set-matrix
         run: |
@@ -88,6 +88,10 @@ jobs:
     needs:
       - generate-matrix
       - pythonbuild
+    # Permissions used for actions/attest-build-provenance
+    permissions:
+      id-token: write
+      attestations: write
     runs-on: ${{ matrix.runner }}
     strategy:
       matrix: ${{ fromJson(needs.generate-matrix.outputs.matrix) }}
@@ -132,6 +136,12 @@ jobs:
           $Dists = Resolve-Path -Path "dist/*.tar.zst" -Relative
           .\pythonbuild.exe validate-distribution --run $Dists
 
+      - name: Generate attestations
+        uses: actions/attest-build-provenance@v2
+        if: ${{ github.ref == 'refs/heads/main' }}
+        with:
+          subject-path: dist/*
+
       - name: Upload Distributions
         uses: actions/upload-artifact@v4
         with:

From cda1c64dd1b3b7e457d3cc5efc5ff6bf7229f5a3 Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Fri, 10 Jan 2025 15:56:03 -0600
Subject: [PATCH 026/157] Implement matrix sharding (#492)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Since we've encountered the GitHub matrix size limit of 256 entries a
couple times now (recently in #388), this adds sharding to our matrix
generation script.

There's now a `--max-shards` option which splits the matrix into (up to)
the requested number of shards. We don't split it evenly, we eagerly
fill each shard first. To consume the shards, we just copy the `build`
job into two identical child jobs which consume each matrix shard.
Ideally, we'd avoid code duplication here by using a re-usable action or
something for the build-steps — but that's overkill at this point.

We only need this for Linux for the foreseeable future.
---
 .github/workflows/linux.yml | 93 +++++++++++++++++++++++++++++++++++--
 ci-matrix.py                | 44 ++++++++++++++----
 2 files changed, 124 insertions(+), 13 deletions(-)

diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml
index 45bab94b..aff3d53c 100644
--- a/.github/workflows/linux.yml
+++ b/.github/workflows/linux.yml
@@ -125,7 +125,8 @@ jobs:
   generate-matrix:
     runs-on: ubuntu-latest
     outputs:
-      matrix: ${{ steps.set-matrix.outputs.matrix }}
+      matrix-0: ${{ steps.set-matrix.outputs.matrix-0 }}
+      matrix-1: ${{ steps.set-matrix.outputs.matrix-1 }}
       any_builds: ${{ steps.set-matrix.outputs.any_builds }}
       pythonbuild_changed: ${{ steps.changed.outputs.pythonbuild_any_changed }}
     steps:
@@ -144,11 +145,19 @@ jobs:
       - name: Generate build matrix
         id: set-matrix
         run: |
-          uv run ci-matrix.py --platform linux --labels '${{ steps.get-labels.outputs.labels }}' > matrix.json && echo "matrix=$(cat matrix.json)" >> $GITHUB_OUTPUT
+          uv run ci-matrix.py \
+            --platform linux \
+            --labels '${{ steps.get-labels.outputs.labels }}' \
+            --max-shards 2 \
+            > matrix.json
+
+          echo "matrix-0=$(jq -c '.["0"]' matrix.json)" >> $GITHUB_OUTPUT
+          echo "matrix-1=$(jq -c '.["1"]' matrix.json)" >> $GITHUB_OUTPUT
+
           # Display the matrix for debugging too
           cat matrix.json | jq
 
-          if jq -e '.include | length > 0' matrix.json > /dev/null; then
+          if jq -e '.["0"].include | length > 0' matrix.json > /dev/null; then
             # Build matrix has entries
             echo "any_builds=true" >> $GITHUB_OUTPUT
           else
@@ -163,7 +172,7 @@ jobs:
             pythonbuild:
               - "src/*.rs"
 
-  build:
+  build-0:
     needs:
       - generate-matrix
       - pythonbuild
@@ -174,7 +183,81 @@ jobs:
       attestations: write
     runs-on: ${{ matrix.runner }}
     strategy:
-      matrix: ${{ fromJson(needs.generate-matrix.outputs.matrix) }}
+      matrix: ${{ fromJson(needs.generate-matrix.outputs.matrix-0) }}
+      fail-fast: false
+    name: ${{ matrix.target_triple }} / ${{ matrix.python }} / ${{ matrix.build_options }}
+    steps:
+      - uses: actions/checkout@v4
+        with:
+          fetch-depth: 0
+
+      - name: Install Python
+        uses: actions/setup-python@v5
+        with:
+          python-version: '3.11'
+
+      - name: Download pythonbuild
+        uses: actions/download-artifact@v4
+        with:
+          name: pythonbuild
+          path: build
+
+      - name: Download images
+        uses: actions/download-artifact@v4
+        with:
+          pattern: image-*
+          path: build
+          merge-multiple: true
+
+      - name: Load Docker Images
+        run: |
+          for f in build/image-*.tar.zst; do
+            echo "decompressing $f"
+            zstd -d --rm ${f}
+          done
+
+          for f in build/image-*.tar; do
+            echo "loading $f"
+            docker load --input $f
+          done
+
+      - name: Build
+        if: ${{ ! matrix.dry-run }}
+        run: |
+          # Do empty target so all generated files are touched.
+          ./build-linux.py --make-target empty
+
+          # Touch mtimes of all images so they are newer than autogenerated files above.
+          touch build/image-*
+
+          ./build-linux.py --target-triple ${{ matrix.target_triple }} --python cpython-${{ matrix.python }} --options ${{ matrix.build_options }}
+
+      - name: Validate Distribution
+        if: ${{ ! matrix.dry-run }}
+        run: |
+          chmod +x build/pythonbuild
+
+          if [ "${{ matrix.run }}" == "true" ]; then
+            EXTRA_ARGS="--run"
+          fi
+
+          build/pythonbuild validate-distribution ${EXTRA_ARGS} dist/*.tar.zst
+
+      - name: Upload Distribution
+        if: ${{ ! matrix.dry-run }}
+        uses: actions/upload-artifact@v4
+        with:
+          name: cpython-${{ matrix.python }}-${{ matrix.target_triple }}-${{ matrix.build_options }}
+          path: dist/*
+
+  build-1:
+    needs:
+      - generate-matrix
+      - pythonbuild
+      - image
+    runs-on: ${{ matrix.runner }}
+    strategy:
+      matrix: ${{ fromJson(needs.generate-matrix.outputs.matrix-1) }}
       fail-fast: false
     name: ${{ matrix.target_triple }} / ${{ matrix.python }} / ${{ matrix.build_options }}
     steps:
diff --git a/ci-matrix.py b/ci-matrix.py
index e9b882fa..c9bcccee 100644
--- a/ci-matrix.py
+++ b/ci-matrix.py
@@ -8,6 +8,7 @@
 
 import argparse
 import json
+import sys
 from typing import Any, Optional
 
 import yaml
@@ -16,6 +17,7 @@
 CI_TARGETS_YAML = "ci-targets.yaml"
 CI_RUNNERS_YAML = "ci-runners.yaml"
 CI_EXTRA_SKIP_LABELS = ["documentation"]
+CI_MATRIX_SIZE_LIMIT = 256  # The maximum size of a matrix in GitHub Actions
 
 
 def meets_conditional_version(version: str, min_version: str) -> bool:
@@ -216,6 +218,12 @@ def parse_args() -> argparse.Namespace:
         choices=["darwin", "linux", "windows"],
         help="Filter matrix entries by platform",
     )
+    parser.add_argument(
+        "--max-shards",
+        type=int,
+        default=0,
+        help="The maximum number of shards allowed; set to zero to disable ",
+    )
     parser.add_argument(
         "--labels",
         help="Comma-separated list of labels to filter by (e.g., 'platform:darwin,python:3.13,build:debug'), all must match.",
@@ -246,14 +254,34 @@ def main() -> None:
             if runner_config.get("free")
         }
 
-    matrix = {
-        "include": generate_matrix_entries(
-            config,
-            runners,
-            args.platform,
-            labels,
-        )
-    }
+    entries = generate_matrix_entries(
+        config,
+        runners,
+        args.platform,
+        labels,
+    )
+
+    if args.max_shards:
+        matrix = {}
+        shards = (len(entries) // CI_MATRIX_SIZE_LIMIT) + 1
+        if shards > args.max_shards:
+            print(
+                f"error: matrix of size {len(entries)} requires {shards} shards, but the maximum is {args.max_shards}; consider increasing `--max-shards`",
+                file=sys.stderr,
+            )
+            sys.exit(1)
+        for shard in range(args.max_shards):
+            shard_entries = entries[
+                shard * CI_MATRIX_SIZE_LIMIT : (shard + 1) * CI_MATRIX_SIZE_LIMIT
+            ]
+            matrix[str(shard)] = {"include": shard_entries}
+    else:
+        if len(entries) > CI_MATRIX_SIZE_LIMIT:
+            print(
+                f"warning: matrix of size {len(entries)} exceeds limit of {CI_MATRIX_SIZE_LIMIT} but sharding is not enabled; consider setting `--max-shards`",
+                file=sys.stderr,
+            )
+        matrix = {"include": entries}
 
     print(json.dumps(matrix))
 

From 62f1b0393cee7dc30333ec337ce25d4ab12f341b Mon Sep 17 00:00:00 2001
From: Xeonacid <h.dwwwwww@gmail.com>
Date: Wed, 15 Jan 2025 01:32:25 +0800
Subject: [PATCH 027/157] Add riscv64-linux support (#491)

Added separate Dockerfiles for riscv64 as suggested by
https://github.com/astral-sh/python-build-standalone/issues/219#issuecomment-1962751095.

RISC-V needs `atomic` linked which is added to
`LINUX_ALLOW_SYSTEM_LIBRARIES`.

Tested locally with `./build-linux.py --target-triple
riscv64-unknown-linux-gnu --python
cpython-{3.9,3.10,3.11,3.12,3.13,3.14}` and all build fine.

CI is added but not tested yet. I'd like the PR to test itself :P

Closes #388
---
 .github/workflows/linux.yml                 |  2 +
 ci-targets.yaml                             | 21 +++++++
 cpython-unix/build-cpython.sh               |  3 +
 cpython-unix/build-libX11.sh                |  3 +
 cpython-unix/build-main.py                  |  2 +
 cpython-unix/build.cross-riscv64.Dockerfile | 68 +++++++++++++++++++++
 cpython-unix/build.py                       |  7 +++
 cpython-unix/extension-modules.yml          |  1 +
 cpython-unix/targets.yml                    | 40 ++++++++++++
 cpython-unix/xcb.cross-riscv64.Dockerfile   |  3 +
 docs/building.rst                           |  1 +
 src/release.rs                              | 13 ++++
 src/validation.rs                           |  8 +++
 13 files changed, 172 insertions(+)
 create mode 100644 cpython-unix/build.cross-riscv64.Dockerfile
 create mode 100644 cpython-unix/xcb.cross-riscv64.Dockerfile

diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml
index aff3d53c..26b97f23 100644
--- a/.github/workflows/linux.yml
+++ b/.github/workflows/linux.yml
@@ -58,9 +58,11 @@ jobs:
         image:
           - build
           - build.cross
+          - build.cross-riscv64
           - gcc
           - xcb
           - xcb.cross
+          - xcb.cross-riscv64
     name: ${{ matrix.image }}
     runs-on: depot-ubuntu-22.04
     permissions:
diff --git a/ci-targets.yaml b/ci-targets.yaml
index cd6d2916..0ecc662d 100644
--- a/ci-targets.yaml
+++ b/ci-targets.yaml
@@ -143,6 +143,27 @@ linux:
           - freethreaded+lto
         minimum-python-version: "3.13"
 
+  riscv64-unknown-linux-gnu:
+    arch: riscv64
+    libc: gnu
+    python_versions:
+      - "3.9"
+      - "3.10"
+      - "3.11"
+      - "3.12"
+      - "3.13"
+      - "3.14"
+    build_options:
+      - debug
+      - noopt
+      - lto
+    build_options_conditional:
+      - options:
+          - freethreaded+debug
+          - freethreaded+noopt
+          - freethreaded+lto
+        minimum-python-version: "3.13"
+
   x86_64-unknown-linux-gnu:
     arch: x86_64
     libc: gnu
diff --git a/cpython-unix/build-cpython.sh b/cpython-unix/build-cpython.sh
index bd9c7bc7..edf68527 100755
--- a/cpython-unix/build-cpython.sh
+++ b/cpython-unix/build-cpython.sh
@@ -936,6 +936,9 @@ mips64el-unknown-linux-gnuabi64)
 ppc64le-unknown-linux-gnu)
     PYTHON_ARCH="powerpc64le-linux-gnu"
     ;;
+riscv64-unknown-linux-gnu)
+    PYTHON_ARCH="riscv64-linux-gnu"
+    ;;
 s390x-unknown-linux-gnu)
     PYTHON_ARCH="s390x-linux-gnu"
     ;;
diff --git a/cpython-unix/build-libX11.sh b/cpython-unix/build-libX11.sh
index 019b2c07..6870514c 100755
--- a/cpython-unix/build-libX11.sh
+++ b/cpython-unix/build-libX11.sh
@@ -69,6 +69,9 @@ if [ -n "${CROSS_COMPILING}" ]; then
     ppc64le-unknown-linux-gnu)
       EXTRA_FLAGS="${EXTRA_FLAGS} --enable-malloc0returnsnull"
       ;;
+    riscv64-unknown-linux-gnu)
+      EXTRA_FLAGS="${EXTRA_FLAGS} --enable-malloc0returnsnull"
+      ;;
     s390x-unknown-linux-gnu)
       EXTRA_FLAGS="${EXTRA_FLAGS} --enable-malloc0returnsnull"
       ;;
diff --git a/cpython-unix/build-main.py b/cpython-unix/build-main.py
index a41e333b..dd4d2d7c 100755
--- a/cpython-unix/build-main.py
+++ b/cpython-unix/build-main.py
@@ -103,9 +103,11 @@ def main():
             "toolchain",
             "toolchain-image-build",
             "toolchain-image-build.cross",
+            "toolchain-image-build.cross-riscv64",
             "toolchain-image-gcc",
             "toolchain-image-xcb",
             "toolchain-image-xcb.cross",
+            "toolchain-image-xcb.cross-riscv64",
         },
         default="default",
         help="The make target to evaluate",
diff --git a/cpython-unix/build.cross-riscv64.Dockerfile b/cpython-unix/build.cross-riscv64.Dockerfile
new file mode 100644
index 00000000..740a098b
--- /dev/null
+++ b/cpython-unix/build.cross-riscv64.Dockerfile
@@ -0,0 +1,68 @@
+# Debian Buster.
+FROM debian@sha256:2a0c1b9175adf759420fe0fbd7f5b449038319171eb76554bb76cbe172b62b42
+MAINTAINER Gregory Szorc <gregory.szorc@gmail.com>
+
+RUN groupadd -g 1000 build && \
+    useradd -u 1000 -g 1000 -d /build -s /bin/bash -m build && \
+    mkdir /tools && \
+    chown -R build:build /build /tools
+
+ENV HOME=/build \
+    SHELL=/bin/bash \
+    USER=build \
+    LOGNAME=build \
+    HOSTNAME=builder \
+    DEBIAN_FRONTEND=noninteractive
+
+CMD ["/bin/bash", "--login"]
+WORKDIR '/build'
+
+RUN for s in debian_buster debian_buster-updates debian-security_buster/updates; do \
+      echo "deb http://snapshot.debian.org/archive/${s%_*}/20250109T084424Z/ ${s#*_} main"; \
+    done > /etc/apt/sources.list && \
+    ( echo 'quiet "true";'; \
+      echo 'APT::Get::Assume-Yes "true";'; \
+      echo 'APT::Install-Recommends "false";'; \
+      echo 'Acquire::Check-Valid-Until "false";'; \
+      echo 'Acquire::Retries "5";'; \
+    ) > /etc/apt/apt.conf.d/99cpython-portable
+
+RUN apt-get update
+
+# Host building.
+RUN apt-get install \
+    bzip2 \
+    gcc \
+    g++ \
+    libc6-dev \
+    libffi-dev \
+    make \
+    patch \
+    perl \
+    pkg-config \
+    tar \
+    xz-utils \
+    unzip \
+    zip \
+    zlib1g-dev
+
+# Cross-building.
+RUN apt-get install \
+    gcc-aarch64-linux-gnu \
+    gcc-arm-linux-gnueabi \
+    gcc-arm-linux-gnueabihf \
+    gcc-mips-linux-gnu \
+    gcc-mips64el-linux-gnuabi64 \
+    gcc-mipsel-linux-gnu \
+    gcc-powerpc64le-linux-gnu \
+    gcc-riscv64-linux-gnu \
+    gcc-s390x-linux-gnu \
+    libc6-dev-arm64-cross \
+    libc6-dev-armel-cross \
+    libc6-dev-armhf-cross \
+    libc6-dev-mips-cross \
+    libc6-dev-mips64el-cross \
+    libc6-dev-mipsel-cross \
+    libc6-dev-ppc64el-cross \
+    libc6-dev-riscv64-cross \
+    libc6-dev-s390x-cross
diff --git a/cpython-unix/build.py b/cpython-unix/build.py
index 8122dd9a..60935417 100755
--- a/cpython-unix/build.py
+++ b/cpython-unix/build.py
@@ -550,6 +550,13 @@ def python_build_info(
     if mips and version == "3.13":
         # See https://github.com/indygreg/python-build-standalone/issues/410
         linux_allowed_system_libraries.add("atomic")
+    riscv = target_triple.split("-")[0] in {"riscv64"}
+    if riscv:
+        # RISC-V binary often comes with libatomic on old GCC versions
+        # See https://github.com/riscvarchive/riscv-gcc/issues/12
+        # https://github.com/riscvarchive/riscv-gcc/issues/337
+        # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86005
+        linux_allowed_system_libraries.add("atomic")
 
     # Add in core linking annotations.
     libs = extra_metadata["python_config_vars"].get("LIBS", "").split()
diff --git a/cpython-unix/extension-modules.yml b/cpython-unix/extension-modules.yml
index 6a17cb87..1a195b04 100644
--- a/cpython-unix/extension-modules.yml
+++ b/cpython-unix/extension-modules.yml
@@ -259,6 +259,7 @@ _decimal:
       targets:
         - aarch64-.*
         - ppc64le-unknown-linux.*
+        - riscv64-unknown-linux.*
         - s390x-unknown-linux-.*
         - x86_64.*
   links:
diff --git a/cpython-unix/targets.yml b/cpython-unix/targets.yml
index 64683ec6..d3285891 100644
--- a/cpython-unix/targets.yml
+++ b/cpython-unix/targets.yml
@@ -470,6 +470,46 @@ ppc64le-unknown-linux-gnu:
     - zlib
   openssl_target: linux-ppc64le
 
+riscv64-unknown-linux-gnu:
+  host_platforms:
+    - linux64
+  pythons_supported:
+    - '3.9'
+    - '3.10'
+    - '3.11'
+    - '3.12'
+    - '3.13'
+    - '3.14'
+  docker_image_suffix: .cross-riscv64
+  host_cc: /usr/bin/x86_64-linux-gnu-gcc
+  host_cxx: /usr/bin/x86_64-linux-gnu-g++
+  target_cc: /usr/bin/riscv64-linux-gnu-gcc
+  needs:
+    - autoconf
+    - bdb
+    - binutils
+    - bzip2
+    - expat
+    - libedit
+    - libffi
+    - libX11
+    - libXau
+    - libxcb
+    - m4
+    - mpdecimal
+    - ncurses
+    - openssl-3.0
+    - patchelf
+    - sqlite
+    - tcl
+    - tk
+    - tix
+    - uuid
+    - xorgproto
+    - xz
+    - zlib
+  openssl_target: linux64-riscv64
+
 s390x-unknown-linux-gnu:
   host_platforms:
     - linux64
diff --git a/cpython-unix/xcb.cross-riscv64.Dockerfile b/cpython-unix/xcb.cross-riscv64.Dockerfile
new file mode 100644
index 00000000..260aa7d7
--- /dev/null
+++ b/cpython-unix/xcb.cross-riscv64.Dockerfile
@@ -0,0 +1,3 @@
+{% include 'build.cross-riscv64.Dockerfile' %}
+RUN apt-get install \
+    python
diff --git a/docs/building.rst b/docs/building.rst
index cadd0c49..dc91dea2 100644
--- a/docs/building.rst
+++ b/docs/building.rst
@@ -42,6 +42,7 @@ As are various other targets::
     $ ./build-linux.py --target mips-unknown-linux-gnu
     $ ./build-linux.py --target mipsel-unknown-linux-gnu
     $ ./build-linux.py --target ppc64le-unknown-linux-gnu
+    $ ./build-linux.py --target riscv64-unknown-linux-gnu
     $ ./build-linux.py --target s390x-unknown-linux-gnu
 
 macOS
diff --git a/src/release.rs b/src/release.rs
index e67a114f..62eb76bf 100644
--- a/src/release.rs
+++ b/src/release.rs
@@ -194,6 +194,19 @@ pub static RELEASE_TRIPLES: Lazy<BTreeMap<&'static str, TripleRelease>> = Lazy::
         },
     );
 
+    h.insert(
+        "riscv64-unknown-linux-gnu",
+        TripleRelease {
+            suffixes: linux_suffixes_nopgo.clone(),
+            install_only_suffix: "lto",
+            python_version_requirement: Some(VersionSpecifier::from_str(">=3.9").unwrap()),
+            conditional_suffixes: vec![ConditionalSuffixes {
+                python_version_requirement: VersionSpecifier::from_str(">=3.13").unwrap(),
+                suffixes: linux_suffixes_nopgo_freethreaded.clone(),
+            }],
+        },
+    );
+
     h.insert(
         "s390x-unknown-linux-gnu",
         TripleRelease {
diff --git a/src/validation.rs b/src/validation.rs
index fa57aec6..b8a27a06 100644
--- a/src/validation.rs
+++ b/src/validation.rs
@@ -45,6 +45,7 @@ const RECOGNIZED_TRIPLES: &[&str] = &[
     "mipsel-unknown-linux-gnu",
     "mips64el-unknown-linux-gnuabi64",
     "ppc64le-unknown-linux-gnu",
+    "riscv64-unknown-linux-gnu",
     "s390x-unknown-linux-gnu",
     "thumbv7k-apple-watchos",
     "x86_64-apple-darwin",
@@ -172,6 +173,10 @@ static GLIBC_MAX_VERSION_BY_TRIPLE: Lazy<HashMap<&'static str, version_compare::
             "ppc64le-unknown-linux-gnu",
             version_compare::Version::from("2.17").unwrap(),
         );
+        versions.insert(
+            "riscv64-unknown-linux-gnu",
+            version_compare::Version::from("2.28").unwrap(),
+        );
         versions.insert(
             "s390x-unknown-linux-gnu",
             version_compare::Version::from("2.17").unwrap(),
@@ -233,6 +238,7 @@ static ELF_ALLOWED_LIBRARIES_BY_TRIPLE: Lazy<HashMap<&'static str, Vec<&'static
             ),
             ("mips64el-unknown-linux-gnuabi64", vec![]),
             ("ppc64le-unknown-linux-gnu", vec!["ld64.so.1", "ld64.so.2"]),
+            ("riscv64-unknown-linux-gnu", vec!["ld-linux-riscv64-lp64d.so.1", "libatomic.so.1"]),
             ("s390x-unknown-linux-gnu", vec!["ld64.so.1"]),
             ("x86_64-unknown-linux-gnu", vec!["ld-linux-x86-64.so.2"]),
             ("x86_64_v2-unknown-linux-gnu", vec!["ld-linux-x86-64.so.2"]),
@@ -488,6 +494,7 @@ static PLATFORM_TAG_BY_TRIPLE: Lazy<HashMap<&'static str, &'static str>> = Lazy:
         ("mipsel-unknown-linux-gnu", "linux-mipsel"),
         ("mips64el-unknown-linux-gnuabi64", "todo"),
         ("ppc64le-unknown-linux-gnu", "linux-powerpc64le"),
+        ("riscv64-unknown-linux-gnu", "linux-riscv64"),
         ("s390x-unknown-linux-gnu", "linux-s390x"),
         ("x86_64-apple-darwin", "macosx-10.15-x86_64"),
         ("x86_64-apple-ios", "iOS-x86_64"),
@@ -866,6 +873,7 @@ fn validate_elf<Elf: FileHeader<Endian = Endianness>>(
         "mipsel-unknown-linux-gnu" => object::elf::EM_MIPS,
         "mips64el-unknown-linux-gnuabi64" => 0,
         "ppc64le-unknown-linux-gnu" => object::elf::EM_PPC64,
+        "riscv64-unknown-linux-gnu" => object::elf::EM_RISCV,
         "s390x-unknown-linux-gnu" => object::elf::EM_S390,
         "x86_64-unknown-linux-gnu" => object::elf::EM_X86_64,
         "x86_64_v2-unknown-linux-gnu" => object::elf::EM_X86_64,

From 2d8972d70c4ac7ce125d01387961924fcb395985 Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Tue, 14 Jan 2025 11:40:45 -0600
Subject: [PATCH 028/157] Update CPython 3.14a3 -> 3.14a4 (#493)

---
 cpython-unix/build-cpython.sh                 | 14 ++++++++----
 ...atch-configure-bolt-apply-flags-3.14.patch | 22 +++++++++++++++++++
 pythonbuild/downloads.py                      |  8 +++----
 3 files changed, 36 insertions(+), 8 deletions(-)
 create mode 100644 cpython-unix/patch-configure-bolt-apply-flags-3.14.patch

diff --git a/cpython-unix/build-cpython.sh b/cpython-unix/build-cpython.sh
index edf68527..e7ed8cb1 100755
--- a/cpython-unix/build-cpython.sh
+++ b/cpython-unix/build-cpython.sh
@@ -284,11 +284,17 @@ if [ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_11}" ]; then
 fi
 
 if [ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_12}" ]; then
-    # Adjust BOLT flags to yield better behavior. See inline details in patch.
-    patch -p1 -i ${ROOT}/patch-configure-bolt-flags.patch
+    # On 3.14+, we upstreamed these changes and they are no longer needed
+    if [ -n "${PYTHON_MEETS_MAXIMUM_VERSION_3_13}" ]; then
+        # Adjust BOLT flags to yield better behavior. See inline details in patch.
+        patch -p1 -i ${ROOT}/patch-configure-bolt-flags.patch
 
-    # Adjust BOLT application flags to make use of modern LLVM features.
-    patch -p1 -i ${ROOT}/patch-configure-bolt-apply-flags.patch
+        # Adjust BOLT application flags to make use of modern LLVM features.
+        patch -p1 -i ${ROOT}/patch-configure-bolt-apply-flags.patch
+    else
+        # We are still upstreaming some additional optimization flags
+        patch -p1 -i ${ROOT}/patch-configure-bolt-apply-flags-3.14.patch
+    fi
 fi
 
 # The optimization make targets are both phony and non-phony. This leads
diff --git a/cpython-unix/patch-configure-bolt-apply-flags-3.14.patch b/cpython-unix/patch-configure-bolt-apply-flags-3.14.patch
new file mode 100644
index 00000000..e810a482
--- /dev/null
+++ b/cpython-unix/patch-configure-bolt-apply-flags-3.14.patch
@@ -0,0 +1,22 @@
+diff --git a/configure.ac b/configure.ac
+index ee034e5a962..f1a69b7d4a7 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -2183,8 +2183,9 @@ then
+     [m4_normalize("
+      -update-debug-sections
+      -reorder-blocks=ext-tsp
+      -reorder-functions=cdsort
+      -split-functions
++     -split-strategy=cdsplit
+      -icf=1
+      -inline-all
+      -split-eh
+@@ -2196,6 +2197,7 @@ then
+      -dyno-stats
+      -use-gnu-stack
+      -frame-opt=hot
++     -hugify
+    ")]
+   )
+ fi
diff --git a/pythonbuild/downloads.py b/pythonbuild/downloads.py
index e3e1a1ba..983efa04 100644
--- a/pythonbuild/downloads.py
+++ b/pythonbuild/downloads.py
@@ -80,10 +80,10 @@
         "python_tag": "cp313",
     },
     "cpython-3.14": {
-        "url": "https://www.python.org/ftp/python/3.14.0/Python-3.14.0a3.tar.xz",
-        "size": 22749680,
-        "sha256": "94349df207456a575a8867c20b4ca434f870e1920dcdcc8fdf797e1af49abe90",
-        "version": "3.14.0a3",
+        "url": "https://www.python.org/ftp/python/3.14.0/Python-3.14.0a4.tar.xz",
+        "size": 22798932,
+        "sha256": "c24f07881873c1d460228795ca6ca8c99130e30c773c91463d30d7ea8ff0e70b",
+        "version": "3.14.0a4",
         "licenses": ["Python-2.0", "CNRI-Python"],
         "license_file": "LICENSE.cpython.txt",
         "python_tag": "cp314",

From 6a1b95d01397b8284132944b9ec025cf2b6bd56b Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Tue, 14 Jan 2025 13:34:44 -0600
Subject: [PATCH 029/157] Retry downloads when <75% of the file is downloaded
 (#496)

Closes https://github.com/astral-sh/python-build-standalone/issues/489
(hopefully)
---
 pythonbuild/utils.py | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/pythonbuild/utils.py b/pythonbuild/utils.py
index 7d30b2df..13bea0df 100644
--- a/pythonbuild/utils.py
+++ b/pythonbuild/utils.py
@@ -214,6 +214,10 @@ def write_target_settings(targets, dest_path: pathlib.Path):
 class IntegrityError(Exception):
     """Represents an integrity error when downloading a URL."""
 
+    def __init__(self, *args, length: int):
+        self.length = length
+        super().__init__(*args)
+
 
 def secure_download_stream(url, size, sha256):
     """Securely download a URL to a stream of chunks.
@@ -291,9 +295,13 @@ def download_to_path(url: str, path: pathlib.Path, size: int, sha256: str):
                         fh.write(chunk)
 
                 break
-            except IntegrityError:
+            except IntegrityError as e:
                 tmp.unlink()
-                raise
+                # If we didn't get most of the expected file, retry
+                if e.length > size * 0.75:
+                    raise
+                print(f"Integrity error on {url}; retrying: {e}")
+                time.sleep(2**attempt)
         except http.client.HTTPException as e:
             print(f"HTTP exception on {url}; retrying: {e}")
             time.sleep(2**attempt)

From 6f3ab9844d0791cfbbf6caf28bdf60b2812b4c10 Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Tue, 14 Jan 2025 13:50:37 -0600
Subject: [PATCH 030/157] Upgrade tcl/tk from 8.6.12 to 8.6.14 on Unix (#495)

Rebase of #313 to only apply to Unix. We'll handle Windows separately in
#494.

---------

Co-authored-by: Gregory Szorc <gregory.szorc@gmail.com>
---
 cpython-unix/build-cpython.sh      |  4 ++--
 cpython-unix/build.py              |  2 +-
 cpython-unix/extension-modules.yml |  1 +
 cpython-windows/build.py           |  6 ++---
 pythonbuild/downloads.py           | 35 +++++++++++++++++++++++++-----
 src/validation.rs                  | 10 ++++++++-
 6 files changed, 46 insertions(+), 12 deletions(-)

diff --git a/cpython-unix/build-cpython.sh b/cpython-unix/build-cpython.sh
index e7ed8cb1..a04677f1 100755
--- a/cpython-unix/build-cpython.sh
+++ b/cpython-unix/build-cpython.sh
@@ -473,7 +473,7 @@ if [ "${PYBUILD_PLATFORM}" = "macos" ]; then
     # symbol.
     if [ -n "${PYTHON_MEETS_MAXIMUM_VERSION_3_9}" ]; then
         if [ "${TARGET_TRIPLE}" != "aarch64-apple-darwin" ]; then
-            for symbol in clock_getres clock_gettime clock_settime faccessat fchmodat fchownat fdopendir fstatat futimens getentropy linkat mkdirat openat preadv pwritev readlinkat renameat symlinkat unlinkat utimensat; do
+            for symbol in clock_getres clock_gettime clock_settime faccessat fchmodat fchownat fdopendir fstatat futimens getentropy linkat mkdirat openat preadv pwritev readlinkat renameat symlinkat unlinkat utimensat uttype; do
                 CONFIGURE_FLAGS="${CONFIGURE_FLAGS} ac_cv_func_${symbol}=no"
             done
         fi
@@ -1083,7 +1083,7 @@ if [ -d "${TOOLS_PATH}/deps/lib/tcl8" ]; then
     # Copy tcl/tk/tix resources needed by tkinter.
     mkdir ${ROOT}/out/python/install/lib/tcl
     # Keep this list in sync with tcl_library_paths.
-    for source in ${TOOLS_PATH}/deps/lib/{itcl4.2.2,tcl8,tcl8.6,thread2.8.7,tk8.6}; do
+    for source in ${TOOLS_PATH}/deps/lib/{itcl4.2.4,tcl8,tcl8.6,thread2.8.9,tk8.6}; do
         cp -av $source ${ROOT}/out/python/install/lib/
     done
 
diff --git a/cpython-unix/build.py b/cpython-unix/build.py
index 60935417..5d4b5c9d 100755
--- a/cpython-unix/build.py
+++ b/cpython-unix/build.py
@@ -893,7 +893,7 @@ def build_cpython(
 
         python_info["tcl_library_path"] = "install/lib"
         python_info["tcl_library_paths"] = [
-            "itcl4.2.2",
+            "itcl4.2.4",
             "tcl8",
             "tcl8.6",
             "thread2.8.7",
diff --git a/cpython-unix/extension-modules.yml b/cpython-unix/extension-modules.yml
index 1a195b04..968f8d81 100644
--- a/cpython-unix/extension-modules.yml
+++ b/cpython-unix/extension-modules.yml
@@ -689,6 +689,7 @@ _tkinter:
     - CoreGraphics
     - IOKit
     - QuartzCore
+    - UniformTypeIdentifiers
 
 _tokenize:
   minimum-python-version: "3.11"
diff --git a/cpython-windows/build.py b/cpython-windows/build.py
index e410bf47..4f833a4a 100644
--- a/cpython-windows/build.py
+++ b/cpython-windows/build.py
@@ -114,7 +114,7 @@
     "_lzma": ["xz"],
     "_sqlite3": ["sqlite"],
     "_ssl": ["openssl"],
-    "_tkinter": ["tcl", "tk", "tix"],
+    "_tkinter": ["tcl-8612", "tk-8612", "tix"],
     "_uuid": ["uuid"],
     "zlib": ["zlib"],
 }
@@ -355,7 +355,7 @@ def hack_props(
     sqlite_version = DOWNLOADS["sqlite"]["version"]
     xz_version = DOWNLOADS["xz"]["version"]
     zlib_version = DOWNLOADS["zlib"]["version"]
-    tcltk_commit = DOWNLOADS["tk-windows-bin"]["git_commit"]
+    tcltk_commit = DOWNLOADS["tk-windows-bin-8612"]["git_commit"]
     mpdecimal_version = DOWNLOADS["mpdecimal"]["version"]
 
     sqlite_path = td / ("sqlite-autoconf-%s" % sqlite_version)
@@ -1197,7 +1197,7 @@ def build_cpython(
     bzip2_archive = download_entry("bzip2", BUILD)
     sqlite_archive = download_entry("sqlite", BUILD)
     tk_bin_archive = download_entry(
-        "tk-windows-bin", BUILD, local_name="tk-windows-bin.tar.gz"
+        "tk-windows-bin-8612", BUILD, local_name="tk-windows-bin.tar.gz"
     )
     xz_archive = download_entry("xz", BUILD)
     zlib_archive = download_entry("zlib", BUILD)
diff --git a/pythonbuild/downloads.py b/pythonbuild/downloads.py
index 983efa04..401bd171 100644
--- a/pythonbuild/downloads.py
+++ b/pythonbuild/downloads.py
@@ -309,10 +309,10 @@
         "version": "5.38.2.2",
     },
     "tcl": {
-        "url": "https://prdownloads.sourceforge.net/tcl/tcl8.6.12-src.tar.gz",
-        "size": 10353486,
-        "sha256": "26c995dd0f167e48b11961d891ee555f680c175f7173ff8cb829f4ebcde4c1a6",
-        "version": "8.6.12",
+        "url": "https://prdownloads.sourceforge.net/tcl/tcl8.6.14-src.tar.gz",
+        "size": 11627322,
+        "sha256": "5880225babf7954c58d4fb0f5cf6279104ce1cd6aa9b71e9a6322540e1c4de66",
+        "version": "8.6.14",
         "library_names": ["tcl8.6"],
         "licenses": ["TCL"],
         "license_file": "LICENSE.tcl.txt",
@@ -326,6 +326,31 @@
         "license_file": "LICENSE.tix.txt",
     },
     "tk": {
+        "url": "https://prdownloads.sourceforge.net/tcl/tk8.6.14-src.tar.gz",
+        "size": 4510695,
+        "sha256": "8ffdb720f47a6ca6107eac2dd877e30b0ef7fac14f3a84ebbd0b3612cee41a94",
+        "version": "8.6.14",
+        "library_names": ["tk8.6"],
+        "licenses": ["TCL"],
+        "license_file": "LICENSE.tcl.txt",
+    },
+    "tk-windows-bin": {
+        "url": "https://github.com/python/cpython-bin-deps/archive/c624cc881bd0e5071dec9de4b120cbe9985d8c14.tar.gz",
+        "size": 9497943,
+        "sha256": "9b8e77d55f40ceaedd140ccca0daa804f0d43346d5abfcead9b547b5590f82f8",
+        "version": "8.6.14",
+        "git_commit": "c624cc881bd0e5071dec9de4b120cbe9985d8c14",
+    },
+    "tcl-8612": {
+        "url": "https://prdownloads.sourceforge.net/tcl/tcl8.6.12-src.tar.gz",
+        "size": 10353486,
+        "sha256": "26c995dd0f167e48b11961d891ee555f680c175f7173ff8cb829f4ebcde4c1a6",
+        "version": "8.6.12",
+        "library_names": ["tcl8.6"],
+        "licenses": ["TCL"],
+        "license_file": "LICENSE.tcl.txt",
+    },
+    "tk-8612": {
         "url": "https://prdownloads.sourceforge.net/tcl/tk8.6.12-src.tar.gz",
         "size": 4515393,
         "sha256": "12395c1f3fcb6bed2938689f797ea3cdf41ed5cb6c4766eec8ac949560310630",
@@ -334,7 +359,7 @@
         "licenses": ["TCL"],
         "license_file": "LICENSE.tcl.txt",
     },
-    "tk-windows-bin": {
+    "tk-windows-bin-8612": {
         "url": "https://github.com/python/cpython-bin-deps/archive/e3c3e9a2856124aa32b608632a52742d479eb7a9.tar.gz",
         "size": 6787654,
         "sha256": "01ad9c663659224e075d487cbc33ea2fed7a225593965b79bed92ca7f79b676f",
diff --git a/src/validation.rs b/src/validation.rs
index b8a27a06..fa19b4d3 100644
--- a/src/validation.rs
+++ b/src/validation.rs
@@ -238,7 +238,10 @@ static ELF_ALLOWED_LIBRARIES_BY_TRIPLE: Lazy<HashMap<&'static str, Vec<&'static
             ),
             ("mips64el-unknown-linux-gnuabi64", vec![]),
             ("ppc64le-unknown-linux-gnu", vec!["ld64.so.1", "ld64.so.2"]),
-            ("riscv64-unknown-linux-gnu", vec!["ld-linux-riscv64-lp64d.so.1", "libatomic.so.1"]),
+            (
+                "riscv64-unknown-linux-gnu",
+                vec!["ld-linux-riscv64-lp64d.so.1", "libatomic.so.1"],
+            ),
             ("s390x-unknown-linux-gnu", vec!["ld64.so.1"]),
             ("x86_64-unknown-linux-gnu", vec!["ld-linux-x86-64.so.2"]),
             ("x86_64_v2-unknown-linux-gnu", vec!["ld-linux-x86-64.so.2"]),
@@ -394,6 +397,11 @@ static DARWIN_ALLOWED_DYLIBS: Lazy<Vec<MachOAllowedDylib>> = Lazy::new(|| {
                 max_compatibility_version: "1.0.0".try_into().unwrap(),
                 required: true,
             },
+            MachOAllowedDylib {
+                name: "/System/Library/Frameworks/UniformTypeIdentifiers.framework/Versions/A/UniformTypeIdentifiers".to_string(),
+                max_compatibility_version: "1.0.0".try_into().unwrap(),
+                required: true,
+            },
             MachOAllowedDylib {
                 name: "/usr/lib/libedit.3.dylib".to_string(),
                 max_compatibility_version: "2.0.0".try_into().unwrap(),

From 658bff82414f9499972564554892ba61184faecb Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Tue, 14 Jan 2025 16:12:29 -0600
Subject: [PATCH 031/157] Add Python 3.14 support on Windows (#494)

The upstream build system now requires the latest tcl/tk and we want to
upgrade anyway, so that happens here as well. There are some concerns
about the new zlib/msvcrt dependencies, so I'm limiting these to the
3.14a to see how it goes.

See #495
---
 ci-targets.yaml          |  2 ++
 cpython-windows/build.py | 38 +++++++++++++++++++++++++++++++-------
 src/validation.rs        | 26 ++++++++++++++++++++++++--
 3 files changed, 57 insertions(+), 9 deletions(-)

diff --git a/ci-targets.yaml b/ci-targets.yaml
index 0ecc662d..ec08bd9a 100644
--- a/ci-targets.yaml
+++ b/ci-targets.yaml
@@ -320,6 +320,7 @@ windows:
       - "3.11"
       - "3.12"
       - "3.13"
+      - "3.14"
     build_options:
       - pgo
     build_options_conditional:
@@ -336,6 +337,7 @@ windows:
       - "3.11"
       - "3.12"
       - "3.13"
+      - "3.14"
     build_options:
       - pgo
     build_options_conditional:
diff --git a/cpython-windows/build.py b/cpython-windows/build.py
index 4f833a4a..638a2c78 100644
--- a/cpython-windows/build.py
+++ b/cpython-windows/build.py
@@ -345,6 +345,7 @@ def hack_props(
     td: pathlib.Path,
     pcbuild_path: pathlib.Path,
     arch: str,
+    python_version: str,
 ):
     # TODO can we pass props into msbuild.exe?
 
@@ -355,9 +356,14 @@ def hack_props(
     sqlite_version = DOWNLOADS["sqlite"]["version"]
     xz_version = DOWNLOADS["xz"]["version"]
     zlib_version = DOWNLOADS["zlib"]["version"]
-    tcltk_commit = DOWNLOADS["tk-windows-bin-8612"]["git_commit"]
+
     mpdecimal_version = DOWNLOADS["mpdecimal"]["version"]
 
+    if meets_python_minimum_version(python_version, "3.14"):
+        tcltk_commit = DOWNLOADS["tk-windows-bin"]["git_commit"]
+    else:
+        tcltk_commit = DOWNLOADS["tk-windows-bin-8612"]["git_commit"]
+
     sqlite_path = td / ("sqlite-autoconf-%s" % sqlite_version)
     bzip2_path = td / ("bzip2-%s" % bzip2_version)
     libffi_path = td / "libffi"
@@ -487,6 +493,7 @@ def hack_project_files(
         td,
         pcbuild_path,
         build_directory,
+        python_version,
     )
 
     # Our SQLite directory is named weirdly. This throws off version detection
@@ -566,9 +573,13 @@ def hack_project_files(
         rb'<ClCompile Include="$(opensslIncludeDir)\openssl\applink.c">',
     )
 
-    # We're still on the pre-built tk-windows-bin 8.6.12 which doesn't have a
-    # standalone zlib DLL. So remove references to it from 3.12+.
-    if meets_python_minimum_version(python_version, "3.12"):
+    # Python 3.12+ uses the the pre-built tk-windows-bin 8.6.12 which doesn't
+    # have a standalone zlib DLL, so we remove references to it. For Python
+    # 3.14+, we're using tk-windows-bin 8.6.14 which includes a prebuilt zlib
+    # DLL, so we skip this patch there.
+    if meets_python_minimum_version(
+        python_version, "3.12"
+    ) and meets_python_maximum_version(python_version, "3.13"):
         static_replace_in_file(
             pcbuild_path / "_tkinter.vcxproj",
             rb'<_TclTkDLL Include="$(tcltkdir)\bin\$(tclZlibDllName)" />',
@@ -1127,6 +1138,10 @@ def find_additional_dependencies(project: pathlib.Path):
                 if name == "openssl":
                     name = openssl_entry
 
+                # On 3.14+, we use the latest tcl/tk version
+                if ext == "_tkinter" and python_majmin == "314":
+                    name = name.replace("-8612", "")
+
                 download_entry = DOWNLOADS[name]
 
                 # This will raise if no license metadata defined. This is
@@ -1196,9 +1211,6 @@ def build_cpython(
 
     bzip2_archive = download_entry("bzip2", BUILD)
     sqlite_archive = download_entry("sqlite", BUILD)
-    tk_bin_archive = download_entry(
-        "tk-windows-bin-8612", BUILD, local_name="tk-windows-bin.tar.gz"
-    )
     xz_archive = download_entry("xz", BUILD)
     zlib_archive = download_entry("zlib", BUILD)
 
@@ -1210,6 +1222,17 @@ def build_cpython(
     setuptools_wheel = download_entry("setuptools", BUILD)
     pip_wheel = download_entry("pip", BUILD)
 
+    # On CPython 3.14+, we use the latest tcl/tk version which has additional runtime
+    # dependencies, so we are conservative and use the old version elsewhere.
+    if meets_python_minimum_version(python_version, "3.14"):
+        tk_bin_archive = download_entry(
+            "tk-windows-bin", BUILD, local_name="tk-windows-bin.tar.gz"
+        )
+    else:
+        tk_bin_archive = download_entry(
+            "tk-windows-bin-8612", BUILD, local_name="tk-windows-bin.tar.gz"
+        )
+
     # CPython 3.13+ no longer uses a bundled `mpdecimal` version so we build it
     if meets_python_minimum_version(python_version, "3.13"):
         mpdecimal_archive = download_entry("mpdecimal", BUILD)
@@ -1690,6 +1713,7 @@ def main() -> None:
             "cpython-3.11",
             "cpython-3.12",
             "cpython-3.13",
+            "cpython-3.14",
         },
         default="cpython-3.11",
         help="Python distribution to build",
diff --git a/src/validation.rs b/src/validation.rs
index fa19b4d3..1beea181 100644
--- a/src/validation.rs
+++ b/src/validation.rs
@@ -137,6 +137,9 @@ const PE_ALLOWED_LIBRARIES: &[&str] = &[
     "tk86t.dll",
 ];
 
+// CPython 3.14 uses tcl/tk 8.6.14+ which includes a bundled zlib and dynamically links to msvcrt.
+const PE_ALLOWED_LIBRARIES_314: &[&str] = &["msvcrt.dll", "zlib1.dll"];
+
 static GLIBC_MAX_VERSION_BY_TRIPLE: Lazy<HashMap<&'static str, version_compare::Version<'static>>> =
     Lazy::new(|| {
         let mut versions = HashMap::new();
@@ -795,6 +798,8 @@ const GLOBAL_EXTENSIONS_WINDOWS: &[&str] = &[
     "winsound",
 ];
 
+const GLOBAL_EXTENSIONS_WINDOWS_3_14: &[&str] = &["_wmi"];
+
 const GLOBAL_EXTENSIONS_WINDOWS_PRE_3_13: &[&str] = &["_msi"];
 
 /// Extension modules not present in Windows static builds.
@@ -1331,6 +1336,7 @@ fn validate_macho<Mach: MachHeader<Endian = Endianness>>(
 
 fn validate_pe<'data, Pe: ImageNtHeaders>(
     context: &mut ValidationContext,
+    python_major_minor: &str,
     path: &Path,
     pe: &PeFile<'data, Pe, &'data [u8]>,
 ) -> Result<()> {
@@ -1346,6 +1352,18 @@ fn validate_pe<'data, Pe: ImageNtHeaders>(
             let lib = import_table.name(descriptor.name.get(object::LittleEndian))?;
             let lib = String::from_utf8(lib.to_vec())?;
 
+            match python_major_minor {
+                "3.9" | "3.10" | "3.11" | "3.12" | "3.13" => {}
+                "3.14" => {
+                    if PE_ALLOWED_LIBRARIES_314.contains(&lib.as_str()) {
+                        continue;
+                    }
+                }
+                _ => {
+                    panic!("unhandled Python version: {}", python_major_minor);
+                }
+            }
+
             if !PE_ALLOWED_LIBRARIES.contains(&lib.as_str()) {
                 context
                     .errors
@@ -1451,11 +1469,11 @@ fn validate_possible_object_file(
             }
             FileKind::Pe32 => {
                 let file = PeFile32::parse(data)?;
-                validate_pe(&mut context, path, &file)?;
+                validate_pe(&mut context, python_major_minor, path, &file)?;
             }
             FileKind::Pe64 => {
                 let file = PeFile64::parse(data)?;
-                validate_pe(&mut context, path, &file)?;
+                validate_pe(&mut context, python_major_minor, path, &file)?;
             }
             _ => {}
         }
@@ -1526,6 +1544,10 @@ fn validate_extension_modules(
             wanted.extend(GLOBAL_EXTENSIONS_WINDOWS_PRE_3_13);
         }
 
+        if matches!(python_major_minor, "3.14") {
+            wanted.extend(GLOBAL_EXTENSIONS_WINDOWS_3_14);
+        }
+
         if static_crt {
             for x in GLOBAL_EXTENSIONS_WINDOWS_NO_STATIC {
                 wanted.remove(*x);

From 9023b79082f045fa9cf6fba7f07da0d7718e0041 Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Tue, 14 Jan 2025 16:22:17 -0600
Subject: [PATCH 032/157] Add Python 3.14 to Windows release targets (#497)

This reverts commit 3a8ea4a9b34474aa31343311ae2b95288208cc39.
---
 src/release.rs | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/src/release.rs b/src/release.rs
index 62eb76bf..f0c70f62 100644
--- a/src/release.rs
+++ b/src/release.rs
@@ -105,13 +105,12 @@ pub static RELEASE_TRIPLES: Lazy<BTreeMap<&'static str, TripleRelease>> = Lazy::
     );
 
     // Windows.
-    // TODO: Python 3.14 support on Windows
     h.insert(
         "i686-pc-windows-msvc",
         TripleRelease {
             suffixes: vec!["pgo"],
             install_only_suffix: "pgo",
-            python_version_requirement: Some(VersionSpecifier::from_str("<3.14").unwrap()),
+            python_version_requirement: None,
             conditional_suffixes: vec![ConditionalSuffixes {
                 python_version_requirement: VersionSpecifier::from_str(">=3.13").unwrap(),
                 suffixes: vec!["freethreaded+pgo"],
@@ -123,7 +122,7 @@ pub static RELEASE_TRIPLES: Lazy<BTreeMap<&'static str, TripleRelease>> = Lazy::
         TripleRelease {
             suffixes: vec!["pgo"],
             install_only_suffix: "pgo",
-            python_version_requirement: Some(VersionSpecifier::from_str("<3.14").unwrap()),
+            python_version_requirement: None,
             conditional_suffixes: vec![ConditionalSuffixes {
                 python_version_requirement: VersionSpecifier::from_str(">=3.13").unwrap(),
                 suffixes: vec!["freethreaded+pgo"],
@@ -138,7 +137,7 @@ pub static RELEASE_TRIPLES: Lazy<BTreeMap<&'static str, TripleRelease>> = Lazy::
         TripleRelease {
             suffixes: vec!["pgo"],
             install_only_suffix: "pgo",
-            python_version_requirement: Some(VersionSpecifier::from_str("<3.14").unwrap()),
+            python_version_requirement: None,
             conditional_suffixes: vec![ConditionalSuffixes {
                 python_version_requirement: VersionSpecifier::from_str(">=3.13").unwrap(),
                 suffixes: vec!["freethreaded+pgo"],
@@ -150,7 +149,7 @@ pub static RELEASE_TRIPLES: Lazy<BTreeMap<&'static str, TripleRelease>> = Lazy::
         TripleRelease {
             suffixes: vec!["pgo"],
             install_only_suffix: "pgo",
-            python_version_requirement: Some(VersionSpecifier::from_str("<3.14").unwrap()),
+            python_version_requirement: None,
             conditional_suffixes: vec![ConditionalSuffixes {
                 python_version_requirement: VersionSpecifier::from_str(">=3.13").unwrap(),
                 suffixes: vec!["freethreaded+pgo"],

From 722eb604c197179c715b2498a59f037506eebba3 Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Tue, 14 Jan 2025 16:22:24 -0600
Subject: [PATCH 033/157] Fix attestation permissions for sharded linux builds
 (#498)

---
 .github/workflows/linux.yml | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml
index 26b97f23..5941c85f 100644
--- a/.github/workflows/linux.yml
+++ b/.github/workflows/linux.yml
@@ -257,6 +257,10 @@ jobs:
       - generate-matrix
       - pythonbuild
       - image
+    # Permissions used for actions/attest-build-provenance
+    permissions:
+      id-token: write
+      attestations: write
     runs-on: ${{ matrix.runner }}
     strategy:
       matrix: ${{ fromJson(needs.generate-matrix.outputs.matrix-1) }}

From fc29abe434cdbf48426bc1c1270232b898f2f5f2 Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Wed, 15 Jan 2025 11:43:10 -0600
Subject: [PATCH 034/157] Upgrade `reqwest` to 0.12 (#500)

Fixes artifact upload failures introduced by conflicting versions in
#486
---
 Cargo.lock    | 554 ++++++++++++++++++++++++++++----------------------
 Cargo.toml    |   2 +-
 src/github.rs |   6 +-
 3 files changed, 314 insertions(+), 248 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 425d307b..70bd4f01 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -125,6 +125,12 @@ dependencies = [
  "syn 2.0.95",
 ]
 
+[[package]]
+name = "atomic-waker"
+version = "1.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0"
+
 [[package]]
 name = "autocfg"
 version = "1.1.0"
@@ -199,9 +205,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
 
 [[package]]
 name = "bytes"
-version = "1.5.0"
+version = "1.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223"
+checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b"
 
 [[package]]
 name = "bzip2"
@@ -239,6 +245,12 @@ version = "1.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
 
+[[package]]
+name = "cfg_aliases"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
+
 [[package]]
 name = "chrono"
 version = "0.4.34"
@@ -249,7 +261,7 @@ dependencies = [
  "iana-time-zone",
  "num-traits",
  "serde",
- "windows-targets 0.52.3",
+ "windows-targets 0.52.6",
 ]
 
 [[package]]
@@ -645,16 +657,16 @@ dependencies = [
 
 [[package]]
 name = "h2"
-version = "0.3.26"
+version = "0.4.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8"
+checksum = "ccae279728d634d083c00f6099cb58f01cc99c145b84b8be2f6c74618d79922e"
 dependencies = [
+ "atomic-waker",
  "bytes",
  "fnv",
  "futures-core",
  "futures-sink",
- "futures-util",
- "http 0.2.11",
+ "http",
  "indexmap",
  "slab",
  "tokio",
@@ -689,17 +701,6 @@ dependencies = [
  "digest",
 ]
 
-[[package]]
-name = "http"
-version = "0.2.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb"
-dependencies = [
- "bytes",
- "fnv",
- "itoa",
-]
-
 [[package]]
 name = "http"
 version = "1.0.0"
@@ -711,17 +712,6 @@ dependencies = [
  "itoa",
 ]
 
-[[package]]
-name = "http-body"
-version = "0.4.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2"
-dependencies = [
- "bytes",
- "http 0.2.11",
- "pin-project-lite",
-]
-
 [[package]]
 name = "http-body"
 version = "1.0.0"
@@ -729,7 +719,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643"
 dependencies = [
  "bytes",
- "http 1.0.0",
+ "http",
 ]
 
 [[package]]
@@ -740,8 +730,8 @@ checksum = "41cb79eb393015dadd30fc252023adb0b2400a0caee0fa2a077e6e21a551e840"
 dependencies = [
  "bytes",
  "futures-util",
- "http 1.0.0",
- "http-body 1.0.0",
+ "http",
+ "http-body",
  "pin-project-lite",
 ]
 
@@ -751,72 +741,61 @@ version = "1.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904"
 
-[[package]]
-name = "httpdate"
-version = "1.0.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
-
 [[package]]
 name = "hyper"
-version = "0.14.28"
+version = "1.5.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80"
+checksum = "256fb8d4bd6413123cc9d91832d78325c48ff41677595be797d90f42969beae0"
 dependencies = [
  "bytes",
  "futures-channel",
- "futures-core",
  "futures-util",
  "h2",
- "http 0.2.11",
- "http-body 0.4.6",
+ "http",
+ "http-body",
  "httparse",
- "httpdate",
  "itoa",
  "pin-project-lite",
- "socket2",
+ "smallvec",
  "tokio",
- "tower-service",
- "tracing",
  "want",
 ]
 
 [[package]]
-name = "hyper"
-version = "1.2.0"
+name = "hyper-rustls"
+version = "0.26.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "186548d73ac615b32a73aafe38fb4f56c0d340e110e5a200bcadbaf2e199263a"
+checksum = "a0bea761b46ae2b24eb4aef630d8d1c398157b6fc29e6350ecf090a0b70c952c"
 dependencies = [
- "bytes",
- "futures-channel",
  "futures-util",
- "http 1.0.0",
- "http-body 1.0.0",
- "httparse",
- "itoa",
- "pin-project-lite",
- "smallvec",
+ "http",
+ "hyper",
+ "hyper-util",
+ "log",
+ "rustls 0.22.2",
+ "rustls-native-certs",
+ "rustls-pki-types",
  "tokio",
- "want",
+ "tokio-rustls 0.25.0",
+ "tower-service",
 ]
 
 [[package]]
 name = "hyper-rustls"
-version = "0.26.0"
+version = "0.27.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a0bea761b46ae2b24eb4aef630d8d1c398157b6fc29e6350ecf090a0b70c952c"
+checksum = "2d191583f3da1305256f22463b9bb0471acad48a4e534a5218b9963e9c1f59b2"
 dependencies = [
  "futures-util",
- "http 1.0.0",
- "hyper 1.2.0",
+ "http",
+ "hyper",
  "hyper-util",
- "log",
- "rustls 0.22.2",
- "rustls-native-certs",
+ "rustls 0.23.21",
  "rustls-pki-types",
  "tokio",
- "tokio-rustls",
+ "tokio-rustls 0.26.1",
  "tower-service",
+ "webpki-roots",
 ]
 
 [[package]]
@@ -825,7 +804,7 @@ version = "0.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3203a961e5c83b6f5498933e78b6b263e208c197b63e9c6c53cc82ffd3f63793"
 dependencies = [
- "hyper 1.2.0",
+ "hyper",
  "hyper-util",
  "pin-project-lite",
  "tokio",
@@ -834,33 +813,35 @@ dependencies = [
 
 [[package]]
 name = "hyper-tls"
-version = "0.5.0"
+version = "0.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905"
+checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0"
 dependencies = [
  "bytes",
- "hyper 0.14.28",
+ "http-body-util",
+ "hyper",
+ "hyper-util",
  "native-tls",
  "tokio",
  "tokio-native-tls",
+ "tower-service",
 ]
 
 [[package]]
 name = "hyper-util"
-version = "0.1.3"
+version = "0.1.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ca38ef113da30126bbff9cd1705f9273e15d45498615d138b0c20279ac7a76aa"
+checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4"
 dependencies = [
  "bytes",
  "futures-channel",
  "futures-util",
- "http 1.0.0",
- "http-body 1.0.0",
- "hyper 1.2.0",
+ "http",
+ "http-body",
+ "hyper",
  "pin-project-lite",
  "socket2",
  "tokio",
- "tower",
  "tower-service",
  "tracing",
 ]
@@ -983,9 +964,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
 
 [[package]]
 name = "libc"
-version = "0.2.153"
+version = "0.2.169"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
+checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a"
 
 [[package]]
 name = "line-wrap"
@@ -1142,11 +1123,11 @@ dependencies = [
  "futures",
  "futures-core",
  "futures-util",
- "http 1.0.0",
- "http-body 1.0.0",
+ "http",
+ "http-body",
  "http-body-util",
- "hyper 1.2.0",
- "hyper-rustls",
+ "hyper",
+ "hyper-rustls 0.26.0",
  "hyper-timeout",
  "hyper-util",
  "jsonwebtoken",
@@ -1160,7 +1141,7 @@ dependencies = [
  "serde_urlencoded",
  "snafu",
  "tokio",
- "tower",
+ "tower 0.4.13",
  "tower-http",
  "tracing",
  "url",
@@ -1407,9 +1388,9 @@ dependencies = [
  "futures",
  "goblin",
  "hex",
- "http 1.0.0",
+ "http",
  "http-body-util",
- "hyper 1.2.0",
+ "hyper",
  "hyper-util",
  "normalize-path",
  "object",
@@ -1418,7 +1399,7 @@ dependencies = [
  "pdb",
  "pep440_rs",
  "rayon",
- "reqwest 0.11.24",
+ "reqwest",
  "reqwest-middleware",
  "reqwest-retry",
  "scroll 0.12.0",
@@ -1445,6 +1426,58 @@ dependencies = [
  "memchr",
 ]
 
+[[package]]
+name = "quinn"
+version = "0.11.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "62e96808277ec6f97351a2380e6c25114bc9e67037775464979f3037c92d05ef"
+dependencies = [
+ "bytes",
+ "pin-project-lite",
+ "quinn-proto",
+ "quinn-udp",
+ "rustc-hash",
+ "rustls 0.23.21",
+ "socket2",
+ "thiserror 2.0.11",
+ "tokio",
+ "tracing",
+]
+
+[[package]]
+name = "quinn-proto"
+version = "0.11.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a2fe5ef3495d7d2e377ff17b1a8ce2ee2ec2a18cde8b6ad6619d65d0701c135d"
+dependencies = [
+ "bytes",
+ "getrandom",
+ "rand",
+ "ring",
+ "rustc-hash",
+ "rustls 0.23.21",
+ "rustls-pki-types",
+ "slab",
+ "thiserror 2.0.11",
+ "tinyvec",
+ "tracing",
+ "web-time",
+]
+
+[[package]]
+name = "quinn-udp"
+version = "0.5.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1c40286217b4ba3a71d644d752e6a0b71f13f1b6a2c5311acfcbe0c2418ed904"
+dependencies = [
+ "cfg_aliases",
+ "libc",
+ "once_cell",
+ "socket2",
+ "tracing",
+ "windows-sys 0.52.0",
+]
+
 [[package]]
 name = "quote"
 version = "1.0.35"
@@ -1524,20 +1557,23 @@ dependencies = [
 
 [[package]]
 name = "reqwest"
-version = "0.11.24"
+version = "0.12.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c6920094eb85afde5e4a138be3f2de8bbdf28000f0029e72c45025a56b042251"
+checksum = "43e734407157c3c2034e0258f5e4473ddb361b1e85f95a66690d67264d7cd1da"
 dependencies = [
- "base64 0.21.7",
+ "base64 0.22.1",
  "bytes",
  "encoding_rs",
  "futures-core",
  "futures-util",
  "h2",
- "http 0.2.11",
- "http-body 0.4.6",
- "hyper 0.14.28",
+ "http",
+ "http-body",
+ "http-body-util",
+ "hyper",
+ "hyper-rustls 0.27.5",
  "hyper-tls",
+ "hyper-util",
  "ipnet",
  "js-sys",
  "log",
@@ -1546,58 +1582,28 @@ dependencies = [
  "once_cell",
  "percent-encoding",
  "pin-project-lite",
- "rustls 0.21.11",
- "rustls-pemfile 1.0.4",
+ "quinn",
+ "rustls 0.23.21",
+ "rustls-pemfile",
+ "rustls-pki-types",
  "serde",
  "serde_json",
  "serde_urlencoded",
- "sync_wrapper 0.1.2",
+ "sync_wrapper",
  "system-configuration",
  "tokio",
  "tokio-native-tls",
+ "tokio-rustls 0.26.1",
  "tokio-util",
+ "tower 0.5.2",
  "tower-service",
  "url",
  "wasm-bindgen",
  "wasm-bindgen-futures",
  "wasm-streams",
  "web-sys",
- "winreg 0.50.0",
-]
-
-[[package]]
-name = "reqwest"
-version = "0.12.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c7d6d2a27d57148378eb5e111173f4276ad26340ecc5c49a4a2152167a2d6a37"
-dependencies = [
- "base64 0.22.1",
- "bytes",
- "futures-core",
- "futures-util",
- "http 1.0.0",
- "http-body 1.0.0",
- "http-body-util",
- "hyper 1.2.0",
- "hyper-util",
- "ipnet",
- "js-sys",
- "log",
- "mime",
- "once_cell",
- "percent-encoding",
- "pin-project-lite",
- "serde",
- "serde_json",
- "serde_urlencoded",
- "sync_wrapper 1.0.2",
- "tokio",
- "tower-service",
- "url",
- "wasm-bindgen",
- "wasm-bindgen-futures",
- "web-sys",
- "winreg 0.52.0",
+ "webpki-roots",
+ "windows-registry",
 ]
 
 [[package]]
@@ -1608,10 +1614,10 @@ checksum = "d1ccd3b55e711f91a9885a2fa6fbbb2e39db1776420b062efc058c6410f7e5e3"
 dependencies = [
  "anyhow",
  "async-trait",
- "http 1.0.0",
- "reqwest 0.12.5",
+ "http",
+ "reqwest",
  "serde",
- "thiserror",
+ "thiserror 1.0.69",
  "tower-service",
 ]
 
@@ -1625,13 +1631,13 @@ dependencies = [
  "async-trait",
  "futures",
  "getrandom",
- "http 1.0.0",
- "hyper 1.2.0",
+ "http",
+ "hyper",
  "parking_lot",
- "reqwest 0.12.5",
+ "reqwest",
  "reqwest-middleware",
  "retry-policies",
- "thiserror",
+ "thiserror 1.0.69",
  "tokio",
  "tracing",
  "wasm-timer",
@@ -1667,6 +1673,12 @@ version = "0.1.23"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
 
+[[package]]
+name = "rustc-hash"
+version = "2.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c7fb8039b3032c191086b10f11f319a6e99e1e82889c5cc6046f515c9db1d497"
+
 [[package]]
 name = "rustix"
 version = "0.38.31"
@@ -1682,26 +1694,28 @@ dependencies = [
 
 [[package]]
 name = "rustls"
-version = "0.21.11"
+version = "0.22.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7fecbfb7b1444f477b345853b1fce097a2c6fb637b2bfb87e6bc5db0f043fae4"
+checksum = "e87c9956bd9807afa1f77e0f7594af32566e830e088a5576d27c5b6f30f49d41"
 dependencies = [
  "log",
  "ring",
- "rustls-webpki 0.101.7",
- "sct",
+ "rustls-pki-types",
+ "rustls-webpki",
+ "subtle",
+ "zeroize",
 ]
 
 [[package]]
 name = "rustls"
-version = "0.22.2"
+version = "0.23.21"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e87c9956bd9807afa1f77e0f7594af32566e830e088a5576d27c5b6f30f49d41"
+checksum = "8f287924602bf649d949c63dc8ac8b235fa5387d394020705b80c4eb597ce5b8"
 dependencies = [
- "log",
+ "once_cell",
  "ring",
  "rustls-pki-types",
- "rustls-webpki 0.102.2",
+ "rustls-webpki",
  "subtle",
  "zeroize",
 ]
@@ -1713,21 +1727,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8f1fb85efa936c42c6d5fc28d2629bb51e4b2f4b8a5211e297d599cc5a093792"
 dependencies = [
  "openssl-probe",
- "rustls-pemfile 2.1.0",
+ "rustls-pemfile",
  "rustls-pki-types",
  "schannel",
  "security-framework",
 ]
 
-[[package]]
-name = "rustls-pemfile"
-version = "1.0.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c"
-dependencies = [
- "base64 0.21.7",
-]
-
 [[package]]
 name = "rustls-pemfile"
 version = "2.1.0"
@@ -1740,25 +1745,18 @@ dependencies = [
 
 [[package]]
 name = "rustls-pki-types"
-version = "1.3.0"
+version = "1.10.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "048a63e5b3ac996d78d402940b5fa47973d2d080c6c6fffa1d0f19c4445310b7"
-
-[[package]]
-name = "rustls-webpki"
-version = "0.101.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765"
+checksum = "d2bf47e6ff922db3825eb750c4e2ff784c6ff8fb9e13046ef6a1d1c5401b0b37"
 dependencies = [
- "ring",
- "untrusted",
+ "web-time",
 ]
 
 [[package]]
 name = "rustls-webpki"
-version = "0.102.2"
+version = "0.102.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "faaa0a62740bedb9b2ef5afa303da42764c012f743917351dc9a237ea1663610"
+checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9"
 dependencies = [
  "ring",
  "rustls-pki-types",
@@ -1829,16 +1827,6 @@ dependencies = [
  "syn 2.0.95",
 ]
 
-[[package]]
-name = "sct"
-version = "0.7.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414"
-dependencies = [
- "ring",
- "untrusted",
-]
-
 [[package]]
 name = "secrecy"
 version = "0.8.0"
@@ -1983,7 +1971,7 @@ checksum = "adc4e5204eb1910f40f9cfa375f6f05b68c3abac4b6fd879c8ff5e7ae8a0a085"
 dependencies = [
  "num-bigint",
  "num-traits",
- "thiserror",
+ "thiserror 1.0.69",
  "time",
 ]
 
@@ -2081,34 +2069,31 @@ dependencies = [
  "unicode-ident",
 ]
 
-[[package]]
-name = "sync_wrapper"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160"
-
 [[package]]
 name = "sync_wrapper"
 version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263"
+dependencies = [
+ "futures-core",
+]
 
 [[package]]
 name = "system-configuration"
-version = "0.5.1"
+version = "0.6.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7"
+checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b"
 dependencies = [
- "bitflags 1.3.2",
+ "bitflags 2.4.2",
  "core-foundation",
  "system-configuration-sys",
 ]
 
 [[package]]
 name = "system-configuration-sys"
-version = "0.5.0"
+version = "0.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9"
+checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4"
 dependencies = [
  "core-foundation-sys",
  "libc",
@@ -2154,7 +2139,16 @@ version = "1.0.69"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
 dependencies = [
- "thiserror-impl",
+ "thiserror-impl 1.0.69",
+]
+
+[[package]]
+name = "thiserror"
+version = "2.0.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d452f284b73e6d76dd36758a0c8684b1d5be31f92b89d07fd5822175732206fc"
+dependencies = [
+ "thiserror-impl 2.0.11",
 ]
 
 [[package]]
@@ -2168,6 +2162,17 @@ dependencies = [
  "syn 2.0.95",
 ]
 
+[[package]]
+name = "thiserror-impl"
+version = "2.0.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "26afc1baea8a989337eeb52b6e72a039780ce45c3edfcc9c5b9d112feeb173c2"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.95",
+]
+
 [[package]]
 name = "time"
 version = "0.3.36"
@@ -2250,6 +2255,16 @@ dependencies = [
  "tokio",
 ]
 
+[[package]]
+name = "tokio-rustls"
+version = "0.26.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5f6d0975eaace0cf0fcadee4e4aaa5da15b5c079146f2cffb67c113be122bf37"
+dependencies = [
+ "rustls 0.23.21",
+ "tokio",
+]
+
 [[package]]
 name = "tokio-util"
 version = "0.7.10"
@@ -2281,6 +2296,21 @@ dependencies = [
  "tracing",
 ]
 
+[[package]]
+name = "tower"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9"
+dependencies = [
+ "futures-core",
+ "futures-util",
+ "pin-project-lite",
+ "sync_wrapper",
+ "tokio",
+ "tower-layer",
+ "tower-service",
+]
+
 [[package]]
 name = "tower-http"
 version = "0.5.2"
@@ -2290,12 +2320,12 @@ dependencies = [
  "bitflags 2.4.2",
  "bytes",
  "futures-util",
- "http 1.0.0",
- "http-body 1.0.0",
+ "http",
+ "http-body",
  "http-body-util",
  "iri-string",
  "pin-project-lite",
- "tower",
+ "tower 0.4.13",
  "tower-layer",
  "tower-service",
  "tracing",
@@ -2303,15 +2333,15 @@ dependencies = [
 
 [[package]]
 name = "tower-layer"
-version = "0.3.2"
+version = "0.3.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0"
+checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e"
 
 [[package]]
 name = "tower-service"
-version = "0.3.2"
+version = "0.3.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52"
+checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3"
 
 [[package]]
 name = "tracing"
@@ -2573,6 +2603,25 @@ dependencies = [
  "wasm-bindgen",
 ]
 
+[[package]]
+name = "web-time"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb"
+dependencies = [
+ "js-sys",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "webpki-roots"
+version = "0.26.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5d642ff16b7e79272ae451b7322067cdc17cadf68c23264be9d94a32319efe7e"
+dependencies = [
+ "rustls-pki-types",
+]
+
 [[package]]
 name = "winapi"
 version = "0.3.9"
@@ -2601,7 +2650,37 @@ version = "0.52.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
 dependencies = [
- "windows-targets 0.52.3",
+ "windows-targets 0.52.6",
+]
+
+[[package]]
+name = "windows-registry"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0"
+dependencies = [
+ "windows-result",
+ "windows-strings",
+ "windows-targets 0.52.6",
+]
+
+[[package]]
+name = "windows-result"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e"
+dependencies = [
+ "windows-targets 0.52.6",
+]
+
+[[package]]
+name = "windows-strings"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10"
+dependencies = [
+ "windows-result",
+ "windows-targets 0.52.6",
 ]
 
 [[package]]
@@ -2619,7 +2698,7 @@ version = "0.52.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
 dependencies = [
- "windows-targets 0.52.3",
+ "windows-targets 0.52.6",
 ]
 
 [[package]]
@@ -2639,17 +2718,18 @@ dependencies = [
 
 [[package]]
 name = "windows-targets"
-version = "0.52.3"
+version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d380ba1dc7187569a8a9e91ed34b8ccfc33123bbacb8c0aed2d1ad7f3ef2dc5f"
+checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
 dependencies = [
- "windows_aarch64_gnullvm 0.52.3",
- "windows_aarch64_msvc 0.52.3",
- "windows_i686_gnu 0.52.3",
- "windows_i686_msvc 0.52.3",
- "windows_x86_64_gnu 0.52.3",
- "windows_x86_64_gnullvm 0.52.3",
- "windows_x86_64_msvc 0.52.3",
+ "windows_aarch64_gnullvm 0.52.6",
+ "windows_aarch64_msvc 0.52.6",
+ "windows_i686_gnu 0.52.6",
+ "windows_i686_gnullvm",
+ "windows_i686_msvc 0.52.6",
+ "windows_x86_64_gnu 0.52.6",
+ "windows_x86_64_gnullvm 0.52.6",
+ "windows_x86_64_msvc 0.52.6",
 ]
 
 [[package]]
@@ -2660,9 +2740,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
 
 [[package]]
 name = "windows_aarch64_gnullvm"
-version = "0.52.3"
+version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "68e5dcfb9413f53afd9c8f86e56a7b4d86d9a2fa26090ea2dc9e40fba56c6ec6"
+checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
 
 [[package]]
 name = "windows_aarch64_msvc"
@@ -2672,9 +2752,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
 
 [[package]]
 name = "windows_aarch64_msvc"
-version = "0.52.3"
+version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8dab469ebbc45798319e69eebf92308e541ce46760b49b18c6b3fe5e8965b30f"
+checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
 
 [[package]]
 name = "windows_i686_gnu"
@@ -2684,9 +2764,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
 
 [[package]]
 name = "windows_i686_gnu"
-version = "0.52.3"
+version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2a4e9b6a7cac734a8b4138a4e1044eac3404d8326b6c0f939276560687a033fb"
+checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
+
+[[package]]
+name = "windows_i686_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
 
 [[package]]
 name = "windows_i686_msvc"
@@ -2696,9 +2782,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
 
 [[package]]
 name = "windows_i686_msvc"
-version = "0.52.3"
+version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "28b0ec9c422ca95ff34a78755cfa6ad4a51371da2a5ace67500cf7ca5f232c58"
+checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
 
 [[package]]
 name = "windows_x86_64_gnu"
@@ -2708,9 +2794,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
 
 [[package]]
 name = "windows_x86_64_gnu"
-version = "0.52.3"
+version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "704131571ba93e89d7cd43482277d6632589b18ecf4468f591fbae0a8b101614"
+checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
 
 [[package]]
 name = "windows_x86_64_gnullvm"
@@ -2720,9 +2806,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
 
 [[package]]
 name = "windows_x86_64_gnullvm"
-version = "0.52.3"
+version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "42079295511643151e98d61c38c0acc444e52dd42ab456f7ccfd5152e8ecf21c"
+checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
 
 [[package]]
 name = "windows_x86_64_msvc"
@@ -2732,29 +2818,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
 
 [[package]]
 name = "windows_x86_64_msvc"
-version = "0.52.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0770833d60a970638e989b3fa9fd2bb1aaadcf88963d1659fd7d9990196ed2d6"
-
-[[package]]
-name = "winreg"
-version = "0.50.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1"
-dependencies = [
- "cfg-if",
- "windows-sys 0.48.0",
-]
-
-[[package]]
-name = "winreg"
-version = "0.52.0"
+version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a277a57398d4bfa075df44f501a17cfdf8542d224f0d36095a2adc7aee4ef0a5"
-dependencies = [
- "cfg-if",
- "windows-sys 0.48.0",
-]
+checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
 
 [[package]]
 name = "xattr"
diff --git a/Cargo.toml b/Cargo.toml
index ba5b32ac..e3826630 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -25,7 +25,7 @@ once_cell = "1.19.0"
 pdb = "0.8.0"
 pep440_rs = "0.6.6"
 rayon = "1.8.1"
-reqwest = { version = "0.11.24", features = ["rustls", "stream"] }
+reqwest = { version = "0.12.12", features = ["rustls-tls-webpki-roots", "stream"] }
 reqwest-middleware = "0.4.0"
 reqwest-retry = "0.7.0"
 scroll = "0.12.0"
diff --git a/src/github.rs b/src/github.rs
index bfc03d01..8a432841 100644
--- a/src/github.rs
+++ b/src/github.rs
@@ -16,8 +16,8 @@ use {
         Octocrab, OctocrabBuilder,
     },
     rayon::prelude::*,
-    reqwest::StatusCode,
-    reqwest_middleware::{reqwest, ClientBuilder, ClientWithMiddleware},
+    reqwest::{Client, StatusCode},
+    reqwest_middleware::{self, ClientWithMiddleware},
     reqwest_retry::{
         default_on_request_failure, policies::ExponentialBackoff, RetryTransientMiddleware,
         Retryable, RetryableStrategy,
@@ -473,7 +473,7 @@ pub async fn command_upload_release_distributions(args: &ArgMatches) -> Result<(
     let mut digests = BTreeMap::new();
 
     let retry_policy = ExponentialBackoff::builder().build_with_max_retries(5);
-    let raw_client = ClientBuilder::new(reqwest_middleware::reqwest::Client::new())
+    let raw_client = reqwest_middleware::ClientBuilder::new(Client::new())
         .with(RetryTransientMiddleware::new_with_policy_and_strategy(
             retry_policy,
             GitHubUploadRetryStrategy,

From 8dc1b9ca41b1c2c3545e469a18abc570672b968b Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Tue, 28 Jan 2025 10:04:12 -0600
Subject: [PATCH 035/157] Fix virtual environment creation when bootstrapping
 build environments with a standalone Python (#505)

Per
https://github.com/astral-sh/python-build-standalone/issues/381#issuecomment-2616817789
this should stop the build bootsrapping script from crashing when
running the build with a standalone Python distribution (which was..
really annoying me).
---
 build-linux.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/build-linux.py b/build-linux.py
index 2128c331..95a71604 100755
--- a/build-linux.py
+++ b/build-linux.py
@@ -21,7 +21,7 @@
 def bootstrap():
     BUILD.mkdir(exist_ok=True)
 
-    venv.create(VENV, with_pip=True)
+    venv.create(VENV, with_pip=True, symlinks=True)
 
     subprocess.run([str(PIP), "install", "-r", str(REQUIREMENTS)], check=True)
 

From cb32f8db9f02ba0459dd7b2774275dcf0dfb93e0 Mon Sep 17 00:00:00 2001
From: samypr100 <3933065+samypr100@users.noreply.github.com>
Date: Tue, 28 Jan 2025 12:41:14 -0500
Subject: [PATCH 036/157] Build attestations improvements (#501)

Per
https://github.com/astral-sh/python-build-standalone/issues/343#issuecomment-2598666478

* Adds attestations to build-0 of the linux matrix (due to recent
refactor)
* Adds attestations to release artifacts which include install only
derived builds.
---
 .github/workflows/linux.yml   | 6 ++++++
 .github/workflows/release.yml | 9 +++++++++
 2 files changed, 15 insertions(+)

diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml
index 5941c85f..1c8377d2 100644
--- a/.github/workflows/linux.yml
+++ b/.github/workflows/linux.yml
@@ -245,6 +245,12 @@ jobs:
 
           build/pythonbuild validate-distribution ${EXTRA_ARGS} dist/*.tar.zst
 
+      - name: Generate attestations
+        uses: actions/attest-build-provenance@v2
+        if: ${{ github.ref == 'refs/heads/main' }}
+        with:
+          subject-path: dist/*
+
       - name: Upload Distribution
         if: ${{ ! matrix.dry-run }}
         uses: actions/upload-artifact@v4
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 3faca6ac..cf58dc13 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -21,6 +21,9 @@ env:
 permissions:
   contents: write
   packages: write
+  # Permissions used for actions/attest-build-provenance
+  id-token: write
+  attestations: write
 
 jobs:
   release:
@@ -75,3 +78,9 @@ jobs:
       # Uploading the relevant artifact to the GitHub release.
       - run: just release-run ${{ secrets.GITHUB_TOKEN }} ${{ github.event.inputs.sha }} ${{ github.event.inputs.tag }}
         if: ${{ github.event.inputs.dry-run == 'false' }}
+
+      - name: Generate attestations
+        uses: actions/attest-build-provenance@v2
+        if: ${{ github.event.inputs.dry-run == 'false' }}
+        with:
+          subject-path: dist/*.tar.@(zst|gz)

From dfb68b21e37b4629733aca0b347ba952ccfb67e4 Mon Sep 17 00:00:00 2001
From: Geoffrey Thomas <geofft@ldpreload.com>
Date: Thu, 30 Jan 2025 16:44:24 -0500
Subject: [PATCH 037/157] Make the installed pkg-config files relocatable
 (astral-sh/uv#11028) (#507)

This ensures that e.g. `PKG_CONFIG_PATH=/wherever/python/lib/pkgconfig
pkg-config --cflags` gets you existent paths in /wherever/python instead
of nonexistent paths in /install.
---
 cpython-unix/build-cpython.sh | 5 +++++
 docs/quirks.rst               | 1 -
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/cpython-unix/build-cpython.sh b/cpython-unix/build-cpython.sh
index a04677f1..de471953 100755
--- a/cpython-unix/build-cpython.sh
+++ b/cpython-unix/build-cpython.sh
@@ -1116,5 +1116,10 @@ else
     cp -av Tools/scripts/run_tests.py ${ROOT}/out/python/build/
 fi
 
+# Don't hard-code the build-time prefix into the pkg-config files. See
+# the description of `pcfiledir` in `man pkg-config`.
+find ${ROOT}/out/python/install/lib/pkgconfig -name \*.pc -type f -exec \
+    sed ${sed_args} 's|^prefix=/install|prefix=${pcfiledir}/../..|' {} +
+
 mkdir ${ROOT}/out/python/licenses
 cp ${ROOT}/LICENSE.*.txt ${ROOT}/out/python/licenses/
diff --git a/docs/quirks.rst b/docs/quirks.rst
index 04e2484c..3c16745e 100644
--- a/docs/quirks.rst
+++ b/docs/quirks.rst
@@ -305,7 +305,6 @@ build-time configuration in a handful of files:
   ``lib/python3.10/_sysconfigdata__linux_x86_64-linux-gnu.py``.
 * In a ``Makefile`` under a ``config-*`` directory in the standard library.
   e.g. ``lib/python3.10/config-3.10-x86_64-linux-gnu/Makefile``.
-* In ``pkgconfig`` files. e.g. ``lib/pkgconfig/python3.pc``.
 * In ``python*-config`` files. e.g. ``bin/python3.10-config``.
 * In ``PYTHON.json`` (mostly reflected values from ``_sysconfigdata_*.py``.
 

From 12d9c061f080ca69ffe7bbc19e8db940bbafdd7b Mon Sep 17 00:00:00 2001
From: Geoffrey Thomas <geofft@ldpreload.com>
Date: Thu, 30 Jan 2025 16:44:36 -0500
Subject: [PATCH 038/157] build-cpython.sh: Don't repack the pip wheel (#506)

We're no longer patching it as of #401 (3dbca1c08f) so there's no longer
a need to unpack and repack it.
---
 cpython-unix/build-cpython.sh | 17 -----------------
 1 file changed, 17 deletions(-)

diff --git a/cpython-unix/build-cpython.sh b/cpython-unix/build-cpython.sh
index de471953..a07188a6 100755
--- a/cpython-unix/build-cpython.sh
+++ b/cpython-unix/build-cpython.sh
@@ -51,23 +51,6 @@ tar -xf Python-${PYTHON_VERSION}.tar.xz
 PIP_WHEEL="${ROOT}/pip-${PIP_VERSION}-py3-none-any.whl"
 SETUPTOOLS_WHEEL="${ROOT}/setuptools-${SETUPTOOLS_VERSION}-py3-none-any.whl"
 
-# pip and setuptools don't properly handle the case where the current executable
-# isn't dynamic. This is tracked by https://github.com/pypa/pip/issues/6543.
-# We need to patch both.
-#
-# Ideally we'd do this later in the build. However, since we use the pip
-# wheel to bootstrap itself, we need to patch the wheel before it is used.
-#
-# Wheels are zip files. So we simply unzip, patch, and rezip.
-mkdir pip-tmp
-pushd pip-tmp
-unzip "${PIP_WHEEL}"
-rm -f "${PIP_WHEEL}"
-
-zip -r "${PIP_WHEEL}" *
-popd
-rm -rf pip-tmp
-
 cat Setup.local
 mv Setup.local Python-${PYTHON_VERSION}/Modules/Setup.local
 

From 4615f2f41cfb033f1838f1ca5f7e1f41d53e7222 Mon Sep 17 00:00:00 2001
From: samypr100 <3933065+samypr100@users.noreply.github.com>
Date: Mon, 3 Feb 2025 13:58:07 -0500
Subject: [PATCH 039/157] Adjust python-build-standalone links (#509)

## Summary

When running locally, I noticed constant redirects in my traffic from
`indygreg/python-build-standalone` to
`astral-sh/python-build-standalone`. This PR corrects some of the links
to avoid the redirects by using the new canonical location.

## Test Plan

Manually verified all adjusted links work as expected.
---
 .github/workflows/linux.yml        | 2 +-
 Justfile                           | 4 ++--
 cpython-unix/build.py              | 2 +-
 cpython-unix/extension-modules.yml | 2 +-
 docs/quirks.rst                    | 8 ++++----
 docs/running.rst                   | 4 ++--
 docs/technotes.rst                 | 2 +-
 pythonbuild/downloads.py           | 2 +-
 pythonbuild/utils.py               | 2 +-
 src/main.rs                        | 4 ++--
 src/validation.rs                  | 2 +-
 11 files changed, 17 insertions(+), 17 deletions(-)

diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml
index 1c8377d2..7445e80b 100644
--- a/.github/workflows/linux.yml
+++ b/.github/workflows/linux.yml
@@ -107,7 +107,7 @@ jobs:
           cache-from: |
             type=registry,ref=ghcr.io/${{ env.REPO_NAME }}:${{ matrix.image }}-${{ env.GIT_REF_NAME }}
             type=registry,ref=ghcr.io/${{ env.REPO_NAME }}:${{ matrix.image }}-main
-            type=registry,ref=ghcr.io/indygreg/python-build-standalone:${{ matrix.image }}-main
+            type=registry,ref=ghcr.io/astral-sh/python-build-standalone:${{ matrix.image }}-main
           cache-to: |
             type=registry,ref=ghcr.io/${{ env.REPO_NAME }}:${{ matrix.image }}-${{ env.GIT_REF_NAME }},ignore-error=true
           outputs: |
diff --git a/Justfile b/Justfile
index 1d6a02a3..0255bd22 100644
--- a/Justfile
+++ b/Justfile
@@ -51,8 +51,8 @@ release-set-latest-release tag:
   {
     "version": 1,
     "tag": "{{tag}}",
-    "release_url": "https://github.com/indygreg/python-build-standalone/releases/tag/{{tag}}",
-    "asset_url_prefix": "https://github.com/indygreg/python-build-standalone/releases/download/{{tag}}"
+    "release_url": "https://github.com/astral-sh/python-build-standalone/releases/tag/{{tag}}",
+    "asset_url_prefix": "https://github.com/astral-sh/python-build-standalone/releases/download/{{tag}}"
   }
   EOF
 
diff --git a/cpython-unix/build.py b/cpython-unix/build.py
index 5d4b5c9d..da66ba4e 100755
--- a/cpython-unix/build.py
+++ b/cpython-unix/build.py
@@ -548,7 +548,7 @@ def python_build_info(
     mips = target_triple.split("-")[0] in {"mips", "mipsel"}
     linux_allowed_system_libraries = LINUX_ALLOW_SYSTEM_LIBRARIES.copy()
     if mips and version == "3.13":
-        # See https://github.com/indygreg/python-build-standalone/issues/410
+        # See https://github.com/astral-sh/python-build-standalone/issues/410
         linux_allowed_system_libraries.add("atomic")
     riscv = target_triple.split("-")[0] in {"riscv64"}
     if riscv:
diff --git a/cpython-unix/extension-modules.yml b/cpython-unix/extension-modules.yml
index 968f8d81..a8ff460f 100644
--- a/cpython-unix/extension-modules.yml
+++ b/cpython-unix/extension-modules.yml
@@ -833,7 +833,7 @@ nis:
     # has a wonky history where it was once part of glibc and core system installs
     # but is slowly being phased away from base installations. There are potential
     # workarounds to adding nis support. See discussion in
-    # https://github.com/indygreg/python-build-standalone/issues/51.
+    # https://github.com/astral-sh/python-build-standalone/issues/51.
     - .*
 
   sources:
diff --git a/docs/quirks.rst b/docs/quirks.rst
index 3c16745e..77e4d4fe 100644
--- a/docs/quirks.rst
+++ b/docs/quirks.rst
@@ -197,7 +197,7 @@ distributions aren't compatible with
 stipulates that Python and extension modules are linked against a
 dynamic musl. This is what you'll find in Alpine Linux, for example.
 
-See https://github.com/indygreg/python-build-standalone/issues/86 for
+See https://github.com/astral-sh/python-build-standalone/issues/86 for
 a tracking issue to improve the state of musl distributions.
 
 .. _quirk_linux_libx11:
@@ -249,7 +249,7 @@ The static linking of ``libX11`` and other libraries can cause problems when
 loaded into the process. For example, extension modules associated with ``PyQt``
 are known to link against a shared ``libX11.so.6``. If multiple versions of
 ``libX11`` are loaded into the same process, run-time crashes / segfaults can
-occur. See e.g. https://github.com/indygreg/python-build-standalone/issues/95.
+occur. See e.g. https://github.com/astral-sh/python-build-standalone/issues/95.
 
 The conceptual workaround is to not statically link ``libX11`` and similar
 libraries into ``libpython``. However, this requires re-linking a custom
@@ -289,8 +289,8 @@ on ``libcrypt.so.1`` and don't want to upgrade, you can instruct end-users
 to install a ``libxcrypt-compat`` (or comparable) package to provide the
 missing ``libcrypt.so.1``.
 
-See https://github.com/indygreg/python-build-standalone/issues/113 and
-https://github.com/indygreg/python-build-standalone/issues/173 for additional
+See https://github.com/astral-sh/python-build-standalone/issues/113 and
+https://github.com/astral-sh/python-build-standalone/issues/173 for additional
 context on this matter.
 
 .. _quirk_references_to_build_paths:
diff --git a/docs/running.rst b/docs/running.rst
index 41b76cec..22d3db04 100644
--- a/docs/running.rst
+++ b/docs/running.rst
@@ -8,14 +8,14 @@ Obtaining Distributions
 =======================
 
 Pre-built distributions are published as releases on GitHub at
-https://github.com/indygreg/python-build-standalone/releases.
+https://github.com/astral-sh/python-build-standalone/releases.
 Simply go to that page and find the latest release along with
 its release notes.
 
 Machines can find the latest release by querying the GitHub releases
 API. Alternatively, a JSON file publishing metadata about the latest
 release can be fetched from
-https://raw.githubusercontent.com/indygreg/python-build-standalone/latest-release/latest-release.json.
+https://raw.githubusercontent.com/astral-sh/python-build-standalone/latest-release/latest-release.json.
 The JSON format is simple and hopefully self-descriptive.
 
 Published distributions vary by their:
diff --git a/docs/technotes.rst b/docs/technotes.rst
index a362999d..613f10c6 100644
--- a/docs/technotes.rst
+++ b/docs/technotes.rst
@@ -120,7 +120,7 @@ versions of Fedora and RHEL.
 Because the ``nis`` extension is perceived to be likely unused functionality,
 we've decided to not build it instead of adding complexity to deal with
 the ``libnsl`` dependency. See further discussion in
-https://github.com/indygreg/python-build-standalone/issues/51.
+https://github.com/astral-sh/python-build-standalone/issues/51.
 
 If ``nis`` functionality is important to you, please file a GitHub issue
 to request it.
diff --git a/pythonbuild/downloads.py b/pythonbuild/downloads.py
index 401bd171..1e9a8ed8 100644
--- a/pythonbuild/downloads.py
+++ b/pythonbuild/downloads.py
@@ -416,7 +416,7 @@
     # IMPORTANT: xz 5.6 has a backdoor. Be extremely cautious before taking any xz
     # upgrade since it isn't clear which versions are safe.
     "xz": {
-        "url": "https://github.com/indygreg/python-build-standalone/releases/download/20240224/xz-5.2.12.tar.gz",
+        "url": "https://github.com/astral-sh/python-build-standalone/releases/download/20240224/xz-5.2.12.tar.gz",
         "size": 2190541,
         "sha256": "61bda930767dcb170a5328a895ec74cab0f5aac4558cdda561c83559db582a13",
         "version": "5.2.12",
diff --git a/pythonbuild/utils.py b/pythonbuild/utils.py
index 13bea0df..6fe5e355 100644
--- a/pythonbuild/utils.py
+++ b/pythonbuild/utils.py
@@ -617,7 +617,7 @@ def validate_python_json(info, extension_modules):
 
 def release_download_statistics(mode="by_asset"):
     with urllib.request.urlopen(
-        "https://api.github.com/repos/indygreg/python-build-standalone/releases"
+        "https://api.github.com/repos/astral-sh/python-build-standalone/releases"
     ) as fh:
         data = json.load(fh)
 
diff --git a/src/main.rs b/src/main.rs
index b12ef0fa..df441e13 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -61,7 +61,7 @@ fn main_impl() -> Result<()> {
                 Arg::new("organization")
                     .long("org")
                     .action(ArgAction::Set)
-                    .default_value("indygreg")
+                    .default_value("astral-sh")
                     .help("GitHub organization"),
             )
             .arg(
@@ -145,7 +145,7 @@ fn main_impl() -> Result<()> {
                 Arg::new("organization")
                     .long("org")
                     .action(ArgAction::Set)
-                    .default_value("indygreg")
+                    .default_value("astral-sh")
                     .help("GitHub organization"),
             )
             .arg(
diff --git a/src/validation.rs b/src/validation.rs
index 1beea181..4bb28de0 100644
--- a/src/validation.rs
+++ b/src/validation.rs
@@ -40,7 +40,7 @@ const RECOGNIZED_TRIPLES: &[&str] = &[
     "i686-pc-windows-msvc",
     "i686-unknown-linux-gnu",
     // Note there's build support for mips* targets but they are not tested
-    // See https://github.com/indygreg/python-build-standalone/issues/412
+    // See https://github.com/astral-sh/python-build-standalone/issues/412
     "mips-unknown-linux-gnu",
     "mipsel-unknown-linux-gnu",
     "mips64el-unknown-linux-gnuabi64",

From 183bc646b12dc35a39d2fd7c21ac2afa055a5395 Mon Sep 17 00:00:00 2001
From: Geoffrey Thomas <geofft@ldpreload.com>
Date: Wed, 5 Feb 2025 13:46:31 -0500
Subject: [PATCH 040/157] Upgrade CPython 3.12.8 to 3.12.9, 3.13.1 to 3.13.2
 (#513)

Our BOLT patches that landed for 3.14 have been backported to 3.12 and
3.13, so the remaining BOLT patch now applies to 3.12+.
---
 cpython-unix/build-cpython.sh                 | 14 ++----
 ...h-configure-bolt-apply-flags-128514.patch} |  0
 .../patch-configure-bolt-apply-flags.patch    | 23 ---------
 cpython-unix/patch-configure-bolt-flags.patch | 50 -------------------
 .../patch-test-embed-prevent-segfault.patch   |  8 ---
 pythonbuild/downloads.py                      | 16 +++---
 6 files changed, 11 insertions(+), 100 deletions(-)
 rename cpython-unix/{patch-configure-bolt-apply-flags-3.14.patch => patch-configure-bolt-apply-flags-128514.patch} (100%)
 delete mode 100644 cpython-unix/patch-configure-bolt-apply-flags.patch
 delete mode 100644 cpython-unix/patch-configure-bolt-flags.patch

diff --git a/cpython-unix/build-cpython.sh b/cpython-unix/build-cpython.sh
index a07188a6..6d8a5cde 100755
--- a/cpython-unix/build-cpython.sh
+++ b/cpython-unix/build-cpython.sh
@@ -267,17 +267,9 @@ if [ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_11}" ]; then
 fi
 
 if [ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_12}" ]; then
-    # On 3.14+, we upstreamed these changes and they are no longer needed
-    if [ -n "${PYTHON_MEETS_MAXIMUM_VERSION_3_13}" ]; then
-        # Adjust BOLT flags to yield better behavior. See inline details in patch.
-        patch -p1 -i ${ROOT}/patch-configure-bolt-flags.patch
-
-        # Adjust BOLT application flags to make use of modern LLVM features.
-        patch -p1 -i ${ROOT}/patch-configure-bolt-apply-flags.patch
-    else
-        # We are still upstreaming some additional optimization flags
-        patch -p1 -i ${ROOT}/patch-configure-bolt-apply-flags-3.14.patch
-    fi
+    # Additional BOLT optimizations, being upstreamed in
+    # https://github.com/python/cpython/issues/128514
+    patch -p1 -i ${ROOT}/patch-configure-bolt-apply-flags-128514.patch
 fi
 
 # The optimization make targets are both phony and non-phony. This leads
diff --git a/cpython-unix/patch-configure-bolt-apply-flags-3.14.patch b/cpython-unix/patch-configure-bolt-apply-flags-128514.patch
similarity index 100%
rename from cpython-unix/patch-configure-bolt-apply-flags-3.14.patch
rename to cpython-unix/patch-configure-bolt-apply-flags-128514.patch
diff --git a/cpython-unix/patch-configure-bolt-apply-flags.patch b/cpython-unix/patch-configure-bolt-apply-flags.patch
deleted file mode 100644
index c91822e4..00000000
--- a/cpython-unix/patch-configure-bolt-apply-flags.patch
+++ /dev/null
@@ -1,23 +0,0 @@
-diff --git a/configure.ac b/configure.ac
-index ee034e5a962..f1a69b7d4a7 100644
---- a/configure.ac
-+++ b/configure.ac
-@@ -2183,8 +2183,9 @@ then
-     [m4_normalize("
-      -update-debug-sections
-      -reorder-blocks=ext-tsp
--     -reorder-functions=hfsort+
-+     -reorder-functions=cdsort
-      -split-functions
-+     -split-strategy=cdsplit
-      -icf=1
-      -inline-all
-      -split-eh
-@@ -2196,6 +2197,7 @@ then
-      -dyno-stats
-      -use-gnu-stack
-      -frame-opt=hot
-+     -hugify
-    ")]
-   )
- fi
diff --git a/cpython-unix/patch-configure-bolt-flags.patch b/cpython-unix/patch-configure-bolt-flags.patch
deleted file mode 100644
index c9fbf824..00000000
--- a/cpython-unix/patch-configure-bolt-flags.patch
+++ /dev/null
@@ -1,50 +0,0 @@
-diff --git a/configure.ac b/configure.ac
-index bc8c357e996..eef55d4839a 100644
---- a/configure.ac
-+++ b/configure.ac
-@@ -2104,6 +2104,27 @@ AS_VAR_IF([enable_shared], [yes], [
-   BOLT_BINARIES="${BOLT_BINARIES} \$(INSTSONAME)"
- ])
- 
-+AC_ARG_VAR(
-+  [BOLT_COMMON_FLAGS],
-+  [Common arguments to llvm-bolt when instrumenting and applying]
-+)
-+
-+AC_MSG_CHECKING([BOLT_COMMON_FLAGS])
-+if test -z "${BOLT_COMMON_FLAGS}"
-+then
-+  AS_VAR_SET(
-+    [BOLT_COMMON_FLAGS],
-+    [m4_normalize("
-+      [-update-debug-sections]
-+
-+      dnl At least LLVM 19.x doesn't support computed gotos in PIC compiled code.
-+      dnl Exclude functions containing computed gotos.
-+      dnl TODO this may be fixed in LLVM 20.x via https://github.com/llvm/llvm-project/pull/120267.
-+      [-skip-funcs=_PyEval_EvalFrameDefault,sre_ucs1_match/1,sre_ucs2_match/1,sre_ucs4_match/1]
-+    ")]
-+  )
-+fi
-+
- AC_ARG_VAR(
-   [BOLT_INSTRUMENT_FLAGS],
-   [Arguments to llvm-bolt when instrumenting binaries]
-@@ -2111,7 +2132,7 @@ AC_ARG_VAR(
- AC_MSG_CHECKING([BOLT_INSTRUMENT_FLAGS])
- if test -z "${BOLT_INSTRUMENT_FLAGS}"
- then
--  BOLT_INSTRUMENT_FLAGS=
-+  BOLT_INSTRUMENT_FLAGS="${BOLT_COMMON_FLAGS}"
- fi
- AC_MSG_RESULT([$BOLT_INSTRUMENT_FLAGS])
- 
-@@ -2125,7 +2146,7 @@ then
-   AS_VAR_SET(
-     [BOLT_APPLY_FLAGS],
-     [m4_normalize("
--     -update-debug-sections
-+     ${BOLT_COMMON_FLAGS}
-      -reorder-blocks=ext-tsp
-      -reorder-functions=hfsort+
-      -split-functions
diff --git a/cpython-unix/patch-test-embed-prevent-segfault.patch b/cpython-unix/patch-test-embed-prevent-segfault.patch
index 4eac5b28..d05e2b00 100644
--- a/cpython-unix/patch-test-embed-prevent-segfault.patch
+++ b/cpython-unix/patch-test-embed-prevent-segfault.patch
@@ -10,11 +10,3 @@ index 13713cf37b8..40ee4837bfe 100644
      def test_global_pathconfig(self):
          # Test C API functions getting the path configuration:
          #
-@@ -1866,6 +1867,7 @@ def test_no_memleak(self):
-                 self.assertEqual(blocks, 0, out)
- 
- 
-+@unittest.skipIf(support.check_bolt_optimized, "segfaults on BOLT instrumented binaries")
- class StdPrinterTests(EmbeddingTestsMixin, unittest.TestCase):
-     # Test PyStdPrinter_Type which is used by _PySys_SetPreliminaryStderr():
-     #   "Set up a preliminary stderr printer until we have enough
diff --git a/pythonbuild/downloads.py b/pythonbuild/downloads.py
index 1e9a8ed8..0a723aa9 100644
--- a/pythonbuild/downloads.py
+++ b/pythonbuild/downloads.py
@@ -62,19 +62,19 @@
         "python_tag": "cp311",
     },
     "cpython-3.12": {
-        "url": "https://www.python.org/ftp/python/3.12.8/Python-3.12.8.tar.xz",
-        "size": 20489808,
-        "sha256": "c909157bb25ec114e5869124cc2a9c4a4d4c1e957ca4ff553f1edc692101154e",
-        "version": "3.12.8",
+        "url": "https://www.python.org/ftp/python/3.12.9/Python-3.12.9.tar.xz",
+        "size": 20502440,
+        "sha256": "7220835d9f90b37c006e9842a8dff4580aaca4318674f947302b8d28f3f81112",
+        "version": "3.12.9",
         "licenses": ["Python-2.0", "CNRI-Python"],
         "license_file": "LICENSE.cpython.txt",
         "python_tag": "cp312",
     },
     "cpython-3.13": {
-        "url": "https://www.python.org/ftp/python/3.13.1/Python-3.13.1.tar.xz",
-        "size": 22589692,
-        "sha256": "9cf9427bee9e2242e3877dd0f6b641c1853ca461f39d6503ce260a59c80bf0d9",
-        "version": "3.13.1",
+        "url": "https://www.python.org/ftp/python/3.13.2/Python-3.13.2.tar.xz",
+        "size": 22621108,
+        "sha256": "d984bcc57cd67caab26f7def42e523b1c015bbc5dc07836cf4f0b63fa159eb56",
+        "version": "3.13.2",
         "licenses": ["Python-2.0", "CNRI-Python"],
         "license_file": "LICENSE.cpython.txt",
         "python_tag": "cp313",

From 99c99ab2c4bd196243274398d199bb716f662e01 Mon Sep 17 00:00:00 2001
From: samypr100 <3933065+samypr100@users.noreply.github.com>
Date: Wed, 5 Feb 2025 19:18:49 -0400
Subject: [PATCH 041/157] fix: remove release attestations (#514)

See
https://github.com/astral-sh/python-build-standalone/actions/runs/13165689836/job/36745165697

This remove release attestations for now until problem with glob
resulting in no matches is identified
---
 .github/workflows/release.yml | 6 ------
 1 file changed, 6 deletions(-)

diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index cf58dc13..4f91719c 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -78,9 +78,3 @@ jobs:
       # Uploading the relevant artifact to the GitHub release.
       - run: just release-run ${{ secrets.GITHUB_TOKEN }} ${{ github.event.inputs.sha }} ${{ github.event.inputs.tag }}
         if: ${{ github.event.inputs.dry-run == 'false' }}
-
-      - name: Generate attestations
-        uses: actions/attest-build-provenance@v2
-        if: ${{ github.event.inputs.dry-run == 'false' }}
-        with:
-          subject-path: dist/*.tar.@(zst|gz)

From cab271cd7e1015d4dd1dfe71a9e8be823498b84d Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Wed, 5 Feb 2025 17:18:59 -0600
Subject: [PATCH 042/157] Bump openssl from 0.10.66 to 0.10.70 (#510)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Bumps [openssl](https://github.com/sfackler/rust-openssl) from 0.10.66
to 0.10.70.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/sfackler/rust-openssl/releases">openssl's
releases</a>.</em></p>
<blockquote>
<h2>openssl v0.10.70</h2>
<h2>What's Changed</h2>
<ul>
<li>Attempt to fix CI by pinning to the Ubuntu 22.04 image by <a
href="https://github.com/alex"><code>@​alex</code></a> in <a
href="https://redirect.github.com/sfackler/rust-openssl/pull/2357">sfackler/rust-openssl#2357</a></li>
<li>Remove EC_METHOD and EC_GROUP_new for LibreSSL 4.1 by <a
href="https://github.com/botovq"><code>@​botovq</code></a> in <a
href="https://redirect.github.com/sfackler/rust-openssl/pull/2356">sfackler/rust-openssl#2356</a></li>
<li>Test against 3.4.0 final release by <a
href="https://github.com/alex"><code>@​alex</code></a> in <a
href="https://redirect.github.com/sfackler/rust-openssl/pull/2359">sfackler/rust-openssl#2359</a></li>
<li>Expose <code>SslMethod::{dtls_client,dtls_server}</code> by <a
href="https://github.com/alex"><code>@​alex</code></a> in <a
href="https://redirect.github.com/sfackler/rust-openssl/pull/2358">sfackler/rust-openssl#2358</a></li>
<li>Fix lifetimes in ssl::select_next_proto by <a
href="https://github.com/sfackler"><code>@​sfackler</code></a> in <a
href="https://redirect.github.com/sfackler/rust-openssl/pull/2360">sfackler/rust-openssl#2360</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.69...openssl-v0.10.70">https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.69...openssl-v0.10.70</a></p>
<h2>openssl v0.10.69</h2>
<h2>What's Changed</h2>
<ul>
<li>build(deps): Update <code>openssl-macro</code> to version
<code>0.1.1</code> by <a
href="https://github.com/caspermeijn"><code>@​caspermeijn</code></a> in
<a
href="https://redirect.github.com/sfackler/rust-openssl/pull/2324">sfackler/rust-openssl#2324</a></li>
<li>Enable set_alpn_select_callback for BoringSSL by <a
href="https://github.com/ViktoriiaKovalova"><code>@​ViktoriiaKovalova</code></a>
in <a
href="https://redirect.github.com/sfackler/rust-openssl/pull/2327">sfackler/rust-openssl#2327</a></li>
<li>Switch the test to use prime256v1 based key by <a
href="https://github.com/dcermak"><code>@​dcermak</code></a> in <a
href="https://redirect.github.com/sfackler/rust-openssl/pull/2330">sfackler/rust-openssl#2330</a></li>
<li>Expose EVP_DigestSqueeze from Hasher by <a
href="https://github.com/initsecret"><code>@​initsecret</code></a> in <a
href="https://redirect.github.com/sfackler/rust-openssl/pull/2275">sfackler/rust-openssl#2275</a></li>
<li>Expose SSL_CTX_load_verify_locations by <a
href="https://github.com/sfackler"><code>@​sfackler</code></a> in <a
href="https://redirect.github.com/sfackler/rust-openssl/pull/2353">sfackler/rust-openssl#2353</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a
href="https://github.com/caspermeijn"><code>@​caspermeijn</code></a>
made their first contribution in <a
href="https://redirect.github.com/sfackler/rust-openssl/pull/2324">sfackler/rust-openssl#2324</a></li>
<li><a
href="https://github.com/ViktoriiaKovalova"><code>@​ViktoriiaKovalova</code></a>
made their first contribution in <a
href="https://redirect.github.com/sfackler/rust-openssl/pull/2327">sfackler/rust-openssl#2327</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.68...openssl-v0.10.69">https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.68...openssl-v0.10.69</a></p>
<h2>openssl-v0.10.68</h2>
<h2>What's Changed</h2>
<ul>
<li>fixes <a
href="https://redirect.github.com/sfackler/rust-openssl/issues/2317">#2317</a>
-- restore compatibility with our MSRV and release openssl 0.9.68 by <a
href="https://github.com/alex"><code>@​alex</code></a> in <a
href="https://redirect.github.com/sfackler/rust-openssl/pull/2318">sfackler/rust-openssl#2318</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.67...openssl-v0.10.68">https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.67...openssl-v0.10.68</a></p>
<h2>openssl-v0.10.67</h2>
<h2>What's Changed</h2>
<ul>
<li>Added a utility function to ensure we never have an issue with
0-length slices from pointers again by <a
href="https://github.com/alex"><code>@​alex</code></a> in <a
href="https://redirect.github.com/sfackler/rust-openssl/pull/2268">sfackler/rust-openssl#2268</a></li>
<li>Fix CI for the latest rustc by <a
href="https://github.com/alex"><code>@​alex</code></a> in <a
href="https://redirect.github.com/sfackler/rust-openssl/pull/2271">sfackler/rust-openssl#2271</a></li>
<li>Add binding for EVP_DigestSqueeze by <a
href="https://github.com/initsecret"><code>@​initsecret</code></a> in <a
href="https://redirect.github.com/sfackler/rust-openssl/pull/2270">sfackler/rust-openssl#2270</a></li>
<li>libressl 4.0: const correctness for X509_LOOKUP_METHOD by <a
href="https://github.com/botovq"><code>@​botovq</code></a> in <a
href="https://redirect.github.com/sfackler/rust-openssl/pull/2276">sfackler/rust-openssl#2276</a></li>
<li>Bump hex dev-dependency version by <a
href="https://github.com/alex"><code>@​alex</code></a> in <a
href="https://redirect.github.com/sfackler/rust-openssl/pull/2277">sfackler/rust-openssl#2277</a></li>
<li>Raise bindgen version by <a
href="https://github.com/alex"><code>@​alex</code></a> in <a
href="https://redirect.github.com/sfackler/rust-openssl/pull/2278">sfackler/rust-openssl#2278</a></li>
<li>Ensure Rsa::check_key doesn't leave errors on the stack by <a
href="https://github.com/alex"><code>@​alex</code></a> in <a
href="https://redirect.github.com/sfackler/rust-openssl/pull/2279">sfackler/rust-openssl#2279</a></li>
<li>Update some docs to use the corresponds macro by <a
href="https://github.com/rushilmehra"><code>@​rushilmehra</code></a> in
<a
href="https://redirect.github.com/sfackler/rust-openssl/pull/2282">sfackler/rust-openssl#2282</a></li>
<li>Don't leave errors on the stack in
<code>MdCtxRef::digest_verify_final</code> by <a
href="https://github.com/alex"><code>@​alex</code></a> in <a
href="https://redirect.github.com/sfackler/rust-openssl/pull/2283">sfackler/rust-openssl#2283</a></li>
<li>Adjustments for LibreSSL 4 by <a
href="https://github.com/botovq"><code>@​botovq</code></a> in <a
href="https://redirect.github.com/sfackler/rust-openssl/pull/2287">sfackler/rust-openssl#2287</a></li>
<li>Explicit rustfmt config by <a
href="https://github.com/kornelski"><code>@​kornelski</code></a> in <a
href="https://redirect.github.com/sfackler/rust-openssl/pull/2285">sfackler/rust-openssl#2285</a></li>
<li>add basic EVP_KDF bindings by <a
href="https://github.com/reaperhulk"><code>@​reaperhulk</code></a> in <a
href="https://redirect.github.com/sfackler/rust-openssl/pull/2289">sfackler/rust-openssl#2289</a></li>
<li>add ossl3 thread pool bindings by <a
href="https://github.com/reaperhulk"><code>@​reaperhulk</code></a> in <a
href="https://redirect.github.com/sfackler/rust-openssl/pull/2293">sfackler/rust-openssl#2293</a></li>
<li>add argon2id support for ossl 3.2+ by <a
href="https://github.com/reaperhulk"><code>@​reaperhulk</code></a> in <a
href="https://redirect.github.com/sfackler/rust-openssl/pull/2290">sfackler/rust-openssl#2290</a></li>
<li>fix 3.2.0 thread support and simplify by <a
href="https://github.com/reaperhulk"><code>@​reaperhulk</code></a> in <a
href="https://redirect.github.com/sfackler/rust-openssl/pull/2294">sfackler/rust-openssl#2294</a></li>
<li>add libctx arg to argon2id by <a
href="https://github.com/reaperhulk"><code>@​reaperhulk</code></a> in <a
href="https://redirect.github.com/sfackler/rust-openssl/pull/2295">sfackler/rust-openssl#2295</a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/sfackler/rust-openssl/commit/a4d399b0f1a3694cb2d1728edf74d318a3cac890"><code>a4d399b</code></a>
Release openssl v0.10.70</li>
<li><a
href="https://github.com/sfackler/rust-openssl/commit/c9a33e286023f92b869c5f157b349be15985a799"><code>c9a33e2</code></a>
Release openssl-sys v0.9.105</li>
<li><a
href="https://github.com/sfackler/rust-openssl/commit/f014afb230de4d77bc79dea60e7e58c2f47b60f2"><code>f014afb</code></a>
Merge pull request <a
href="https://redirect.github.com/sfackler/rust-openssl/issues/2360">#2360</a>
from sfackler/fix-alpn-lifetimes</li>
<li><a
href="https://github.com/sfackler/rust-openssl/commit/8e6e30bbf7e7627845b801f83a3810d6ffc1f157"><code>8e6e30b</code></a>
Fix lifetimes in ssl::select_next_proto</li>
<li><a
href="https://github.com/sfackler/rust-openssl/commit/1aff2801ca1dd756a0566a4d4fa9a00967280114"><code>1aff280</code></a>
Merge pull request <a
href="https://redirect.github.com/sfackler/rust-openssl/issues/2358">#2358</a>
from alex/expose-dlts</li>
<li><a
href="https://github.com/sfackler/rust-openssl/commit/16ca5b278b99bb667321b4d88da230ee8f820e08"><code>16ca5b2</code></a>
Merge pull request <a
href="https://redirect.github.com/sfackler/rust-openssl/issues/2359">#2359</a>
from sfackler/alex-patch-1</li>
<li><a
href="https://github.com/sfackler/rust-openssl/commit/4c9fbb0c18e8a3ac1de9671d7828862b49c1cb87"><code>4c9fbb0</code></a>
Test against 3.4.0 final release</li>
<li><a
href="https://github.com/sfackler/rust-openssl/commit/5ecb31d3fd252c54dbae5e0b5b7ad495b26ac339"><code>5ecb31d</code></a>
Update openssl/src/ssl/mod.rs</li>
<li><a
href="https://github.com/sfackler/rust-openssl/commit/4830f5bb93dafeeeddf32bf41dda83e2560f3d49"><code>4830f5b</code></a>
Expose <code>SslMethod::{dtls_client,dtls_server}</code></li>
<li><a
href="https://github.com/sfackler/rust-openssl/commit/bab03c4093ef626c9564354ae7c2484f4f9ad6a9"><code>bab03c4</code></a>
Merge pull request <a
href="https://redirect.github.com/sfackler/rust-openssl/issues/2356">#2356</a>
from botovq/rm-ec-method</li>
<li>Additional commits viewable in <a
href="https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.66...openssl-v0.10.70">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=openssl&package-manager=cargo&previous-version=0.10.66&new-version=0.10.70)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/astral-sh/python-build-standalone/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
 Cargo.lock | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 70bd4f01..0c44c4b5 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1155,9 +1155,9 @@ checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
 
 [[package]]
 name = "openssl"
-version = "0.10.66"
+version = "0.10.70"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1"
+checksum = "61cfb4e166a8bb8c9b55c500bc2308550148ece889be90f609377e58140f42c6"
 dependencies = [
  "bitflags 2.4.2",
  "cfg-if",
@@ -1187,9 +1187,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
 
 [[package]]
 name = "openssl-sys"
-version = "0.9.103"
+version = "0.9.105"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6"
+checksum = "8b22d5b84be05a8d6947c7cb71f7c849aa0f112acd4bf51c2a7c1c988ac0a9dc"
 dependencies = [
  "cc",
  "libc",

From 5fccb2973c0573eb9e6692b8fd7cc395f37744af Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Thu, 6 Feb 2025 11:02:16 -0600
Subject: [PATCH 043/157] Run `cargo update` (#515)

---
 Cargo.lock | 1171 +++++++++++++++++++++++++++++++---------------------
 1 file changed, 704 insertions(+), 467 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 0c44c4b5..3b391954 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -4,18 +4,18 @@ version = 4
 
 [[package]]
 name = "addr2line"
-version = "0.21.0"
+version = "0.24.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb"
+checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1"
 dependencies = [
  "gimli",
 ]
 
 [[package]]
-name = "adler"
-version = "1.0.2"
+name = "adler2"
+version = "2.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
+checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
 
 [[package]]
 name = "aes"
@@ -45,57 +45,59 @@ dependencies = [
 
 [[package]]
 name = "anstream"
-version = "0.6.12"
+version = "0.6.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "96b09b5178381e0874812a9b157f7fe84982617e48f71f4e3235482775e5b540"
+checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b"
 dependencies = [
  "anstyle",
  "anstyle-parse",
  "anstyle-query",
  "anstyle-wincon",
  "colorchoice",
+ "is_terminal_polyfill",
  "utf8parse",
 ]
 
 [[package]]
 name = "anstyle"
-version = "1.0.6"
+version = "1.0.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc"
+checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9"
 
 [[package]]
 name = "anstyle-parse"
-version = "0.2.3"
+version = "0.2.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c"
+checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9"
 dependencies = [
  "utf8parse",
 ]
 
 [[package]]
 name = "anstyle-query"
-version = "1.0.2"
+version = "1.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648"
+checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c"
 dependencies = [
- "windows-sys 0.52.0",
+ "windows-sys 0.59.0",
 ]
 
 [[package]]
 name = "anstyle-wincon"
-version = "3.0.2"
+version = "3.0.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7"
+checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e"
 dependencies = [
  "anstyle",
- "windows-sys 0.52.0",
+ "once_cell",
+ "windows-sys 0.59.0",
 ]
 
 [[package]]
 name = "anyhow"
-version = "1.0.80"
+version = "1.0.95"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5ad32ce52e4161730f7098c077cd2ed6229b5804ccf99e5366be1ab72a98b4e1"
+checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04"
 
 [[package]]
 name = "apple-sdk"
@@ -110,19 +112,19 @@ dependencies = [
 
 [[package]]
 name = "arc-swap"
-version = "1.6.0"
+version = "1.7.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bddcadddf5e9015d310179a59bb28c4d4b9920ad0f11e8e14dbadf654890c9a6"
+checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457"
 
 [[package]]
 name = "async-trait"
-version = "0.1.77"
+version = "0.1.86"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9"
+checksum = "644dd749086bf3771a2fbc5f256fdb982d53f011c7d5d560304eafeecebce79d"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.95",
+ "syn",
 ]
 
 [[package]]
@@ -133,23 +135,23 @@ checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0"
 
 [[package]]
 name = "autocfg"
-version = "1.1.0"
+version = "1.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
+checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
 
 [[package]]
 name = "backtrace"
-version = "0.3.69"
+version = "0.3.74"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837"
+checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a"
 dependencies = [
  "addr2line",
- "cc",
  "cfg-if",
  "libc",
  "miniz_oxide",
- "object",
+ "object 0.36.7",
  "rustc-demangle",
+ "windows-targets",
 ]
 
 [[package]]
@@ -178,9 +180,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
 
 [[package]]
 name = "bitflags"
-version = "2.4.2"
+version = "2.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf"
+checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36"
 
 [[package]]
 name = "block-buffer"
@@ -193,9 +195,9 @@ dependencies = [
 
 [[package]]
 name = "bumpalo"
-version = "3.15.3"
+version = "3.17.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8ea184aa71bb362a1157c896979544cc23974e08fd265f29ea96b59f0b4a555b"
+checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf"
 
 [[package]]
 name = "byteorder"
@@ -205,9 +207,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
 
 [[package]]
 name = "bytes"
-version = "1.9.0"
+version = "1.10.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b"
+checksum = "f61dac84819c6588b558454b194026eb1f09c293b9036ae9b159e74e73ab6cf9"
 
 [[package]]
 name = "bzip2"
@@ -232,11 +234,13 @@ dependencies = [
 
 [[package]]
 name = "cc"
-version = "1.0.87"
+version = "1.2.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3286b845d0fccbdd15af433f61c5970e711987036cb468f437ff6badd70f4e24"
+checksum = "755717a7de9ec452bf7f3f1a3099085deabd7f2962b861dae91ecd7a365903d2"
 dependencies = [
+ "jobserver",
  "libc",
+ "shlex",
 ]
 
 [[package]]
@@ -253,15 +257,15 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
 
 [[package]]
 name = "chrono"
-version = "0.4.34"
+version = "0.4.39"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5bc015644b92d5890fab7489e49d21f879d5c990186827d42ec511919404f38b"
+checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825"
 dependencies = [
  "android-tzdata",
  "iana-time-zone",
  "num-traits",
  "serde",
- "windows-targets 0.52.6",
+ "windows-targets",
 ]
 
 [[package]]
@@ -276,18 +280,18 @@ dependencies = [
 
 [[package]]
 name = "clap"
-version = "4.5.1"
+version = "4.5.28"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c918d541ef2913577a0f9566e9ce27cb35b6df072075769e0b26cb5a554520da"
+checksum = "3e77c3243bd94243c03672cb5154667347c457ca271254724f9f393aee1c05ff"
 dependencies = [
  "clap_builder",
 ]
 
 [[package]]
 name = "clap_builder"
-version = "4.5.1"
+version = "4.5.27"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9f3e7391dad68afb0c2ede1bf619f579a3dc9c2ec67f089baa397123a2f3d1eb"
+checksum = "1b26884eb4b57140e4d2d93652abfa49498b938b3c9179f9fc487b0acc3edad7"
 dependencies = [
  "anstream",
  "anstyle",
@@ -297,15 +301,15 @@ dependencies = [
 
 [[package]]
 name = "clap_lex"
-version = "0.7.0"
+version = "0.7.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce"
+checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6"
 
 [[package]]
 name = "colorchoice"
-version = "1.0.0"
+version = "1.0.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
+checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
 
 [[package]]
 name = "constant_time_eq"
@@ -325,33 +329,33 @@ dependencies = [
 
 [[package]]
 name = "core-foundation-sys"
-version = "0.8.6"
+version = "0.8.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f"
+checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
 
 [[package]]
 name = "cpufeatures"
-version = "0.2.12"
+version = "0.2.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504"
+checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280"
 dependencies = [
  "libc",
 ]
 
 [[package]]
 name = "crc32fast"
-version = "1.4.0"
+version = "1.4.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa"
+checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3"
 dependencies = [
  "cfg-if",
 ]
 
 [[package]]
 name = "crossbeam-deque"
-version = "0.8.5"
+version = "0.8.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d"
+checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51"
 dependencies = [
  "crossbeam-epoch",
  "crossbeam-utils",
@@ -368,9 +372,9 @@ dependencies = [
 
 [[package]]
 name = "crossbeam-utils"
-version = "0.8.19"
+version = "0.8.21"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345"
+checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
 
 [[package]]
 name = "crypto-common"
@@ -393,13 +397,13 @@ dependencies = [
 
 [[package]]
 name = "derive_more"
-version = "0.99.17"
+version = "0.99.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321"
+checksum = "3da29a38df43d6f156149c9b43ded5e018ddff2a855cf2cfd62e8cd7d079c69f"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 1.0.109",
+ "syn",
 ]
 
 [[package]]
@@ -414,10 +418,15 @@ dependencies = [
 ]
 
 [[package]]
-name = "doc-comment"
-version = "0.3.3"
+name = "displaydoc"
+version = "0.2.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10"
+checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
 
 [[package]]
 name = "duct"
@@ -433,15 +442,15 @@ dependencies = [
 
 [[package]]
 name = "either"
-version = "1.10.0"
+version = "1.13.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a"
+checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
 
 [[package]]
 name = "encoding_rs"
-version = "0.8.33"
+version = "0.8.35"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1"
+checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3"
 dependencies = [
  "cfg-if",
 ]
@@ -454,12 +463,12 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
 
 [[package]]
 name = "errno"
-version = "0.3.8"
+version = "0.3.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245"
+checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d"
 dependencies = [
  "libc",
- "windows-sys 0.52.0",
+ "windows-sys 0.59.0",
 ]
 
 [[package]]
@@ -470,27 +479,27 @@ checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7"
 
 [[package]]
 name = "fastrand"
-version = "2.0.1"
+version = "2.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5"
+checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
 
 [[package]]
 name = "filetime"
-version = "0.2.23"
+version = "0.2.25"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd"
+checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586"
 dependencies = [
  "cfg-if",
  "libc",
- "redox_syscall 0.4.1",
- "windows-sys 0.52.0",
+ "libredox",
+ "windows-sys 0.59.0",
 ]
 
 [[package]]
 name = "flate2"
-version = "1.0.28"
+version = "1.0.35"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e"
+checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c"
 dependencies = [
  "crc32fast",
  "miniz_oxide",
@@ -528,9 +537,9 @@ dependencies = [
 
 [[package]]
 name = "futures"
-version = "0.3.30"
+version = "0.3.31"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0"
+checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876"
 dependencies = [
  "futures-channel",
  "futures-core",
@@ -543,9 +552,9 @@ dependencies = [
 
 [[package]]
 name = "futures-channel"
-version = "0.3.30"
+version = "0.3.31"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78"
+checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10"
 dependencies = [
  "futures-core",
  "futures-sink",
@@ -553,15 +562,15 @@ dependencies = [
 
 [[package]]
 name = "futures-core"
-version = "0.3.30"
+version = "0.3.31"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d"
+checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e"
 
 [[package]]
 name = "futures-executor"
-version = "0.3.30"
+version = "0.3.31"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d"
+checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f"
 dependencies = [
  "futures-core",
  "futures-task",
@@ -570,38 +579,38 @@ dependencies = [
 
 [[package]]
 name = "futures-io"
-version = "0.3.30"
+version = "0.3.31"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1"
+checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6"
 
 [[package]]
 name = "futures-macro"
-version = "0.3.30"
+version = "0.3.31"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
+checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.95",
+ "syn",
 ]
 
 [[package]]
 name = "futures-sink"
-version = "0.3.30"
+version = "0.3.31"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5"
+checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7"
 
 [[package]]
 name = "futures-task"
-version = "0.3.30"
+version = "0.3.31"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004"
+checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988"
 
 [[package]]
 name = "futures-util"
-version = "0.3.30"
+version = "0.3.31"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48"
+checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81"
 dependencies = [
  "futures-channel",
  "futures-core",
@@ -627,28 +636,40 @@ dependencies = [
 
 [[package]]
 name = "getrandom"
-version = "0.2.12"
+version = "0.2.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5"
+checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
 dependencies = [
  "cfg-if",
  "js-sys",
  "libc",
- "wasi",
+ "wasi 0.11.0+wasi-snapshot-preview1",
  "wasm-bindgen",
 ]
 
+[[package]]
+name = "getrandom"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "wasi 0.13.3+wasi-0.2.2",
+ "windows-targets",
+]
+
 [[package]]
 name = "gimli"
-version = "0.28.1"
+version = "0.31.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253"
+checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
 
 [[package]]
 name = "goblin"
-version = "0.8.0"
+version = "0.8.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bb07a4ffed2093b118a525b1d8f5204ae274faed5604537caf7135d0f18d9887"
+checksum = "1b363a30c165f666402fe6a3024d3bec7ebc898f96a4a23bd1c99f8dbf3f4f47"
 dependencies = [
  "log",
  "plain",
@@ -676,15 +697,15 @@ dependencies = [
 
 [[package]]
 name = "hashbrown"
-version = "0.14.3"
+version = "0.15.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
+checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289"
 
 [[package]]
 name = "heck"
-version = "0.4.1"
+version = "0.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
+checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
 
 [[package]]
 name = "hex"
@@ -703,9 +724,9 @@ dependencies = [
 
 [[package]]
 name = "http"
-version = "1.0.0"
+version = "1.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b32afd38673a8016f7c9ae69e5af41a58f81b1d31689040f2f1959594ce194ea"
+checksum = "f16ca2af56261c99fba8bac40a10251ce8188205a4c448fbb745a2e4daa76fea"
 dependencies = [
  "bytes",
  "fnv",
@@ -714,9 +735,9 @@ dependencies = [
 
 [[package]]
 name = "http-body"
-version = "1.0.0"
+version = "1.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643"
+checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184"
 dependencies = [
  "bytes",
  "http",
@@ -724,9 +745,9 @@ dependencies = [
 
 [[package]]
 name = "http-body-util"
-version = "0.1.0"
+version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "41cb79eb393015dadd30fc252023adb0b2400a0caee0fa2a077e6e21a551e840"
+checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f"
 dependencies = [
  "bytes",
  "futures-util",
@@ -737,15 +758,15 @@ dependencies = [
 
 [[package]]
 name = "httparse"
-version = "1.8.0"
+version = "1.10.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904"
+checksum = "f2d708df4e7140240a16cd6ab0ab65c972d7433ab77819ea693fde9c43811e2a"
 
 [[package]]
 name = "hyper"
-version = "1.5.2"
+version = "1.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "256fb8d4bd6413123cc9d91832d78325c48ff41677595be797d90f42969beae0"
+checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80"
 dependencies = [
  "bytes",
  "futures-channel",
@@ -772,7 +793,7 @@ dependencies = [
  "hyper",
  "hyper-util",
  "log",
- "rustls 0.22.2",
+ "rustls 0.22.4",
  "rustls-native-certs",
  "rustls-pki-types",
  "tokio",
@@ -790,7 +811,7 @@ dependencies = [
  "http",
  "hyper",
  "hyper-util",
- "rustls 0.23.21",
+ "rustls 0.23.22",
  "rustls-pki-types",
  "tokio",
  "tokio-rustls 0.26.1",
@@ -800,9 +821,9 @@ dependencies = [
 
 [[package]]
 name = "hyper-timeout"
-version = "0.5.1"
+version = "0.5.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3203a961e5c83b6f5498933e78b6b263e208c197b63e9c6c53cc82ffd3f63793"
+checksum = "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0"
 dependencies = [
  "hyper",
  "hyper-util",
@@ -848,9 +869,9 @@ dependencies = [
 
 [[package]]
 name = "iana-time-zone"
-version = "0.1.60"
+version = "0.1.61"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141"
+checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220"
 dependencies = [
  "android_system_properties",
  "core-foundation-sys",
@@ -869,21 +890,150 @@ dependencies = [
  "cc",
 ]
 
+[[package]]
+name = "icu_collections"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526"
+dependencies = [
+ "displaydoc",
+ "yoke",
+ "zerofrom",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_locid"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637"
+dependencies = [
+ "displaydoc",
+ "litemap",
+ "tinystr",
+ "writeable",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_locid_transform"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e"
+dependencies = [
+ "displaydoc",
+ "icu_locid",
+ "icu_locid_transform_data",
+ "icu_provider",
+ "tinystr",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_locid_transform_data"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e"
+
+[[package]]
+name = "icu_normalizer"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f"
+dependencies = [
+ "displaydoc",
+ "icu_collections",
+ "icu_normalizer_data",
+ "icu_properties",
+ "icu_provider",
+ "smallvec",
+ "utf16_iter",
+ "utf8_iter",
+ "write16",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_normalizer_data"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516"
+
+[[package]]
+name = "icu_properties"
+version = "1.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5"
+dependencies = [
+ "displaydoc",
+ "icu_collections",
+ "icu_locid_transform",
+ "icu_properties_data",
+ "icu_provider",
+ "tinystr",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_properties_data"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569"
+
+[[package]]
+name = "icu_provider"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9"
+dependencies = [
+ "displaydoc",
+ "icu_locid",
+ "icu_provider_macros",
+ "stable_deref_trait",
+ "tinystr",
+ "writeable",
+ "yoke",
+ "zerofrom",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_provider_macros"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
 [[package]]
 name = "idna"
-version = "0.5.0"
+version = "1.0.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6"
+checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e"
 dependencies = [
- "unicode-bidi",
- "unicode-normalization",
+ "idna_adapter",
+ "smallvec",
+ "utf8_iter",
+]
+
+[[package]]
+name = "idna_adapter"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71"
+dependencies = [
+ "icu_normalizer",
+ "icu_properties",
 ]
 
 [[package]]
 name = "indexmap"
-version = "2.2.3"
+version = "2.7.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "233cf39063f058ea2caae4091bf4a3ef70a653afbc026f5c4a4135d114e3c177"
+checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652"
 dependencies = [
  "equivalent",
  "hashbrown",
@@ -912,40 +1062,56 @@ dependencies = [
 
 [[package]]
 name = "ipnet"
-version = "2.9.0"
+version = "2.11.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3"
+checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130"
 
 [[package]]
 name = "iri-string"
-version = "0.7.0"
+version = "0.7.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "21859b667d66a4c1dacd9df0863b3efb65785474255face87f5bca39dd8407c0"
+checksum = "dc0f0a572e8ffe56e2ff4f769f32ffe919282c3916799f8b68688b6030063bea"
 dependencies = [
  "memchr",
  "serde",
 ]
 
+[[package]]
+name = "is_terminal_polyfill"
+version = "1.70.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
+
 [[package]]
 name = "itoa"
-version = "1.0.10"
+version = "1.0.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674"
+
+[[package]]
+name = "jobserver"
+version = "0.1.32"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c"
+checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0"
+dependencies = [
+ "libc",
+]
 
 [[package]]
 name = "js-sys"
-version = "0.3.68"
+version = "0.3.77"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "406cda4b368d531c842222cf9d2600a9a4acce8d29423695379c6868a143a9ee"
+checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f"
 dependencies = [
+ "once_cell",
  "wasm-bindgen",
 ]
 
 [[package]]
 name = "jsonwebtoken"
-version = "9.2.0"
+version = "9.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5c7ea04a7c5c055c175f189b6dc6ba036fd62306b58c66c9f6389036c503a3f4"
+checksum = "b9ae10193d25051e74945f1ea2d0b42e03cc3b890f7e4cc5faa44997d808193f"
 dependencies = [
  "base64 0.21.7",
  "js-sys",
@@ -956,12 +1122,6 @@ dependencies = [
  "simple_asn1",
 ]
 
-[[package]]
-name = "lazy_static"
-version = "1.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
-
 [[package]]
 name = "libc"
 version = "0.2.169"
@@ -969,12 +1129,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a"
 
 [[package]]
-name = "line-wrap"
-version = "0.1.1"
+name = "libredox"
+version = "0.1.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f30344350a2a51da54c1d53be93fade8a237e545dbcc4bdbe635413f2117cab9"
+checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d"
 dependencies = [
- "safemem",
+ "bitflags 2.8.0",
+ "libc",
+ "redox_syscall 0.5.8",
 ]
 
 [[package]]
@@ -985,9 +1147,15 @@ checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
 
 [[package]]
 name = "linux-raw-sys"
-version = "0.4.13"
+version = "0.4.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab"
+
+[[package]]
+name = "litemap"
+version = "0.7.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c"
+checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104"
 
 [[package]]
 name = "lock_api"
@@ -1001,15 +1169,15 @@ dependencies = [
 
 [[package]]
 name = "log"
-version = "0.4.20"
+version = "0.4.25"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
+checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f"
 
 [[package]]
 name = "memchr"
-version = "2.7.1"
+version = "2.7.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149"
+checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
 
 [[package]]
 name = "mime"
@@ -1019,31 +1187,30 @@ checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
 
 [[package]]
 name = "miniz_oxide"
-version = "0.7.2"
+version = "0.8.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7"
+checksum = "b8402cab7aefae129c6977bb0ff1b8fd9a04eb5b51efc50a70bea51cda0c7924"
 dependencies = [
- "adler",
+ "adler2",
 ]
 
 [[package]]
 name = "mio"
-version = "0.8.11"
+version = "1.0.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c"
+checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd"
 dependencies = [
  "libc",
- "wasi",
- "windows-sys 0.48.0",
+ "wasi 0.11.0+wasi-snapshot-preview1",
+ "windows-sys 0.52.0",
 ]
 
 [[package]]
 name = "native-tls"
-version = "0.2.11"
+version = "0.2.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e"
+checksum = "0dab59f8e050d5df8e4dd87d9206fb6f65a483e20ac9fda365ade4fab353196c"
 dependencies = [
- "lazy_static",
  "libc",
  "log",
  "openssl",
@@ -1063,11 +1230,10 @@ checksum = "f5438dd2b2ff4c6df6e1ce22d825ed2fa93ee2922235cc45186991717f0a892d"
 
 [[package]]
 name = "num-bigint"
-version = "0.4.4"
+version = "0.4.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0"
+checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9"
 dependencies = [
- "autocfg",
  "num-integer",
  "num-traits",
 ]
@@ -1089,9 +1255,9 @@ dependencies = [
 
 [[package]]
 name = "num-traits"
-version = "0.2.18"
+version = "0.2.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a"
+checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
 dependencies = [
  "autocfg",
 ]
@@ -1107,15 +1273,24 @@ dependencies = [
  "ruzstd",
 ]
 
+[[package]]
+name = "object"
+version = "0.36.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87"
+dependencies = [
+ "memchr",
+]
+
 [[package]]
 name = "octocrab"
-version = "0.34.1"
+version = "0.34.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9fc61913d67d5ed8e04b55c611ec7450ab811f83aa424f3bd00782c6b0296ae7"
+checksum = "1c4e00a4268539fda6c431a0fd01d016d4b44c361f9c283d0eb8f1ab7408a517"
 dependencies = [
  "arc-swap",
  "async-trait",
- "base64 0.21.7",
+ "base64 0.22.1",
  "bytes",
  "cfg-if",
  "chrono",
@@ -1149,9 +1324,9 @@ dependencies = [
 
 [[package]]
 name = "once_cell"
-version = "1.19.0"
+version = "1.20.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
+checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
 
 [[package]]
 name = "openssl"
@@ -1159,7 +1334,7 @@ version = "0.10.70"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "61cfb4e166a8bb8c9b55c500bc2308550148ece889be90f609377e58140f42c6"
 dependencies = [
- "bitflags 2.4.2",
+ "bitflags 2.8.0",
  "cfg-if",
  "foreign-types",
  "libc",
@@ -1176,14 +1351,14 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.95",
+ "syn",
 ]
 
 [[package]]
 name = "openssl-probe"
-version = "0.1.5"
+version = "0.1.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
+checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e"
 
 [[package]]
 name = "openssl-sys"
@@ -1199,12 +1374,12 @@ dependencies = [
 
 [[package]]
 name = "os_pipe"
-version = "1.1.5"
+version = "1.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "57119c3b893986491ec9aa85056780d3a0f3cf4da7cc09dd3650dbd6c6738fb9"
+checksum = "5ffd2b0a5634335b135d5728d84c5e0fd726954b87111f7506a61c502280d982"
 dependencies = [
  "libc",
- "windows-sys 0.52.0",
+ "windows-sys 0.59.0",
 ]
 
 [[package]]
@@ -1268,11 +1443,11 @@ dependencies = [
 
 [[package]]
 name = "pem"
-version = "3.0.3"
+version = "3.0.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1b8fcc794035347fb64beda2d3b462595dd2753e3f268d89c5aae77e8cf2c310"
+checksum = "8e459365e590736a54c3fa561947c84837534b8e9af6fc5bf781307e82658fae"
 dependencies = [
- "base64 0.21.7",
+ "base64 0.22.1",
  "serde",
 ]
 
@@ -1295,29 +1470,29 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
 
 [[package]]
 name = "pin-project"
-version = "1.1.4"
+version = "1.1.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0302c4a0442c456bd56f841aee5c3bfd17967563f6fadc9ceb9f9c23cf3807e0"
+checksum = "dfe2e71e1471fe07709406bf725f710b02927c9c54b2b5b2ec0e8087d97c327d"
 dependencies = [
  "pin-project-internal",
 ]
 
 [[package]]
 name = "pin-project-internal"
-version = "1.1.4"
+version = "1.1.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "266c042b60c9c76b8d53061e52b2e0d1116abc57cefc8c5cd671619a56ac3690"
+checksum = "f6e859e6e5bd50440ab63c47e3ebabc90f26251f7c73c3d3e837b74a1cc3fa67"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.95",
+ "syn",
 ]
 
 [[package]]
 name = "pin-project-lite"
-version = "0.2.13"
+version = "0.2.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58"
+checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b"
 
 [[package]]
 name = "pin-utils"
@@ -1327,9 +1502,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
 
 [[package]]
 name = "pkg-config"
-version = "0.3.30"
+version = "0.3.31"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec"
+checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2"
 
 [[package]]
 name = "plain"
@@ -1339,13 +1514,12 @@ checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6"
 
 [[package]]
 name = "plist"
-version = "1.6.0"
+version = "1.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e5699cc8a63d1aa2b1ee8e12b9ad70ac790d65788cd36101fa37f87ea46c4cef"
+checksum = "42cf17e9a1800f5f396bc67d193dc9411b59012a5876445ef450d449881e1016"
 dependencies = [
- "base64 0.21.7",
+ "base64 0.22.1",
  "indexmap",
- "line-wrap",
  "quick-xml",
  "serde",
  "time",
@@ -1368,9 +1542,9 @@ dependencies = [
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.92"
+version = "1.0.93"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0"
+checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99"
 dependencies = [
  "unicode-ident",
 ]
@@ -1393,7 +1567,7 @@ dependencies = [
  "hyper",
  "hyper-util",
  "normalize-path",
- "object",
+ "object 0.32.2",
  "octocrab",
  "once_cell",
  "pdb",
@@ -1414,14 +1588,14 @@ dependencies = [
  "url",
  "version-compare",
  "zip",
- "zstd 0.13.0",
+ "zstd 0.13.2",
 ]
 
 [[package]]
 name = "quick-xml"
-version = "0.31.0"
+version = "0.32.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1004a344b30a54e2ee58d66a71b32d2db2feb0a31f9a2d302bf0536f15de2a33"
+checksum = "1d3a6e5838b60e0e8fa7a43f22ade549a37d61f8bdbe636d0d7816191de969c2"
 dependencies = [
  "memchr",
 ]
@@ -1437,7 +1611,7 @@ dependencies = [
  "quinn-proto",
  "quinn-udp",
  "rustc-hash",
- "rustls 0.23.21",
+ "rustls 0.23.22",
  "socket2",
  "thiserror 2.0.11",
  "tokio",
@@ -1451,11 +1625,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "a2fe5ef3495d7d2e377ff17b1a8ce2ee2ec2a18cde8b6ad6619d65d0701c135d"
 dependencies = [
  "bytes",
- "getrandom",
+ "getrandom 0.2.15",
  "rand",
  "ring",
  "rustc-hash",
- "rustls 0.23.21",
+ "rustls 0.23.22",
  "rustls-pki-types",
  "slab",
  "thiserror 2.0.11",
@@ -1475,14 +1649,14 @@ dependencies = [
  "once_cell",
  "socket2",
  "tracing",
- "windows-sys 0.52.0",
+ "windows-sys 0.59.0",
 ]
 
 [[package]]
 name = "quote"
-version = "1.0.35"
+version = "1.0.38"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
+checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc"
 dependencies = [
  "proc-macro2",
 ]
@@ -1514,14 +1688,14 @@ version = "0.6.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
 dependencies = [
- "getrandom",
+ "getrandom 0.2.15",
 ]
 
 [[package]]
 name = "rayon"
-version = "1.8.1"
+version = "1.10.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fa7237101a77a10773db45d62004a272517633fbcc3df19d96455ede1122e051"
+checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa"
 dependencies = [
  "either",
  "rayon-core",
@@ -1548,11 +1722,11 @@ dependencies = [
 
 [[package]]
 name = "redox_syscall"
-version = "0.4.1"
+version = "0.5.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"
+checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834"
 dependencies = [
- "bitflags 1.3.2",
+ "bitflags 2.8.0",
 ]
 
 [[package]]
@@ -1583,7 +1757,7 @@ dependencies = [
  "percent-encoding",
  "pin-project-lite",
  "quinn",
- "rustls 0.23.21",
+ "rustls 0.23.22",
  "rustls-pemfile",
  "rustls-pki-types",
  "serde",
@@ -1630,7 +1804,7 @@ dependencies = [
  "anyhow",
  "async-trait",
  "futures",
- "getrandom",
+ "getrandom 0.2.15",
  "http",
  "hyper",
  "parking_lot",
@@ -1660,7 +1834,7 @@ checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d"
 dependencies = [
  "cc",
  "cfg-if",
- "getrandom",
+ "getrandom 0.2.15",
  "libc",
  "spin",
  "untrusted",
@@ -1669,34 +1843,34 @@ dependencies = [
 
 [[package]]
 name = "rustc-demangle"
-version = "0.1.23"
+version = "0.1.24"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
+checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
 
 [[package]]
 name = "rustc-hash"
-version = "2.1.0"
+version = "2.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c7fb8039b3032c191086b10f11f319a6e99e1e82889c5cc6046f515c9db1d497"
+checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d"
 
 [[package]]
 name = "rustix"
-version = "0.38.31"
+version = "0.38.44"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949"
+checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154"
 dependencies = [
- "bitflags 2.4.2",
+ "bitflags 2.8.0",
  "errno",
  "libc",
  "linux-raw-sys",
- "windows-sys 0.52.0",
+ "windows-sys 0.59.0",
 ]
 
 [[package]]
 name = "rustls"
-version = "0.22.2"
+version = "0.22.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e87c9956bd9807afa1f77e0f7594af32566e830e088a5576d27c5b6f30f49d41"
+checksum = "bf4ef73721ac7bcd79b2b315da7779d8fc09718c6b3d2d1b2d94850eb8c18432"
 dependencies = [
  "log",
  "ring",
@@ -1708,9 +1882,9 @@ dependencies = [
 
 [[package]]
 name = "rustls"
-version = "0.23.21"
+version = "0.23.22"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8f287924602bf649d949c63dc8ac8b235fa5387d394020705b80c4eb597ce5b8"
+checksum = "9fb9263ab4eb695e42321db096e3b8fbd715a59b154d5c88d82db2175b681ba7"
 dependencies = [
  "once_cell",
  "ring",
@@ -1722,9 +1896,9 @@ dependencies = [
 
 [[package]]
 name = "rustls-native-certs"
-version = "0.7.0"
+version = "0.7.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8f1fb85efa936c42c6d5fc28d2629bb51e4b2f4b8a5211e297d599cc5a093792"
+checksum = "e5bfb394eeed242e909609f56089eecfe5fda225042e8b171791b9c95f5931e5"
 dependencies = [
  "openssl-probe",
  "rustls-pemfile",
@@ -1735,19 +1909,18 @@ dependencies = [
 
 [[package]]
 name = "rustls-pemfile"
-version = "2.1.0"
+version = "2.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3c333bb734fcdedcea57de1602543590f545f127dc8b533324318fd492c5c70b"
+checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50"
 dependencies = [
- "base64 0.21.7",
  "rustls-pki-types",
 ]
 
 [[package]]
 name = "rustls-pki-types"
-version = "1.10.1"
+version = "1.11.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d2bf47e6ff922db3825eb750c4e2ff784c6ff8fb9e13046ef6a1d1c5401b0b37"
+checksum = "917ce264624a4b4db1c364dcc35bfca9ded014d0a958cd47ad3e960e988ea51c"
 dependencies = [
  "web-time",
 ]
@@ -1763,6 +1936,12 @@ dependencies = [
  "untrusted",
 ]
 
+[[package]]
+name = "rustversion"
+version = "1.0.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4"
+
 [[package]]
 name = "ruzstd"
 version = "0.5.0"
@@ -1776,23 +1955,17 @@ dependencies = [
 
 [[package]]
 name = "ryu"
-version = "1.0.17"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1"
-
-[[package]]
-name = "safemem"
-version = "0.3.3"
+version = "1.0.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072"
+checksum = "6ea1a2d0a644769cc99faa24c3ad26b379b786fe7c36fd3c546254801650e6dd"
 
 [[package]]
 name = "schannel"
-version = "0.1.23"
+version = "0.1.27"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534"
+checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d"
 dependencies = [
- "windows-sys 0.52.0",
+ "windows-sys 0.59.0",
 ]
 
 [[package]]
@@ -1824,7 +1997,7 @@ checksum = "7f81c2fde025af7e69b1d1420531c8a8811ca898919db177141a85313b1cb932"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.95",
+ "syn",
 ]
 
 [[package]]
@@ -1838,11 +2011,11 @@ dependencies = [
 
 [[package]]
 name = "security-framework"
-version = "2.9.2"
+version = "2.11.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de"
+checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02"
 dependencies = [
- "bitflags 1.3.2",
+ "bitflags 2.8.0",
  "core-foundation",
  "core-foundation-sys",
  "libc",
@@ -1851,9 +2024,9 @@ dependencies = [
 
 [[package]]
 name = "security-framework-sys"
-version = "2.9.1"
+version = "2.14.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a"
+checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32"
 dependencies = [
  "core-foundation-sys",
  "libc",
@@ -1861,46 +2034,47 @@ dependencies = [
 
 [[package]]
 name = "semver"
-version = "1.0.22"
+version = "1.0.25"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca"
+checksum = "f79dfe2d285b0488816f30e700a7438c5a73d816b5b7d3ac72fbc48b0d185e03"
 
 [[package]]
 name = "serde"
-version = "1.0.197"
+version = "1.0.217"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2"
+checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70"
 dependencies = [
  "serde_derive",
 ]
 
 [[package]]
 name = "serde_derive"
-version = "1.0.197"
+version = "1.0.217"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b"
+checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.95",
+ "syn",
 ]
 
 [[package]]
 name = "serde_json"
-version = "1.0.114"
+version = "1.0.138"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0"
+checksum = "d434192e7da787e94a6ea7e9670b26a036d0ca41e0b7efb2676dd32bae872949"
 dependencies = [
  "itoa",
+ "memchr",
  "ryu",
  "serde",
 ]
 
 [[package]]
 name = "serde_path_to_error"
-version = "0.1.15"
+version = "0.1.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ebd154a240de39fdebcf5775d2675c204d7c13cf39a4c697be6493c8e734337c"
+checksum = "af99884400da37c88f5e9146b7f1fd0fbcae8f6eec4e9da38b67d05486f814a6"
 dependencies = [
  "itoa",
  "serde",
@@ -1920,9 +2094,9 @@ dependencies = [
 
 [[package]]
 name = "serde_yaml"
-version = "0.9.32"
+version = "0.9.34+deprecated"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8fd075d994154d4a774f95b51fb96bdc2832b0ea48425c92546073816cda1f2f"
+checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47"
 dependencies = [
  "indexmap",
  "itoa",
@@ -1955,23 +2129,29 @@ dependencies = [
 
 [[package]]
 name = "shared_child"
-version = "1.0.0"
+version = "1.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b0d94659ad3c2137fef23ae75b03d5241d633f8acded53d672decfa0e6e0caef"
+checksum = "09fa9338aed9a1df411814a5b2252f7cd206c55ae9bf2fa763f8de84603aa60c"
 dependencies = [
  "libc",
- "winapi",
+ "windows-sys 0.59.0",
 ]
 
+[[package]]
+name = "shlex"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
+
 [[package]]
 name = "simple_asn1"
-version = "0.6.2"
+version = "0.6.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "adc4e5204eb1910f40f9cfa375f6f05b68c3abac4b6fd879c8ff5e7ae8a0a085"
+checksum = "297f631f50729c8c99b84667867963997ec0b50f32b2a7dbcab828ef0541e8bb"
 dependencies = [
  "num-bigint",
  "num-traits",
- "thiserror 1.0.69",
+ "thiserror 2.0.11",
  "time",
 ]
 
@@ -1986,38 +2166,36 @@ dependencies = [
 
 [[package]]
 name = "smallvec"
-version = "1.13.1"
+version = "1.13.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7"
+checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
 
 [[package]]
 name = "snafu"
-version = "0.7.5"
+version = "0.8.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e4de37ad025c587a29e8f3f5605c00f70b98715ef90b9061a815b9e59e9042d6"
+checksum = "223891c85e2a29c3fe8fb900c1fae5e69c2e42415e3177752e8718475efa5019"
 dependencies = [
- "backtrace",
- "doc-comment",
  "snafu-derive",
 ]
 
 [[package]]
 name = "snafu-derive"
-version = "0.7.5"
+version = "0.8.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "990079665f075b699031e9c08fd3ab99be5029b96f3b78dc0709e8f77e4efebf"
+checksum = "03c3c6b7927ffe7ecaa769ee0e3994da3b8cafc8f444578982c83ecb161af917"
 dependencies = [
  "heck",
  "proc-macro2",
  "quote",
- "syn 1.0.109",
+ "syn",
 ]
 
 [[package]]
 name = "socket2"
-version = "0.5.6"
+version = "0.5.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871"
+checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8"
 dependencies = [
  "libc",
  "windows-sys 0.52.0",
@@ -2029,6 +2207,12 @@ version = "0.9.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
 
+[[package]]
+name = "stable_deref_trait"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
+
 [[package]]
 name = "static_assertions"
 version = "1.1.0"
@@ -2037,21 +2221,21 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
 
 [[package]]
 name = "strsim"
-version = "0.11.0"
+version = "0.11.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01"
+checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
 
 [[package]]
 name = "subtle"
-version = "2.5.0"
+version = "2.6.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc"
+checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
 
 [[package]]
 name = "syn"
-version = "1.0.109"
+version = "2.0.98"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
+checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -2059,23 +2243,23 @@ dependencies = [
 ]
 
 [[package]]
-name = "syn"
-version = "2.0.95"
+name = "sync_wrapper"
+version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "46f71c0377baf4ef1cc3e3402ded576dccc315800fbc62dfc7fe04b009773b4a"
+checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263"
 dependencies = [
- "proc-macro2",
- "quote",
- "unicode-ident",
+ "futures-core",
 ]
 
 [[package]]
-name = "sync_wrapper"
-version = "1.0.2"
+name = "synstructure"
+version = "0.13.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263"
+checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971"
 dependencies = [
- "futures-core",
+ "proc-macro2",
+ "quote",
+ "syn",
 ]
 
 [[package]]
@@ -2084,7 +2268,7 @@ version = "0.6.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b"
 dependencies = [
- "bitflags 2.4.2",
+ "bitflags 2.8.0",
  "core-foundation",
  "system-configuration-sys",
 ]
@@ -2101,9 +2285,9 @@ dependencies = [
 
 [[package]]
 name = "tar"
-version = "0.4.40"
+version = "0.4.43"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b16afcea1f22891c49a00c751c7b63b2233284064f11a200fc624137c51e2ddb"
+checksum = "c65998313f8e17d0d553d28f91a0df93e4dbbbf770279c7bc21ca0f09ea1a1f6"
 dependencies = [
  "filetime",
  "libc",
@@ -2112,14 +2296,16 @@ dependencies = [
 
 [[package]]
 name = "tempfile"
-version = "3.10.0"
+version = "3.16.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a365e8cd18e44762ef95d87f284f4b5cd04107fec2ff3052bd6a3e6069669e67"
+checksum = "38c246215d7d24f48ae091a2902398798e05d978b24315d6efbc00ede9a8bb91"
 dependencies = [
  "cfg-if",
  "fastrand",
+ "getrandom 0.3.1",
+ "once_cell",
  "rustix",
- "windows-sys 0.52.0",
+ "windows-sys 0.59.0",
 ]
 
 [[package]]
@@ -2159,7 +2345,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.95",
+ "syn",
 ]
 
 [[package]]
@@ -2170,14 +2356,14 @@ checksum = "26afc1baea8a989337eeb52b6e72a039780ce45c3edfcc9c5b9d112feeb173c2"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.95",
+ "syn",
 ]
 
 [[package]]
 name = "time"
-version = "0.3.36"
+version = "0.3.37"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885"
+checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21"
 dependencies = [
  "deranged",
  "itoa",
@@ -2196,19 +2382,29 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
 
 [[package]]
 name = "time-macros"
-version = "0.2.18"
+version = "0.2.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf"
+checksum = "2834e6017e3e5e4b9834939793b282bc03b37a3336245fa820e35e233e2a85de"
 dependencies = [
  "num-conv",
  "time-core",
 ]
 
+[[package]]
+name = "tinystr"
+version = "0.7.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f"
+dependencies = [
+ "displaydoc",
+ "zerovec",
+]
+
 [[package]]
 name = "tinyvec"
-version = "1.6.0"
+version = "1.8.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"
+checksum = "022db8904dfa342efe721985167e9fcd16c29b226db4397ed752a761cfce81e8"
 dependencies = [
  "tinyvec_macros",
 ]
@@ -2221,9 +2417,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
 
 [[package]]
 name = "tokio"
-version = "1.36.0"
+version = "1.43.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931"
+checksum = "3d61fa4ffa3de412bfea335c6ecff681de2b609ba3c77ef3e00e521813a9ed9e"
 dependencies = [
  "backtrace",
  "bytes",
@@ -2231,7 +2427,7 @@ dependencies = [
  "mio",
  "pin-project-lite",
  "socket2",
- "windows-sys 0.48.0",
+ "windows-sys 0.52.0",
 ]
 
 [[package]]
@@ -2250,7 +2446,7 @@ version = "0.25.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "775e0c0f0adb3a2f22a00c4745d728b479985fc15ee7ca6a2608388c5569860f"
 dependencies = [
- "rustls 0.22.2",
+ "rustls 0.22.4",
  "rustls-pki-types",
  "tokio",
 ]
@@ -2261,22 +2457,21 @@ version = "0.26.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "5f6d0975eaace0cf0fcadee4e4aaa5da15b5c079146f2cffb67c113be122bf37"
 dependencies = [
- "rustls 0.23.21",
+ "rustls 0.23.22",
  "tokio",
 ]
 
 [[package]]
 name = "tokio-util"
-version = "0.7.10"
+version = "0.7.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15"
+checksum = "d7fcaa8d55a2bdd6b83ace262b016eca0d79ee02818c5c1bcdf0305114081078"
 dependencies = [
  "bytes",
  "futures-core",
  "futures-sink",
  "pin-project-lite",
  "tokio",
- "tracing",
 ]
 
 [[package]]
@@ -2317,7 +2512,7 @@ version = "0.5.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1e9cd434a998747dd2c4276bc96ee2e0c7a2eadf3cae88e52be55a05fa9053f5"
 dependencies = [
- "bitflags 2.4.2",
+ "bitflags 2.8.0",
  "bytes",
  "futures-util",
  "http",
@@ -2345,9 +2540,9 @@ checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3"
 
 [[package]]
 name = "tracing"
-version = "0.1.40"
+version = "0.1.41"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef"
+checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0"
 dependencies = [
  "log",
  "pin-project-lite",
@@ -2357,20 +2552,20 @@ dependencies = [
 
 [[package]]
 name = "tracing-attributes"
-version = "0.1.27"
+version = "0.1.28"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
+checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.95",
+ "syn",
 ]
 
 [[package]]
 name = "tracing-core"
-version = "0.1.32"
+version = "0.1.33"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54"
+checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c"
 dependencies = [
  "once_cell",
 ]
@@ -2397,38 +2592,23 @@ version = "1.17.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
 
-[[package]]
-name = "unicode-bidi"
-version = "0.3.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75"
-
 [[package]]
 name = "unicode-ident"
-version = "1.0.12"
+version = "1.0.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
-
-[[package]]
-name = "unicode-normalization"
-version = "0.1.23"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5"
-dependencies = [
- "tinyvec",
-]
+checksum = "a210d160f08b701c8721ba1c726c11662f877ea6b7094007e1ca9a1041945034"
 
 [[package]]
 name = "unicode-width"
-version = "0.1.13"
+version = "0.1.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d"
+checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"
 
 [[package]]
 name = "unsafe-libyaml"
-version = "0.2.10"
+version = "0.2.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ab4c90930b95a82d00dc9e9ac071b4991924390d46cbd0dfe566148667605e4b"
+checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861"
 
 [[package]]
 name = "unscanny"
@@ -2444,9 +2624,9 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
 
 [[package]]
 name = "url"
-version = "2.5.0"
+version = "2.5.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633"
+checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60"
 dependencies = [
  "form_urlencoded",
  "idna",
@@ -2454,17 +2634,29 @@ dependencies = [
  "serde",
 ]
 
+[[package]]
+name = "utf16_iter"
+version = "1.0.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246"
+
+[[package]]
+name = "utf8_iter"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
+
 [[package]]
 name = "utf8parse"
-version = "0.2.1"
+version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
+checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
 
 [[package]]
 name = "uuid"
-version = "1.10.0"
+version = "1.13.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314"
+checksum = "ced87ca4be083373936a67f8de945faa23b6b42384bd5b64434850802c6dccd0"
 
 [[package]]
 name = "vcpkg"
@@ -2480,9 +2672,9 @@ checksum = "579a42fc0b8e0c63b76519a339be31bed574929511fa53c1a3acae26eb258f29"
 
 [[package]]
 name = "version_check"
-version = "0.9.4"
+version = "0.9.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
+checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
 
 [[package]]
 name = "want"
@@ -2499,48 +2691,59 @@ version = "0.11.0+wasi-snapshot-preview1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
 
+[[package]]
+name = "wasi"
+version = "0.13.3+wasi-0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2"
+dependencies = [
+ "wit-bindgen-rt",
+]
+
 [[package]]
 name = "wasm-bindgen"
-version = "0.2.91"
+version = "0.2.100"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c1e124130aee3fb58c5bdd6b639a0509486b0338acaaae0c84a5124b0f588b7f"
+checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5"
 dependencies = [
  "cfg-if",
+ "once_cell",
+ "rustversion",
  "wasm-bindgen-macro",
 ]
 
 [[package]]
 name = "wasm-bindgen-backend"
-version = "0.2.91"
+version = "0.2.100"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c9e7e1900c352b609c8488ad12639a311045f40a35491fb69ba8c12f758af70b"
+checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6"
 dependencies = [
  "bumpalo",
  "log",
- "once_cell",
  "proc-macro2",
  "quote",
- "syn 2.0.95",
+ "syn",
  "wasm-bindgen-shared",
 ]
 
 [[package]]
 name = "wasm-bindgen-futures"
-version = "0.4.41"
+version = "0.4.50"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "877b9c3f61ceea0e56331985743b13f3d25c406a7098d45180fb5f09bc19ed97"
+checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61"
 dependencies = [
  "cfg-if",
  "js-sys",
+ "once_cell",
  "wasm-bindgen",
  "web-sys",
 ]
 
 [[package]]
 name = "wasm-bindgen-macro"
-version = "0.2.91"
+version = "0.2.100"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b30af9e2d358182b5c7449424f017eba305ed32a7010509ede96cdc4696c46ed"
+checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407"
 dependencies = [
  "quote",
  "wasm-bindgen-macro-support",
@@ -2548,28 +2751,31 @@ dependencies = [
 
 [[package]]
 name = "wasm-bindgen-macro-support"
-version = "0.2.91"
+version = "0.2.100"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "642f325be6301eb8107a83d12a8ac6c1e1c54345a7ef1a9261962dfefda09e66"
+checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.95",
+ "syn",
  "wasm-bindgen-backend",
  "wasm-bindgen-shared",
 ]
 
 [[package]]
 name = "wasm-bindgen-shared"
-version = "0.2.91"
+version = "0.2.100"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4f186bd2dcf04330886ce82d6f33dd75a7bfcf69ecf5763b89fcde53b6ac9838"
+checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d"
+dependencies = [
+ "unicode-ident",
+]
 
 [[package]]
 name = "wasm-streams"
-version = "0.4.0"
+version = "0.4.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b65dc4c90b63b118468cf747d8bf3566c1913ef60be765b5730ead9e0a3ba129"
+checksum = "15053d8d85c7eccdbefef60f06769760a563c7f0a9d6902a13d35c7800b0ad65"
 dependencies = [
  "futures-util",
  "js-sys",
@@ -2595,9 +2801,9 @@ dependencies = [
 
 [[package]]
 name = "web-sys"
-version = "0.3.68"
+version = "0.3.77"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "96565907687f7aceb35bc5fc03770a8a0471d82e479f25832f54a0e3f4b28446"
+checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2"
 dependencies = [
  "js-sys",
  "wasm-bindgen",
@@ -2615,9 +2821,9 @@ dependencies = [
 
 [[package]]
 name = "webpki-roots"
-version = "0.26.7"
+version = "0.26.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5d642ff16b7e79272ae451b7322067cdc17cadf68c23264be9d94a32319efe7e"
+checksum = "2210b291f7ea53617fbafcc4939f10914214ec15aace5ba62293a668f322c5c9"
 dependencies = [
  "rustls-pki-types",
 ]
@@ -2650,7 +2856,7 @@ version = "0.52.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
 dependencies = [
- "windows-targets 0.52.6",
+ "windows-targets",
 ]
 
 [[package]]
@@ -2661,7 +2867,7 @@ checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0"
 dependencies = [
  "windows-result",
  "windows-strings",
- "windows-targets 0.52.6",
+ "windows-targets",
 ]
 
 [[package]]
@@ -2670,7 +2876,7 @@ version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e"
 dependencies = [
- "windows-targets 0.52.6",
+ "windows-targets",
 ]
 
 [[package]]
@@ -2680,16 +2886,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10"
 dependencies = [
  "windows-result",
- "windows-targets 0.52.6",
-]
-
-[[package]]
-name = "windows-sys"
-version = "0.48.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
-dependencies = [
- "windows-targets 0.48.5",
+ "windows-targets",
 ]
 
 [[package]]
@@ -2698,22 +2895,16 @@ version = "0.52.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
 dependencies = [
- "windows-targets 0.52.6",
+ "windows-targets",
 ]
 
 [[package]]
-name = "windows-targets"
-version = "0.48.5"
+name = "windows-sys"
+version = "0.59.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
+checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
 dependencies = [
- "windows_aarch64_gnullvm 0.48.5",
- "windows_aarch64_msvc 0.48.5",
- "windows_i686_gnu 0.48.5",
- "windows_i686_msvc 0.48.5",
- "windows_x86_64_gnu 0.48.5",
- "windows_x86_64_gnullvm 0.48.5",
- "windows_x86_64_msvc 0.48.5",
+ "windows-targets",
 ]
 
 [[package]]
@@ -2722,46 +2913,28 @@ version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
 dependencies = [
- "windows_aarch64_gnullvm 0.52.6",
- "windows_aarch64_msvc 0.52.6",
- "windows_i686_gnu 0.52.6",
+ "windows_aarch64_gnullvm",
+ "windows_aarch64_msvc",
+ "windows_i686_gnu",
  "windows_i686_gnullvm",
- "windows_i686_msvc 0.52.6",
- "windows_x86_64_gnu 0.52.6",
- "windows_x86_64_gnullvm 0.52.6",
- "windows_x86_64_msvc 0.52.6",
+ "windows_i686_msvc",
+ "windows_x86_64_gnu",
+ "windows_x86_64_gnullvm",
+ "windows_x86_64_msvc",
 ]
 
-[[package]]
-name = "windows_aarch64_gnullvm"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
-
 [[package]]
 name = "windows_aarch64_gnullvm"
 version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
 
-[[package]]
-name = "windows_aarch64_msvc"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
-
 [[package]]
 name = "windows_aarch64_msvc"
 version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
 
-[[package]]
-name = "windows_i686_gnu"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
-
 [[package]]
 name = "windows_i686_gnu"
 version = "0.52.6"
@@ -2774,24 +2947,12 @@ version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
 
-[[package]]
-name = "windows_i686_msvc"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
-
 [[package]]
 name = "windows_i686_msvc"
 version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
 
-[[package]]
-name = "windows_x86_64_gnu"
-version = "0.48.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
-
 [[package]]
 name = "windows_x86_64_gnu"
 version = "0.52.6"
@@ -2800,33 +2961,42 @@ checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
 
 [[package]]
 name = "windows_x86_64_gnullvm"
-version = "0.48.5"
+version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
+checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
 
 [[package]]
-name = "windows_x86_64_gnullvm"
+name = "windows_x86_64_msvc"
 version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
+checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
 
 [[package]]
-name = "windows_x86_64_msvc"
-version = "0.48.5"
+name = "wit-bindgen-rt"
+version = "0.33.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
+checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c"
+dependencies = [
+ "bitflags 2.8.0",
+]
 
 [[package]]
-name = "windows_x86_64_msvc"
-version = "0.52.6"
+name = "write16"
+version = "1.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
+checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936"
+
+[[package]]
+name = "writeable"
+version = "0.5.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51"
 
 [[package]]
 name = "xattr"
-version = "1.3.1"
+version = "1.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8da84f1a25939b27f6820d92aed108f83ff920fdf11a7b19366c27c4cda81d4f"
+checksum = "e105d177a3871454f754b33bb0ee637ecaaac997446375fd3e5d43a2ed00c909"
 dependencies = [
  "libc",
  "linux-raw-sys",
@@ -2842,6 +3012,30 @@ dependencies = [
  "linked-hash-map",
 ]
 
+[[package]]
+name = "yoke"
+version = "0.7.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40"
+dependencies = [
+ "serde",
+ "stable_deref_trait",
+ "yoke-derive",
+ "zerofrom",
+]
+
+[[package]]
+name = "yoke-derive"
+version = "0.7.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+ "synstructure",
+]
+
 [[package]]
 name = "zerocopy"
 version = "0.7.35"
@@ -2860,14 +3054,57 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.95",
+ "syn",
+]
+
+[[package]]
+name = "zerofrom"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e"
+dependencies = [
+ "zerofrom-derive",
+]
+
+[[package]]
+name = "zerofrom-derive"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+ "synstructure",
 ]
 
 [[package]]
 name = "zeroize"
-version = "1.7.0"
+version = "1.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde"
+
+[[package]]
+name = "zerovec"
+version = "0.10.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d"
+checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079"
+dependencies = [
+ "yoke",
+ "zerofrom",
+ "zerovec-derive",
+]
+
+[[package]]
+name = "zerovec-derive"
+version = "0.10.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
 
 [[package]]
 name = "zip"
@@ -2900,11 +3137,11 @@ dependencies = [
 
 [[package]]
 name = "zstd"
-version = "0.13.0"
+version = "0.13.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bffb3309596d527cfcba7dfc6ed6052f1d39dfbd7c867aa2e865e4a449c10110"
+checksum = "fcf2b778a664581e31e389454a7072dab1647606d44f7feea22cd5abb9c9f3f9"
 dependencies = [
- "zstd-safe 7.0.0",
+ "zstd-safe 7.2.1",
 ]
 
 [[package]]
@@ -2919,18 +3156,18 @@ dependencies = [
 
 [[package]]
 name = "zstd-safe"
-version = "7.0.0"
+version = "7.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "43747c7422e2924c11144d5229878b98180ef8b06cca4ab5af37afc8a8d8ea3e"
+checksum = "54a3ab4db68cea366acc5c897c7b4d4d1b8994a9cd6e6f841f8964566a419059"
 dependencies = [
  "zstd-sys",
 ]
 
 [[package]]
 name = "zstd-sys"
-version = "2.0.9+zstd.1.5.5"
+version = "2.0.13+zstd.1.5.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9e16efa8a874a0481a574084d34cc26fdb3b99627480f785888deb6386506656"
+checksum = "38ff0f21cfee8f97d94cef41359e0c89aa6113028ab0291aa8ca0038995a95aa"
 dependencies = [
  "cc",
  "pkg-config",

From 469b3c5bb9af119ef6635b52197df42dc2d03d83 Mon Sep 17 00:00:00 2001
From: Emmanuel Leblond <emmanuel.leblond@gmail.com>
Date: Mon, 10 Feb 2025 04:02:42 +0100
Subject: [PATCH 044/157] Update `PYTHON.json` current value for `version`
 field in documentation (#518)

Hi,

Just a minor PR to update `PYTHON.json`'s `version` field value in
documentation, following this change


https://github.com/astral-sh/python-build-standalone/commit/0d7e5e018808ce810262627a2f463bb4eb9f7fb0#diff-e777e81ce98aba56bbd99a66c610b273b2869e8c2c048b39eb75c74c83d3b793R1760
---
 docs/distributions.rst | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/distributions.rst b/docs/distributions.rst
index 052a6e31..3dd6125a 100644
--- a/docs/distributions.rst
+++ b/docs/distributions.rst
@@ -38,7 +38,7 @@ without having to resort to heuristics.
 The file contains a JSON map. This map has the following keys:
 
 version
-   Version number of the file format. Currently ``7``.
+   Version number of the file format. Currently ``8``.
 
 target_triple
    A target triple defining the platform and architecture of the machine

From d03ec63dee4411651a86a61ec3bcd29cdb600657 Mon Sep 17 00:00:00 2001
From: Geoffrey Thomas <geofft@ldpreload.com>
Date: Tue, 11 Feb 2025 17:21:26 -0500
Subject: [PATCH 045/157] Upgrade OpenSSL from 3.0.15 to 3.0.16 (#523)

---
 pythonbuild/downloads.py   | 8 ++++----
 src/verify_distribution.py | 2 +-
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/pythonbuild/downloads.py b/pythonbuild/downloads.py
index 0a723aa9..aff18afd 100644
--- a/pythonbuild/downloads.py
+++ b/pythonbuild/downloads.py
@@ -249,10 +249,10 @@
     # using the latest available.
     # Remember to update OPENSSL_VERSION_INFO in verify_distribution.py whenever upgrading.
     "openssl-3.0": {
-        "url": "https://www.openssl.org/source/openssl-3.0.15.tar.gz",
-        "size": 15318633,
-        "sha256": "23c666d0edf20f14249b3d8f0368acaee9ab585b09e1de82107c66e1f3ec9533",
-        "version": "3.0.15",
+        "url": "https://www.openssl.org/source/openssl-3.0.16.tar.gz",
+        "size": 15334967,
+        "sha256": "57e03c50feab5d31b152af2b764f10379aecd8ee92f16c985983ce4a99f7ef86",
+        "version": "3.0.16",
         "library_names": ["crypto", "ssl"],
         "licenses": ["Apache-2.0"],
         "license_file": "LICENSE.openssl-3.txt",
diff --git a/src/verify_distribution.py b/src/verify_distribution.py
index 5fc6ce8d..46ac48c6 100644
--- a/src/verify_distribution.py
+++ b/src/verify_distribution.py
@@ -135,7 +135,7 @@ def test_ssl(self):
         if os.name == "nt" and sys.version_info[0:2] < (3, 11):
             wanted_version = (1, 1, 1, 23, 15)
         else:
-            wanted_version = (3, 0, 0, 15, 0)
+            wanted_version = (3, 0, 0, 16, 0)
 
         self.assertEqual(ssl.OPENSSL_VERSION_INFO, wanted_version)
 

From 67c3fe7d3bd0639aeb930f42e87f5d836734e945 Mon Sep 17 00:00:00 2001
From: samypr100 <3933065+samypr100@users.noreply.github.com>
Date: Tue, 11 Feb 2025 17:22:00 -0500
Subject: [PATCH 046/157] feat: support release attestations (#517)

## Summary

Reverts https://github.com/astral-sh/python-build-standalone/pull/514

This adds back support for release attestations after asset uploads.

Turns out extended glob is not supported via subject-path given how the
action searches the directories and applies the glob, so instead we
declare multiple simple globs since subject-path supports that too.

## Test Plan

A full release was tested with about 155 artifacts (had to limit release
triplets since free runners have limited resources) which resulted in 76
subjects created due to filtering.

See release here:
https://github.com/samypr100/python-build-standalone/releases/tag/20250205

See run here:
https://github.com/samypr100/python-build-standalone/actions/runs/13220724442/job/36905418053

See attestations here:
https://github.com/samypr100/python-build-standalone/attestations/4870998
---
 .github/workflows/release.yml | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 4f91719c..7993fe5c 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -78,3 +78,12 @@ jobs:
       # Uploading the relevant artifact to the GitHub release.
       - run: just release-run ${{ secrets.GITHUB_TOKEN }} ${{ github.event.inputs.sha }} ${{ github.event.inputs.tag }}
         if: ${{ github.event.inputs.dry-run == 'false' }}
+
+      # We filter by *.tar.@(zst|gz) since actions/attest-build-provenance only supports up to 1024 subjects
+      - name: Generate attestations
+        uses: actions/attest-build-provenance@v2
+        if: ${{ github.event.inputs.dry-run == 'false' }}
+        with:
+          subject-path: |
+            dist/*.tar.gz
+            dist/*.tar.zst

From a456e8fb4a29e337df69da3fc81e7a9b860a7623 Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Tue, 11 Feb 2025 16:28:18 -0600
Subject: [PATCH 047/157] Use an array for cross-platform sed args to avoid
 unexpected shell expansion (#520)

Closes https://github.com/astral-sh/python-build-standalone/issues/519
---
 cpython-unix/build-cpython.sh | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/cpython-unix/build-cpython.sh b/cpython-unix/build-cpython.sh
index 6d8a5cde..fcef6324 100755
--- a/cpython-unix/build-cpython.sh
+++ b/cpython-unix/build-cpython.sh
@@ -34,12 +34,12 @@ export trailer_m4=${TOOLS_PATH}/host/share/autoconf/autoconf/trailer.m4
 # The share/autoconf/autom4te.cfg file also hard-codes some paths. Rewrite
 # those to the real tools path.
 if [ "${PYBUILD_PLATFORM}" = "macos" ]; then
-  sed_args="-i '' -e"
+    sed_args=(-i '' -e)
 else
-  sed_args="-i"
+    sed_args=(-i)
 fi
 
-sed ${sed_args} "s|/tools/host|${TOOLS_PATH}/host|g" ${TOOLS_PATH}/host/share/autoconf/autom4te.cfg
+sed "${sed_args[@]}" "s|/tools/host|${TOOLS_PATH}/host|g" ${TOOLS_PATH}/host/share/autoconf/autom4te.cfg
 
 # We force linking of external static libraries by removing the shared
 # libraries. This is hacky. But we're building in a temporary container
@@ -1094,7 +1094,7 @@ fi
 # Don't hard-code the build-time prefix into the pkg-config files. See
 # the description of `pcfiledir` in `man pkg-config`.
 find ${ROOT}/out/python/install/lib/pkgconfig -name \*.pc -type f -exec \
-    sed ${sed_args} 's|^prefix=/install|prefix=${pcfiledir}/../..|' {} +
+    sed "${sed_args[@]}" 's|^prefix=/install|prefix=${pcfiledir}/../..|' {} +
 
 mkdir ${ROOT}/out/python/licenses
 cp ${ROOT}/LICENSE.*.txt ${ROOT}/out/python/licenses/

From 440cedcf54c990067479bd0b716ca411704138ff Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Tue, 11 Feb 2025 23:16:14 -0600
Subject: [PATCH 048/157] Fix Windows build job names in CI (#525)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

<img width="334" alt="Screenshot 2025-02-11 at 10 58 24 PM"
src="https://github.com/user-attachments/assets/f63da081-c55d-418f-9f64-3b75b7f13c06"
/>
<img width="334" alt="Screenshot 2025-02-11 at 10 58 36 PM"
src="https://github.com/user-attachments/assets/458bf3b1-b6d2-48cc-9e17-bf1a154b2531"
/>
---
 .github/workflows/windows.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml
index 179cfb99..6065b439 100644
--- a/.github/workflows/windows.yml
+++ b/.github/workflows/windows.yml
@@ -96,7 +96,7 @@ jobs:
     strategy:
       matrix: ${{ fromJson(needs.generate-matrix.outputs.matrix) }}
       fail-fast: false
-    name: ${{ matrix.target_triple }} / ${{ matrix.python }} / ${{ matrix.build_option }}
+    name: ${{ matrix.target_triple }} / ${{ matrix.python }} / ${{ matrix.build_options }}
     steps:
       - uses: actions/checkout@v4
         with:

From 1ab35965b84e9d973bf6237a63597eeed06a149b Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Wed, 12 Feb 2025 08:07:22 -0600
Subject: [PATCH 049/157] Bump to CPython 3.14.0a5 (#521)

---
 cpython-unix/build-cpython.sh                 |  5 ---
 ...tch-test-embed-prevent-segfault-3.14.patch | 36 -------------------
 pythonbuild/downloads.py                      |  8 ++---
 3 files changed, 4 insertions(+), 45 deletions(-)
 delete mode 100644 cpython-unix/patch-test-embed-prevent-segfault-3.14.patch

diff --git a/cpython-unix/build-cpython.sh b/cpython-unix/build-cpython.sh
index fcef6324..9c86aa45 100755
--- a/cpython-unix/build-cpython.sh
+++ b/cpython-unix/build-cpython.sh
@@ -314,11 +314,6 @@ if [ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_12}" ]; then
     patch -p1 -i ${ROOT}/patch-test-embed-prevent-segfault.patch
 fi
 
-# Same as above but for an additional set of tests introduced in 3.14.
-if [ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_14}" ]; then
-    patch -p1 -i ${ROOT}/patch-test-embed-prevent-segfault-3.14.patch
-fi
-
 # Most bits look at CFLAGS. But setup.py only looks at CPPFLAGS.
 # So we need to set both.
 CFLAGS="${EXTRA_TARGET_CFLAGS} -fPIC -I${TOOLS_PATH}/deps/include -I${TOOLS_PATH}/deps/include/ncursesw"
diff --git a/cpython-unix/patch-test-embed-prevent-segfault-3.14.patch b/cpython-unix/patch-test-embed-prevent-segfault-3.14.patch
deleted file mode 100644
index d5144086..00000000
--- a/cpython-unix/patch-test-embed-prevent-segfault-3.14.patch
+++ /dev/null
@@ -1,36 +0,0 @@
-diff --git a/Lib/test/test_embed.py b/Lib/test/test_embed.py
-index 7110fb889f3..1b55cd156d7 100644
---- a/Lib/test/test_embed.py
-+++ b/Lib/test/test_embed.py
-@@ -940,6 +940,7 @@ def check_all_configs(self, testname, expected_config=None,
-         self.check_global_config(configs)
-         return configs
- 
-+    @unittest.skipIf(support.check_bolt_optimized, "segfaults on BOLT instrumented binaries")
-     def test_init_default_config(self):
-         self.check_all_configs("test_init_initialize_config", api=API_COMPAT)
- 
-@@ -1039,6 +1040,7 @@ def test_init_from_config(self):
-         self.check_all_configs("test_init_from_config", config, preconfig,
-                                api=API_COMPAT)
- 
-+    @unittest.skipIf(support.check_bolt_optimized, "segfaults on BOLT instrumented binaries")
-     def test_init_compat_env(self):
-         preconfig = {
-             'allocator': ALLOCATOR_FOR_CONFIG,
-@@ -1074,6 +1076,7 @@ def test_init_compat_env(self):
-         self.check_all_configs("test_init_compat_env", config, preconfig,
-                                api=API_COMPAT)
- 
-+    @unittest.skipIf(support.check_bolt_optimized, "segfaults on BOLT instrumented binaries")
-     def test_init_python_env(self):
-         preconfig = {
-             'allocator': ALLOCATOR_FOR_CONFIG,
-@@ -1772,6 +1775,7 @@ def test_init_set_config(self):
-         self.check_all_configs("test_init_set_config", config,
-                                api=API_ISOLATED)
- 
-+    @unittest.skipIf(support.check_bolt_optimized, "segfaults on BOLT instrumented binaries")
-     def test_initconfig_api(self):
-         preconfig = {
-             'configure_locale': True,
diff --git a/pythonbuild/downloads.py b/pythonbuild/downloads.py
index aff18afd..4a753357 100644
--- a/pythonbuild/downloads.py
+++ b/pythonbuild/downloads.py
@@ -80,10 +80,10 @@
         "python_tag": "cp313",
     },
     "cpython-3.14": {
-        "url": "https://www.python.org/ftp/python/3.14.0/Python-3.14.0a4.tar.xz",
-        "size": 22798932,
-        "sha256": "c24f07881873c1d460228795ca6ca8c99130e30c773c91463d30d7ea8ff0e70b",
-        "version": "3.14.0a4",
+        "url": "https://www.python.org/ftp/python/3.14.0/Python-3.14.0a5.tar.xz",
+        "size": 22859900,
+        "sha256": "74e83f26de1e4fb9eef1b56492cff92508834bb71ac13f5c580438ce9f093682",
+        "version": "3.14.0a5",
         "licenses": ["Python-2.0", "CNRI-Python"],
         "license_file": "LICENSE.cpython.txt",
         "python_tag": "cp314",

From aa430e23e31fdbc612938d3a748974a60e6ff1f9 Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Wed, 12 Feb 2025 08:24:49 -0600
Subject: [PATCH 050/157] Enable the tail call interpreter on 3.14+ clang
 builds (#524)

---
 cpython-unix/build-cpython.sh | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/cpython-unix/build-cpython.sh b/cpython-unix/build-cpython.sh
index 9c86aa45..566700e0 100755
--- a/cpython-unix/build-cpython.sh
+++ b/cpython-unix/build-cpython.sh
@@ -348,6 +348,13 @@ if [ "${PYBUILD_PLATFORM}" != "macos" ]; then
     fi
 fi
 
+# On Python 3.14+, enable the tail calling interpreter which is more performant.
+# This is only available on Clang 19+
+# https://docs.python.org/3.14/using/configure.html#cmdoption-with-tail-call-interp
+if [[ "${CC}" = "clang" && -n "${PYTHON_MEETS_MINIMUM_VERSION_3_14}" ]]; then
+    EXTRA_CONFIGURE_FLAGS="${EXTRA_CONFIGURE_FLAGS} --with-tail-call-interp"
+fi
+
 # On Python 3.12+ we need to link the special hacl library provided some SHA-256
 # implementations. Since we hack up the regular extension building mechanism, we
 # need to reinvent this wheel.

From d7759a1090efbdad326aab7ba97d646183b71cc5 Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Thu, 27 Feb 2025 12:33:07 -0600
Subject: [PATCH 051/157] Set `enable-experimental-jit=yes-off` on Python 3.13
 / Linux (#538)

See #535

This builds the JIT, but disables it by default. Users can opt-in to
enable it at runtime.

3.14 and macOS support will follow, there are some hiccups there.
---
 cpython-unix/build-cpython.sh        | 16 ++++++++++++++++
 cpython-unix/patch-jit-llvm-19.patch | 12 ++++++++++++
 2 files changed, 28 insertions(+)
 create mode 100644 cpython-unix/patch-jit-llvm-19.patch

diff --git a/cpython-unix/build-cpython.sh b/cpython-unix/build-cpython.sh
index 566700e0..0bba0168 100755
--- a/cpython-unix/build-cpython.sh
+++ b/cpython-unix/build-cpython.sh
@@ -424,6 +424,22 @@ if [ -n "${CPYTHON_OPTIMIZED}" ]; then
     if [[ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_12}" && -n "${BOLT_CAPABLE}" ]]; then
         CONFIGURE_FLAGS="${CONFIGURE_FLAGS} --enable-bolt"
     fi
+
+    # Allow users to enable the experimental JIT on 3.13+
+    if [[ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_13}" ]]; then
+
+        # The JIT build is failing on macOS and 3.14+ due to compiler errors
+        # Only enable on Linux / 3.13 until that's fixed upstream
+        if [[ -n "${PYTHON_MEETS_MAXIMUM_VERSION_3_13}" && "${PYBUILD_PLATFORM}" != "macos" ]]; then
+            CONFIGURE_FLAGS="${CONFIGURE_FLAGS} --enable-experimental-jit=yes-off"
+        fi
+
+        if [[ -n "${PYTHON_MEETS_MAXIMUM_VERSION_3_13}" ]]; then
+            # On 3.13, LLVM 18 is hard-coded into the configure script. Override it to our toolchain
+            # version.
+            patch -p1 -i "${ROOT}/patch-jit-llvm-19.patch"
+        fi
+    fi
 fi
 
 if [ -n "${CPYTHON_LTO}" ]; then
diff --git a/cpython-unix/patch-jit-llvm-19.patch b/cpython-unix/patch-jit-llvm-19.patch
new file mode 100644
index 00000000..1b66f119
--- /dev/null
+++ b/cpython-unix/patch-jit-llvm-19.patch
@@ -0,0 +1,12 @@
+diff --git a/Tools/jit/_llvm.py b/Tools/jit/_llvm.py
+--- a/Tools/jit/_llvm.py
++++ b/Tools/jit/_llvm.py
+@@ -8,7 +8,7 @@
+ import subprocess
+ import typing
+ 
+-_LLVM_VERSION = 18
++_LLVM_VERSION = 19
+ _LLVM_VERSION_PATTERN = re.compile(rf"version\s+{_LLVM_VERSION}\.\d+\.\d+\S*\s+")
+ 
+ _P = typing.ParamSpec("_P")

From 2a9167e8098ef74f2752eb59636182d0d967c5e9 Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Thu, 27 Feb 2025 13:12:23 -0600
Subject: [PATCH 052/157] Allow the JIT to be used on Python 3.14 (#543)

Follows https://github.com/astral-sh/python-build-standalone/pull/538
---
 cpython-unix/build-cpython.sh                 |  10 +-
 ...atch-jit-tail-call-compat-314-129820.patch | 227 ++++++++++++++++++
 2 files changed, 235 insertions(+), 2 deletions(-)
 create mode 100644 cpython-unix/patch-jit-tail-call-compat-314-129820.patch

diff --git a/cpython-unix/build-cpython.sh b/cpython-unix/build-cpython.sh
index 0bba0168..ea1b1c0a 100755
--- a/cpython-unix/build-cpython.sh
+++ b/cpython-unix/build-cpython.sh
@@ -428,9 +428,9 @@ if [ -n "${CPYTHON_OPTIMIZED}" ]; then
     # Allow users to enable the experimental JIT on 3.13+
     if [[ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_13}" ]]; then
 
-        # The JIT build is failing on macOS and 3.14+ due to compiler errors
+        # The JIT build is failing on macOS due to compiler errors
         # Only enable on Linux / 3.13 until that's fixed upstream
-        if [[ -n "${PYTHON_MEETS_MAXIMUM_VERSION_3_13}" && "${PYBUILD_PLATFORM}" != "macos" ]]; then
+        if [[ "${PYBUILD_PLATFORM}" != "macos" ]]; then
             CONFIGURE_FLAGS="${CONFIGURE_FLAGS} --enable-experimental-jit=yes-off"
         fi
 
@@ -439,6 +439,12 @@ if [ -n "${CPYTHON_OPTIMIZED}" ]; then
             # version.
             patch -p1 -i "${ROOT}/patch-jit-llvm-19.patch"
         fi
+
+         if [[ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_14}" ]]; then
+            # On 3.14, we also use the tail calling interpreter which was incompatible with the JIT
+            # until https://github.com/python/cpython/pull/129820 — backport that
+            patch -p1 -i "${ROOT}/patch-jit-tail-call-compat-314-129820.patch"
+        fi
     fi
 fi
 
diff --git a/cpython-unix/patch-jit-tail-call-compat-314-129820.patch b/cpython-unix/patch-jit-tail-call-compat-314-129820.patch
new file mode 100644
index 00000000..c612c5bc
--- /dev/null
+++ b/cpython-unix/patch-jit-tail-call-compat-314-129820.patch
@@ -0,0 +1,227 @@
+diff --git a/configure b/configure
+index 65b8e711cdccae..ee47feafc73fc1 100755
+--- a/configure
++++ b/configure
+@@ -29281,18 +29281,6 @@ esac
+ fi
+ 
+ 
+-# Do not enable tail-calling interpreter if tier 2 is enabled.
+-if ${tier2_flags:+false} :
+-then :
+-
+-    case "$ac_cv_tail_call" in yes*)
+-
+-printf "%s\n" "#define Py_TAIL_CALL_INTERP 1" >>confdefs.h
+-
+-    esac
+-
+-fi
+-
+ 
+ case $ac_sys_system in
+ AIX*)
+diff --git a/configure.ac b/configure.ac
+index 0c6063d87d654a..c68938ba9e168d 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -7041,19 +7041,6 @@ fi
+ ],
+ [AC_MSG_RESULT([no value specified])])
+ 
+-# Do not enable tail-calling interpreter if tier 2 is enabled.
+-AS_VAR_IF(
+-  [tier2_flags],
+-  [],
+-  [
+-    case "$ac_cv_tail_call" in yes*)
+-      AC_DEFINE([Py_TAIL_CALL_INTERP], [1],
+-      [Define if the C compiler supports efficient proper tail calls.])
+-    esac
+-  ],
+-  []
+-)
+-
+ 
+ case $ac_sys_system in
+ AIX*)
+diff --git a/pyconfig.h.in b/pyconfig.h.in
+index 9ea01ad3fc0a31..4295b4f5ea5fbd 100644
+--- a/pyconfig.h.in
++++ b/pyconfig.h.in
+@@ -1718,7 +1718,7 @@
+ /* The version of SunOS/Solaris as reported by `uname -r' without the dot. */
+ #undef Py_SUNOS_VERSION
+ 
+-/* Define if the C compiler supports efficient proper tail calls. */
++/* Define if you want to use tail-calling interpreters in CPython. */
+ #undef Py_TAIL_CALL_INTERP
+ 
+ /* Define if you want to enable tracing references for debugging purpose */
+
+From dae88e3ca730576256a0b8d2bc9e78b8cacab645 Mon Sep 17 00:00:00 2001
+From: Ken Jin <28750310+Fidget-Spinner@users.noreply.github.com>
+Date: Sat, 8 Feb 2025 01:32:05 +0800
+Subject: [PATCH 2/6] Get JIT working minimally with tailcalling interpreter
+
+---
+ Python/ceval_macros.h | 19 +++++++++++++++++++
+ 1 file changed, 19 insertions(+)
+
+diff --git a/Python/ceval_macros.h b/Python/ceval_macros.h
+index 44bb52a09aab5f..2c7729743b1705 100644
+--- a/Python/ceval_macros.h
++++ b/Python/ceval_macros.h
+@@ -384,6 +384,24 @@ _PyFrame_SetStackPointer(frame, stack_pointer)
+ /* Tier-switching macros. */
+ 
+ #ifdef _Py_JIT
++#ifdef Py_TAIL_CALL_INTERP
++#define GOTO_TIER_TWO(EXECUTOR)                        \
++do {                                                   \
++    OPT_STAT_INC(traces_executed);                     \
++    jit_func jitted = (EXECUTOR)->jit_code;            \
++    next_instr = jitted(frame, stack_pointer, tstate); \
++    Py_DECREF(tstate->previous_executor);              \
++    tstate->previous_executor = NULL;                  \
++    frame = tstate->current_frame;                     \
++    if (next_instr == NULL) {                          \
++        next_instr = frame->instr_ptr;                 \
++        stack_pointer = _PyFrame_GetStackPointer(frame); \
++        return _TAIL_CALL_error(TAIL_CALL_ARGS);       \
++    }                                                  \
++    stack_pointer = _PyFrame_GetStackPointer(frame);   \
++    DISPATCH();                                        \
++} while (0)
++#else
+ #define GOTO_TIER_TWO(EXECUTOR)                        \
+ do {                                                   \
+     OPT_STAT_INC(traces_executed);                     \
+@@ -400,6 +418,7 @@ do {                                                   \
+     stack_pointer = _PyFrame_GetStackPointer(frame);   \
+     DISPATCH();                                        \
+ } while (0)
++#endif
+ #else
+ #define GOTO_TIER_TWO(EXECUTOR) \
+ do { \
+
+From 230d497620d73e17a099326f7e54078e91254e5a Mon Sep 17 00:00:00 2001
+From: Ken Jin <28750310+Fidget-Spinner@users.noreply.github.com>
+Date: Tue, 11 Feb 2025 16:05:57 +0800
+Subject: [PATCH 3/6] Update ceval_macros.h
+
+---
+ Python/ceval_macros.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/Python/ceval_macros.h b/Python/ceval_macros.h
+index 2c7729743b1705..0f4dd61f367dbb 100644
+--- a/Python/ceval_macros.h
++++ b/Python/ceval_macros.h
+@@ -384,7 +384,7 @@ _PyFrame_SetStackPointer(frame, stack_pointer)
+ /* Tier-switching macros. */
+ 
+ #ifdef _Py_JIT
+-#ifdef Py_TAIL_CALL_INTERP
++#if Py_TAIL_CALL_INTERP
+ #define GOTO_TIER_TWO(EXECUTOR)                        \
+ do {                                                   \
+     OPT_STAT_INC(traces_executed);                     \
+
+From c46391470ca8b4d6a4b9c0d9f75c7fcce6ac303a Mon Sep 17 00:00:00 2001
+From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com>
+Date: Tue, 11 Feb 2025 08:06:47 +0000
+Subject: [PATCH 4/6] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20blu?=
+ =?UTF-8?q?rb=5Fit.?=
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+---
+ .../next/Build/2025-02-11-08-06-44.gh-issue-129819.7rn4dY.rst    | 1 +
+ 1 file changed, 1 insertion(+)
+ create mode 100644 Misc/NEWS.d/next/Build/2025-02-11-08-06-44.gh-issue-129819.7rn4dY.rst
+
+diff --git a/Misc/NEWS.d/next/Build/2025-02-11-08-06-44.gh-issue-129819.7rn4dY.rst b/Misc/NEWS.d/next/Build/2025-02-11-08-06-44.gh-issue-129819.7rn4dY.rst
+new file mode 100644
+index 00000000000000..2463e4dba24ae9
+--- /dev/null
++++ b/Misc/NEWS.d/next/Build/2025-02-11-08-06-44.gh-issue-129819.7rn4dY.rst
+@@ -0,0 +1 @@
++Allow building the JIT with the tailcall interpreter.
+
+From 105ab11ce4fcc3d659ccaf36197ea281b853e23a Mon Sep 17 00:00:00 2001
+From: Ken Jin <28750310+Fidget-Spinner@users.noreply.github.com>
+Date: Wed, 12 Feb 2025 16:14:23 +0800
+Subject: [PATCH 5/6] Address review
+
+---
+ Python/ceval_macros.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/Python/ceval_macros.h b/Python/ceval_macros.h
+index 0f4dd61f367dbb..9562ad9d349a11 100644
+--- a/Python/ceval_macros.h
++++ b/Python/ceval_macros.h
+@@ -396,7 +396,7 @@ do {                                                   \
+     if (next_instr == NULL) {                          \
+         next_instr = frame->instr_ptr;                 \
+         stack_pointer = _PyFrame_GetStackPointer(frame); \
+-        return _TAIL_CALL_error(TAIL_CALL_ARGS);       \
++        return JUMP_TO_LABEL(error);                   \
+     }                                                  \
+     stack_pointer = _PyFrame_GetStackPointer(frame);   \
+     DISPATCH();                                        \
+
+From 76c2c96fed4abc68e8879f3d65755d5cba8a4b16 Mon Sep 17 00:00:00 2001
+From: Ken Jin <28750310+Fidget-Spinner@users.noreply.github.com>
+Date: Thu, 13 Feb 2025 01:06:07 +0800
+Subject: [PATCH 6/6] one-liner
+
+---
+ Python/ceval_macros.h | 21 +--------------------
+ 1 file changed, 1 insertion(+), 20 deletions(-)
+
+diff --git a/Python/ceval_macros.h b/Python/ceval_macros.h
+index 2422bf3bcf38f1..4f0071d5e1a09f 100644
+--- a/Python/ceval_macros.h
++++ b/Python/ceval_macros.h
+@@ -381,24 +381,6 @@ _PyFrame_SetStackPointer(frame, stack_pointer)
+ /* Tier-switching macros. */
+ 
+ #ifdef _Py_JIT
+-#if Py_TAIL_CALL_INTERP
+-#define GOTO_TIER_TWO(EXECUTOR)                        \
+-do {                                                   \
+-    OPT_STAT_INC(traces_executed);                     \
+-    jit_func jitted = (EXECUTOR)->jit_code;            \
+-    next_instr = jitted(frame, stack_pointer, tstate); \
+-    Py_DECREF(tstate->previous_executor);              \
+-    tstate->previous_executor = NULL;                  \
+-    frame = tstate->current_frame;                     \
+-    if (next_instr == NULL) {                          \
+-        next_instr = frame->instr_ptr;                 \
+-        stack_pointer = _PyFrame_GetStackPointer(frame); \
+-        return JUMP_TO_LABEL(error);                   \
+-    }                                                  \
+-    stack_pointer = _PyFrame_GetStackPointer(frame);   \
+-    DISPATCH();                                        \
+-} while (0)
+-#else
+ #define GOTO_TIER_TWO(EXECUTOR)                        \
+ do {                                                   \
+     OPT_STAT_INC(traces_executed);                     \
+@@ -413,11 +395,10 @@ do {                                                   \
+     stack_pointer = _PyFrame_GetStackPointer(frame);   \
+     if (next_instr == NULL) {                          \
+         next_instr = frame->instr_ptr;                 \
+-        goto error;                                    \
++        JUMP_TO_LABEL(error);                          \
+     }                                                  \
+     DISPATCH();                                        \
+ } while (0)
+-#endif
+ #else
+ #define GOTO_TIER_TWO(EXECUTOR) \
+ do { \

From d0ed97f7618769996f1dd2a586faec150d7ebcb9 Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Wed, 5 Mar 2025 13:52:04 -0600
Subject: [PATCH 053/157] Populate CXX during builds to avoid calling the
 system toolchain (#545)

Closes #512
---
 cpython-unix/build.py | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/cpython-unix/build.py b/cpython-unix/build.py
index da66ba4e..97ceaebb 100755
--- a/cpython-unix/build.py
+++ b/cpython-unix/build.py
@@ -101,6 +101,9 @@ def add_target_env(env, build_platform, target_triple, build_env):
     env["HOST_CC"] = settings["host_cc"]
     env["HOST_CXX"] = settings["host_cxx"]
     env["CC"] = settings["target_cc"]
+    # We always set CXX, otherwise a build could bypass our toolchain
+    # accidentally, e.g., on macOS where `g++` links to the system clang.
+    env["CXX"] = settings.get("target_cxx", settings.get("host_cxx"))
 
     if settings.get("bolt_capable"):
         env["BOLT_CAPABLE"] = "1"

From 9f447553d1e5a0c4d69b975be150ab3e31975012 Mon Sep 17 00:00:00 2001
From: Gregory Szorc <gregory.szorc@gmail.com>
Date: Tue, 11 Mar 2025 07:23:46 -0700
Subject: [PATCH 054/157] Upgrade to LLVM 20.1.0 (#553)

I just published an LLVM 20.1.0 toolchain with some computed gotos
patches to hopefully improve performance of CPython.


https://github.com/indygreg/toolchain-tools/releases/tag/toolchain-bootstrap%2F20250308

One of the patches changes codegen to fix a regression in LLVM 19.

The other enables bolt to work with computed gotos. To take full
advantage of this functionality we patch CPython configure to remove
some `--skip-funcs` which are no longer required.
---
 cpython-unix/build-cpython.sh                 |  6 ++++-
 .../patch-configure-bolt-skip-funcs.patch     | 17 ++++++++++++
 ...atch => patch-jit-llvm-version-3.13.patch} |  2 +-
 .../patch-jit-llvm-version-3.14.patch         | 12 +++++++++
 pythonbuild/downloads.py                      | 26 +++++++++----------
 pythonbuild/utils.py                          |  2 +-
 src/release.rs                                |  6 ++---
 7 files changed, 52 insertions(+), 19 deletions(-)
 create mode 100644 cpython-unix/patch-configure-bolt-skip-funcs.patch
 rename cpython-unix/{patch-jit-llvm-19.patch => patch-jit-llvm-version-3.13.patch} (93%)
 create mode 100644 cpython-unix/patch-jit-llvm-version-3.14.patch

diff --git a/cpython-unix/build-cpython.sh b/cpython-unix/build-cpython.sh
index ea1b1c0a..05d1603e 100755
--- a/cpython-unix/build-cpython.sh
+++ b/cpython-unix/build-cpython.sh
@@ -270,6 +270,9 @@ if [ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_12}" ]; then
     # Additional BOLT optimizations, being upstreamed in
     # https://github.com/python/cpython/issues/128514
     patch -p1 -i ${ROOT}/patch-configure-bolt-apply-flags-128514.patch
+
+    # Tweak --skip-funcs to work with our toolchain.
+    patch -p1 -i ${ROOT}/patch-configure-bolt-skip-funcs.patch
 fi
 
 # The optimization make targets are both phony and non-phony. This leads
@@ -437,10 +440,11 @@ if [ -n "${CPYTHON_OPTIMIZED}" ]; then
         if [[ -n "${PYTHON_MEETS_MAXIMUM_VERSION_3_13}" ]]; then
             # On 3.13, LLVM 18 is hard-coded into the configure script. Override it to our toolchain
             # version.
-            patch -p1 -i "${ROOT}/patch-jit-llvm-19.patch"
+            patch -p1 -i "${ROOT}/patch-jit-llvm-version-3.13.patch"
         fi
 
          if [[ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_14}" ]]; then
+            patch -p1 -i "${ROOT}/patch-jit-llvm-version-3.14.patch"
             # On 3.14, we also use the tail calling interpreter which was incompatible with the JIT
             # until https://github.com/python/cpython/pull/129820 — backport that
             patch -p1 -i "${ROOT}/patch-jit-tail-call-compat-314-129820.patch"
diff --git a/cpython-unix/patch-configure-bolt-skip-funcs.patch b/cpython-unix/patch-configure-bolt-skip-funcs.patch
new file mode 100644
index 00000000..afc8dd95
--- /dev/null
+++ b/cpython-unix/patch-configure-bolt-skip-funcs.patch
@@ -0,0 +1,17 @@
+diff --git a/configure.ac b/configure.ac
+index 3fcb18922c5..2df614a3063 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -2227,10 +2227,8 @@ then
+     [m4_normalize("
+       [-update-debug-sections]
+ 
+-      dnl At least LLVM 19.x doesn't support computed gotos in PIC compiled code.
+-      dnl Exclude functions containing computed gotos.
+-      dnl TODO this may be fixed in LLVM 20.x via https://github.com/llvm/llvm-project/pull/120267.
+-      [-skip-funcs=_PyEval_EvalFrameDefault,sre_ucs1_match/1,sre_ucs2_match/1,sre_ucs4_match/1]
++      dnl LLVM on at least 20.1.0 crashes on this symbol. Work around.
++      [-skip-funcs=RC4_options/1]
+     ")]
+   )
+ fi
diff --git a/cpython-unix/patch-jit-llvm-19.patch b/cpython-unix/patch-jit-llvm-version-3.13.patch
similarity index 93%
rename from cpython-unix/patch-jit-llvm-19.patch
rename to cpython-unix/patch-jit-llvm-version-3.13.patch
index 1b66f119..33f81e08 100644
--- a/cpython-unix/patch-jit-llvm-19.patch
+++ b/cpython-unix/patch-jit-llvm-version-3.13.patch
@@ -6,7 +6,7 @@ diff --git a/Tools/jit/_llvm.py b/Tools/jit/_llvm.py
  import typing
  
 -_LLVM_VERSION = 18
-+_LLVM_VERSION = 19
++_LLVM_VERSION = 20
  _LLVM_VERSION_PATTERN = re.compile(rf"version\s+{_LLVM_VERSION}\.\d+\.\d+\S*\s+")
  
  _P = typing.ParamSpec("_P")
diff --git a/cpython-unix/patch-jit-llvm-version-3.14.patch b/cpython-unix/patch-jit-llvm-version-3.14.patch
new file mode 100644
index 00000000..f81e80d3
--- /dev/null
+++ b/cpython-unix/patch-jit-llvm-version-3.14.patch
@@ -0,0 +1,12 @@
+diff --git a/Tools/jit/_llvm.py b/Tools/jit/_llvm.py
+--- a/Tools/jit/_llvm.py
++++ b/Tools/jit/_llvm.py
+@@ -8,7 +8,7 @@
+ import subprocess
+ import typing
+ 
+-_LLVM_VERSION = 19
++_LLVM_VERSION = 20
+ _LLVM_VERSION_PATTERN = re.compile(rf"version\s+{_LLVM_VERSION}\.\d+\.\d+\S*\s+")
+ 
+ _P = typing.ParamSpec("_P")
diff --git a/pythonbuild/downloads.py b/pythonbuild/downloads.py
index 4a753357..6497026b 100644
--- a/pythonbuild/downloads.py
+++ b/pythonbuild/downloads.py
@@ -184,25 +184,25 @@
         "version": "14.0.3+20220508",
     },
     # Remember to update LLVM_URL in src/release.rs whenever upgrading.
-    "llvm-19-x86_64-linux": {
-        "url": "https://github.com/indygreg/toolchain-tools/releases/download/toolchain-bootstrap%2F20241231/llvm-19.1.6+20241231-gnu_only-x86_64-unknown-linux-gnu.tar.zst",
-        "size": 251277644,
-        "sha256": "900bbb464d430e960ea97150e073395ae865332ce403e7c1e8f76640cab5e852",
-        "version": "19.1.6+20241231",
+    "llvm-20-x86_64-linux": {
+        "url": "https://github.com/indygreg/toolchain-tools/releases/download/toolchain-bootstrap%2F20250308/llvm-20.1.0+20250308-gnu_only-x86_64-unknown-linux-gnu.tar.zst",
+        "size": 283261860,
+        "sha256": "41d3d74e21e064e2e59a4e89feca74d58a5e9e95f73877f3c9ed82ca95607b47",
+        "version": "20.1.0+20240308",
     },
     # Remember to update LLVM_URL in src/release.rs whenever upgrading.
     "llvm-aarch64-macos": {
-        "url": "https://github.com/indygreg/toolchain-tools/releases/download/toolchain-bootstrap%2F20241231/llvm-19.1.6+20241231-aarch64-apple-darwin.tar.zst",
-        "size": 143884729,
-        "sha256": "c0252c7ebe0b20125fe592a12d43a693fcab0bfa3bec9def6b96b97087e0f765",
-        "version": "19.1.6+20241231",
+        "url": "https://github.com/indygreg/toolchain-tools/releases/download/toolchain-bootstrap%2F20250308/llvm-20.1.0+20250308-aarch64-apple-darwin.tar.zst",
+        "size": 161006322,
+        "sha256": "9897bfaab16c930258f614250a1ade1a8f32df027181bd54a61d24b5a04e284c",
+        "version": "20.1.0+20240308",
     },
     # Remember to update LLVM_URL in src/release.rs whenever upgrading.
     "llvm-x86_64-macos": {
-        "url": "https://github.com/indygreg/toolchain-tools/releases/download/toolchain-bootstrap%2F20241231/llvm-19.1.6+20241231-x86_64-apple-darwin.tar.zst",
-        "size": 143113277,
-        "sha256": "e990dea9ff89e4202d358b477a43f2bd128b244926534b7c8bb29feeaada994e",
-        "version": "19.1.6+20241231",
+        "url": "https://github.com/indygreg/toolchain-tools/releases/download/toolchain-bootstrap%2F20250308/llvm-20.1.0+20250308-x86_64-apple-darwin.tar.zst",
+        "size": 160133882,
+        "sha256": "95cfcb79d752e81735a7a7f7c4cb5a7c16360b6e9a75658a1bd50ce0547d4ad5",
+        "version": "20.1.0+20240308",
     },
     "m4": {
         "url": "https://ftp.gnu.org/gnu/m4/m4-1.4.19.tar.xz",
diff --git a/pythonbuild/utils.py b/pythonbuild/utils.py
index 6fe5e355..1d1e8f50 100644
--- a/pythonbuild/utils.py
+++ b/pythonbuild/utils.py
@@ -434,7 +434,7 @@ def clang_toolchain(host_platform: str, target_triple: str) -> str:
         if "musl" in target_triple:
             return "llvm-14-x86_64-linux"
         else:
-            return "llvm-19-x86_64-linux"
+            return "llvm-20-x86_64-linux"
     elif host_platform == "macos":
         if platform.mac_ver()[2] == "arm64":
             return "llvm-aarch64-macos"
diff --git a/src/release.rs b/src/release.rs
index f0c70f62..49fd8a76 100644
--- a/src/release.rs
+++ b/src/release.rs
@@ -589,14 +589,14 @@ pub fn produce_install_only_stripped(tar_gz_path: &Path, llvm_dir: &Path) -> Res
 static LLVM_URL: Lazy<Url> = Lazy::new(|| {
     if cfg!(target_os = "macos") {
         if std::env::consts::ARCH == "aarch64" {
-            Url::parse("https://github.com/indygreg/toolchain-tools/releases/download/toolchain-bootstrap%2F20241231/llvm-19.1.6+20241231-aarch64-apple-darwin.tar.zst").unwrap()
+            Url::parse("https://github.com/indygreg/toolchain-tools/releases/download/toolchain-bootstrap%2F20250308/llvm-20.1.0+20250308-aarch64-apple-darwin.tar.zst").unwrap()
         } else if std::env::consts::ARCH == "x86_64" {
-            Url::parse("https://github.com/indygreg/toolchain-tools/releases/download/toolchain-bootstrap%2F20241231/llvm-19.1.6+20241231-x86_64-apple-darwin.tar.zst").unwrap()
+            Url::parse("https://github.com/indygreg/toolchain-tools/releases/download/toolchain-bootstrap%2F20250308/llvm-20.1.0+20250308-x86_64-apple-darwin.tar.zst").unwrap()
         } else {
             panic!("unsupported macOS architecture");
         }
     } else if cfg!(target_os = "linux") {
-        Url::parse("https://github.com/indygreg/toolchain-tools/releases/download/toolchain-bootstrap%2F20241231/llvm-19.1.6+20241231-gnu_only-x86_64-unknown-linux-gnu.tar.zst").unwrap()
+        Url::parse("https://github.com/indygreg/toolchain-tools/releases/download/toolchain-bootstrap%2F20250308/llvm-20.1.0+20250308-gnu_only-x86_64-unknown-linux-gnu.tar.zst").unwrap()
     } else {
         panic!("unsupported platform");
     }

From 432bcbeb5418d9919e16c28ab463912de9c1d4e3 Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Tue, 11 Mar 2025 11:49:16 -0500
Subject: [PATCH 055/157] Remove Windows artifacts with the `-shared` suffix
 (#554)

These are purely duplicative and were retained for a transition period.
---
 cpython-windows/build.py | 12 +-----------
 docs/running.rst         |  4 ++++
 src/release.rs           | 27 ---------------------------
 3 files changed, 5 insertions(+), 38 deletions(-)

diff --git a/cpython-windows/build.py b/cpython-windows/build.py
index 638a2c78..47bdc493 100644
--- a/cpython-windows/build.py
+++ b/cpython-windows/build.py
@@ -1801,22 +1801,12 @@ def main() -> None:
             release_tag = release_tag_from_git()
 
         # Create, e.g., `cpython-3.10.13+20240224-x86_64-pc-windows-msvc-pgo.tar.zst`.
-        dest_path = compress_python_archive(
+        compress_python_archive(
             tar_path,
             DIST,
             "%s-%s" % (tar_path.stem, release_tag),
         )
 
-        # Copy to, e.g., `cpython-3.10.13+20240224-x86_64-pc-windows-msvc-shared-pgo.tar.zst`.
-        # The 'shared-' prefix is no longer needed, but we're double-publishing under
-        # both names during the transition period.
-        filename: str = dest_path.name
-        if not filename.endswith("-%s-%s.tar.zst" % (args.options, release_tag)):
-            raise ValueError("expected filename to end with profile: %s" % filename)
-        filename = filename.removesuffix("-%s-%s.tar.zst" % (args.options, release_tag))
-        filename = filename + "-shared-%s-%s.tar.zst" % (args.options, release_tag)
-        shutil.copy2(dest_path, dest_path.with_name(filename))
-
 
 if __name__ == "__main__":
     sys.exit(main())
diff --git a/docs/running.rst b/docs/running.rst
index 22d3db04..d2d2dc9a 100644
--- a/docs/running.rst
+++ b/docs/running.rst
@@ -48,6 +48,8 @@ familiar with LLVM target triples, here is an overview:
    Python and extensions. These builds behave like the official Python
    for Windows distributions.
 
+   These builds are now published without the `-shared` suffix.
+
 ``*-windows-msvc-static``
    These builds of Python are statically linked.
 
@@ -57,6 +59,8 @@ familiar with LLVM target triples, here is an overview:
 
    See :ref:`quirk_windows_static_distributions` for more.
 
+   These builds are no longer published.
+
 ``x86_64-unknown-linux-gnu``
    Linux 64-bit Intel/AMD CPUs linking against GNU libc.
 
diff --git a/src/release.rs b/src/release.rs
index 49fd8a76..b645d8d1 100644
--- a/src/release.rs
+++ b/src/release.rs
@@ -130,33 +130,6 @@ pub static RELEASE_TRIPLES: Lazy<BTreeMap<&'static str, TripleRelease>> = Lazy::
         },
     );
 
-    // The 'shared-' prefix is no longer needed, but we're double-publishing under both names during
-    // the transition period.
-    h.insert(
-        "i686-pc-windows-msvc-shared",
-        TripleRelease {
-            suffixes: vec!["pgo"],
-            install_only_suffix: "pgo",
-            python_version_requirement: None,
-            conditional_suffixes: vec![ConditionalSuffixes {
-                python_version_requirement: VersionSpecifier::from_str(">=3.13").unwrap(),
-                suffixes: vec!["freethreaded+pgo"],
-            }],
-        },
-    );
-    h.insert(
-        "x86_64-pc-windows-msvc-shared",
-        TripleRelease {
-            suffixes: vec!["pgo"],
-            install_only_suffix: "pgo",
-            python_version_requirement: None,
-            conditional_suffixes: vec![ConditionalSuffixes {
-                python_version_requirement: VersionSpecifier::from_str(">=3.13").unwrap(),
-                suffixes: vec!["freethreaded+pgo"],
-            }],
-        },
-    );
-
     // Linux.
     let linux_suffixes_pgo = vec!["debug", "pgo+lto"];
     let linux_suffixes_nopgo = vec!["debug", "lto", "noopt"];

From 08c1fac51ad40c25ba487f272565604d28ba22d8 Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Tue, 11 Mar 2025 11:50:56 -0500
Subject: [PATCH 056/157] Add dynamically linked musl distributions (#541)

As a consequence of #540 I was playing with these concepts and decided
to explore it.

This includes #546 (could be merged separately or together), which
separates "static" builds from the "musl" triple specifically in favor
of a dedicated build option.

The main implementation downside here is that `$ORIGIN` doesn't work
with DT_NEEDED so we need to use RUNPATH instead, which can cause the
wrong library to be loaded if LD_LIBRARY_PATH is set. Given the current
builds aren't usable at all, I think this is a fine trade-off. We can
explore alternatives in the future, like statically linking just
libpython.

Another caveat here: for consistency with the glibc builds, we're
changing the "default" musl build to be dynamically linked. This is a
breaking change in the release artifacts. The statically linked musl
build will include a `+static` suffix. We could do something for
backwards compatibility here, but I _think_ this probably makes sense in
the long term. My primary concern is that consumers that combine
releases (such as uv) would need to encode this change (e.g., toggle the
expectation based on the python-build-standalone version tag).

It's challenging to test changes to the release artifact handling.
Regardless of approach, this will need a follow-up to adjust that
accordingly.
---
 .github/workflows/linux.yml     | 14 ++++++
 ci-targets.yaml                 | 12 +++++
 cpython-unix/build-cpython.sh   | 61 +++++++++++++++++--------
 cpython-unix/build-libX11.sh    | 24 ++++++++++
 cpython-unix/build-main.py      |  9 +++-
 cpython-unix/build-musl.sh      | 54 ++++++++++++++++++++--
 cpython-unix/build-tcl.sh       |  9 ++++
 cpython-unix/build-xextproto.sh | 13 +++++-
 cpython-unix/build-xproto.sh    | 13 +++++-
 cpython-unix/build.py           | 80 ++++++++++++++++++++++++---------
 pythonbuild/buildenv.py         | 10 ++++-
 pythonbuild/cpython.py          | 12 ++---
 pythonbuild/docker.py           |  7 +--
 pythonbuild/downloads.py        |  8 ++++
 src/validation.rs               | 60 ++++++++++++++++---------
 src/verify_distribution.py      |  3 +-
 16 files changed, 309 insertions(+), 80 deletions(-)

diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml
index 7445e80b..e7281574 100644
--- a/.github/workflows/linux.yml
+++ b/.github/workflows/linux.yml
@@ -240,6 +240,13 @@ jobs:
           chmod +x build/pythonbuild
 
           if [ "${{ matrix.run }}" == "true" ]; then
+            if [ "${{ matrix.libc }}" == "musl" ]; then
+              sudo apt install musl-dev
+
+              # GitHub's setup-python action sets `LD_LIBRARY_PATH` which overrides `RPATH`
+              # as used in the musl builds.
+              unset LD_LIBRARY_PATH
+            fi
             EXTRA_ARGS="--run"
           fi
 
@@ -324,6 +331,13 @@ jobs:
           chmod +x build/pythonbuild
 
           if [ "${{ matrix.run }}" == "true" ]; then
+            if [ "${{ matrix.libc }}" == "musl" ]; then
+              sudo apt install musl-dev
+
+              # GitHub's setup-python action sets `LD_LIBRARY_PATH` which overrides `RPATH`
+              # as used in the musl builds.
+              unset LD_LIBRARY_PATH
+            fi
             EXTRA_ARGS="--run"
           fi
 
diff --git a/ci-targets.yaml b/ci-targets.yaml
index ec08bd9a..cd892ac9 100644
--- a/ci-targets.yaml
+++ b/ci-targets.yaml
@@ -257,6 +257,9 @@ linux:
       - "3.12"
       - "3.13"
     build_options:
+      - debug+static
+      - noopt+static
+      - lto+static
       - debug
       - noopt
       - lto
@@ -273,6 +276,9 @@ linux:
       - "3.12"
       - "3.13"
     build_options:
+      - debug+static
+      - noopt+static
+      - lto+static
       - debug
       - noopt
       - lto
@@ -289,6 +295,9 @@ linux:
       - "3.12"
       - "3.13"
     build_options:
+      - debug+static
+      - noopt+static
+      - lto+static
       - debug
       - noopt
       - lto
@@ -305,6 +314,9 @@ linux:
       - "3.12"
       - "3.13"
     build_options:
+      - debug+static
+      - noopt+static
+      - lto+static
       - debug
       - noopt
       - lto
diff --git a/cpython-unix/build-cpython.sh b/cpython-unix/build-cpython.sh
index 05d1603e..350be3cf 100755
--- a/cpython-unix/build-cpython.sh
+++ b/cpython-unix/build-cpython.sh
@@ -384,12 +384,8 @@ CONFIGURE_FLAGS="
     --without-ensurepip
     ${EXTRA_CONFIGURE_FLAGS}"
 
-if [ "${CC}" = "musl-clang" ]; then
-    CFLAGS="${CFLAGS} -static"
-    CPPFLAGS="${CPPFLAGS} -static"
-    LDFLAGS="${LDFLAGS} -static"
-    PYBUILD_SHARED=0
 
+if [ "${CC}" = "musl-clang" ]; then
     # In order to build the _blake2 extension module with SSE3+ instructions, we need
     # musl-clang to find headers that provide access to the intrinsics, as they are not
     # provided by musl. These are part of the include files that are part of clang.
@@ -403,6 +399,13 @@ if [ "${CC}" = "musl-clang" ]; then
         fi
         cp "$h" /tools/host/include/
     done
+fi
+
+if [ -n "${CPYTHON_STATIC}" ]; then
+    CFLAGS="${CFLAGS} -static"
+    CPPFLAGS="${CPPFLAGS} -static"
+    LDFLAGS="${LDFLAGS} -static"
+    PYBUILD_SHARED=0 
 else
     CONFIGURE_FLAGS="${CONFIGURE_FLAGS} --enable-shared"
     PYBUILD_SHARED=1
@@ -644,21 +647,41 @@ if [ "${PYBUILD_SHARED}" = "1" ]; then
         LIBPYTHON_SHARED_LIBRARY_BASENAME=libpython${PYTHON_MAJMIN_VERSION}${PYTHON_BINARY_SUFFIX}.so.1.0
         LIBPYTHON_SHARED_LIBRARY=${ROOT}/out/python/install/lib/${LIBPYTHON_SHARED_LIBRARY_BASENAME}
 
-        # If we simply set DT_RUNPATH via --set-rpath, LD_LIBRARY_PATH would be used before
-        # DT_RUNPATH, which could result in confusion at run-time. But if DT_NEEDED
-        # contains a slash, the explicit path is used.
-        patchelf --replace-needed ${LIBPYTHON_SHARED_LIBRARY_BASENAME} "\$ORIGIN/../lib/${LIBPYTHON_SHARED_LIBRARY_BASENAME}" \
-            ${ROOT}/out/python/install/bin/python${PYTHON_MAJMIN_VERSION}
-
-        # libpython3.so isn't present in debug builds.
-        if [ -z "${CPYTHON_DEBUG}" ]; then
-            patchelf --replace-needed ${LIBPYTHON_SHARED_LIBRARY_BASENAME} "\$ORIGIN/../lib/${LIBPYTHON_SHARED_LIBRARY_BASENAME}" \
-                ${ROOT}/out/python/install/lib/libpython3.so
-        fi
-
-        if [ -n "${PYTHON_BINARY_SUFFIX}" ]; then
+        if [ "${CC}" == "musl-clang" ]; then
+            # musl does not support $ORIGIN in DT_NEEDED, so we use RPATH instead. This could be
+            # problematic, i.e., we could load the shared library from the wrong location if
+            # `LD_LIBRARY_PATH` is set, but there's not a clear alternative at this time. The
+            # long term solution is probably to statically link to libpython instead.
+            patchelf --set-rpath "\$ORIGIN/../lib" \
+                ${ROOT}/out/python/install/bin/python${PYTHON_MAJMIN_VERSION}
+
+            # libpython3.so isn't present in debug builds.
+            if [ -z "${CPYTHON_DEBUG}" ]; then
+                patchelf --set-rpath "\$ORIGIN/../lib" \
+                    ${ROOT}/out/python/install/lib/libpython3.so
+            fi
+
+            if [ -n "${PYTHON_BINARY_SUFFIX}" ]; then
+                patchelf --set-rpath "\$ORIGIN/../lib" \
+                    ${ROOT}/out/python/install/bin/python${PYTHON_MAJMIN_VERSION}${PYTHON_BINARY_SUFFIX}
+            fi
+        else
+            # If we simply set DT_RUNPATH via --set-rpath, LD_LIBRARY_PATH would be used before
+            # DT_RUNPATH, which could result in confusion at run-time. But if DT_NEEDED contains a
+            # slash, the explicit path is used.
             patchelf --replace-needed ${LIBPYTHON_SHARED_LIBRARY_BASENAME} "\$ORIGIN/../lib/${LIBPYTHON_SHARED_LIBRARY_BASENAME}" \
-                ${ROOT}/out/python/install/bin/python${PYTHON_MAJMIN_VERSION}${PYTHON_BINARY_SUFFIX}
+                ${ROOT}/out/python/install/bin/python${PYTHON_MAJMIN_VERSION}
+
+            # libpython3.so isn't present in debug builds.
+            if [ -z "${CPYTHON_DEBUG}" ]; then
+                patchelf --replace-needed ${LIBPYTHON_SHARED_LIBRARY_BASENAME} "\$ORIGIN/../lib/${LIBPYTHON_SHARED_LIBRARY_BASENAME}" \
+                    ${ROOT}/out/python/install/lib/libpython3.so
+            fi
+
+            if [ -n "${PYTHON_BINARY_SUFFIX}" ]; then
+                patchelf --replace-needed ${LIBPYTHON_SHARED_LIBRARY_BASENAME} "\$ORIGIN/../lib/${LIBPYTHON_SHARED_LIBRARY_BASENAME}" \
+                    ${ROOT}/out/python/install/bin/python${PYTHON_MAJMIN_VERSION}${PYTHON_BINARY_SUFFIX}
+            fi
         fi
     fi
 fi
diff --git a/cpython-unix/build-libX11.sh b/cpython-unix/build-libX11.sh
index 6870514c..e8f65ad4 100755
--- a/cpython-unix/build-libX11.sh
+++ b/cpython-unix/build-libX11.sh
@@ -75,6 +75,30 @@ if [ -n "${CROSS_COMPILING}" ]; then
     s390x-unknown-linux-gnu)
       EXTRA_FLAGS="${EXTRA_FLAGS} --enable-malloc0returnsnull"
       ;;
+    x86_64-unknown-linux-musl)
+      EXTRA_FLAGS="${EXTRA_FLAGS} --enable-malloc0returnsnull"
+      ;;
+    aarch64-unknown-linux-musl)
+      EXTRA_FLAGS="${EXTRA_FLAGS} --enable-malloc0returnsnull"
+      ;;
+    i686-unknown-linux-musl)
+      EXTRA_FLAGS="${EXTRA_FLAGS} --enable-malloc0returnsnull"
+      ;;
+    mips-unknown-linux-musl)
+      EXTRA_FLAGS="${EXTRA_FLAGS} --enable-malloc0returnsnull"
+      ;;
+    mipsel-unknown-linux-musl)
+      EXTRA_FLAGS="${EXTRA_FLAGS} --enable-malloc0returnsnull"
+      ;;
+    ppc64le-unknown-linux-musl)
+      EXTRA_FLAGS="${EXTRA_FLAGS} --enable-malloc0returnsnull"
+      ;;
+    riscv64-unknown-linux-musl)
+      EXTRA_FLAGS="${EXTRA_FLAGS} --enable-malloc0returnsnull"
+      ;;
+    s390x-unknown-linux-musl)
+      EXTRA_FLAGS="${EXTRA_FLAGS} --enable-malloc0returnsnull"
+      ;;
     *)
       echo "cross-compiling but malloc(0) override not set; failures possible"
       ;;
diff --git a/cpython-unix/build-main.py b/cpython-unix/build-main.py
index dd4d2d7c..6bf91b49 100755
--- a/cpython-unix/build-main.py
+++ b/cpython-unix/build-main.py
@@ -45,6 +45,7 @@ def main():
         print("Unsupported build platform: %s" % sys.platform)
         return 1
 
+    # Note these arguments must be synced with `build.py`
     parser = argparse.ArgumentParser()
 
     parser.add_argument(
@@ -54,10 +55,14 @@ def main():
         help="Target host triple to build for",
     )
 
-    optimizations = {"debug", "noopt", "pgo", "lto", "pgo+lto"}
+    # Construct possible options, we use a set here for canonical ordering
+    options = set()
+    options.update({"debug", "noopt", "pgo", "lto", "pgo+lto"})
+    options.update({f"freethreaded+{option}" for option in options})
+    options.update({f"{option}+static" for option in options})
     parser.add_argument(
         "--options",
-        choices=optimizations.union({f"freethreaded+{o}" for o in optimizations}),
+        choices=options,
         default="noopt",
         help="Build options to apply when compiling Python",
     )
diff --git a/cpython-unix/build-musl.sh b/cpython-unix/build-musl.sh
index 1bf075ce..e31691e7 100755
--- a/cpython-unix/build-musl.sh
+++ b/cpython-unix/build-musl.sh
@@ -3,7 +3,7 @@
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at https://mozilla.org/MPL/2.0/.
 
-set -e
+set -ex
 
 cd /build
 
@@ -18,7 +18,43 @@ pushd musl-${MUSL_VERSION}
 # added reallocarray(), which gets used by at least OpenSSL.
 # Here, we disable this single function so as to not introduce
 # symbol dependencies on clients using an older musl version.
-patch -p1 <<EOF
+if [ "${MUSL_VERSION}" = "1.2.2" ]; then
+    patch -p1 <<EOF
+diff --git a/include/stdlib.h b/include/stdlib.h
+index b54a051f..194c2033 100644
+--- a/include/stdlib.h
++++ b/include/stdlib.h
+@@ -145,7 +145,6 @@ int getloadavg(double *, int);
+ int clearenv(void);
+ #define WCOREDUMP(s) ((s) & 0x80)
+ #define WIFCONTINUED(s) ((s) == 0xffff)
+-void *reallocarray (void *, size_t, size_t);
+ #endif
+ 
+ #ifdef _GNU_SOURCE
+diff --git a/src/malloc/reallocarray.c b/src/malloc/reallocarray.c
+deleted file mode 100644
+index 4a6ebe46..00000000
+--- a/src/malloc/reallocarray.c
++++ /dev/null
+@@ -1,13 +0,0 @@
+-#define _BSD_SOURCE
+-#include <errno.h>
+-#include <stdlib.h>
+-
+-void *reallocarray(void *ptr, size_t m, size_t n)
+-{
+-	if (n && m > -1 / n) {
+-		errno = ENOMEM;
+-		return 0;
+-	}
+-
+-	return realloc(ptr, m * n);
+-}
+EOF
+else
+    # There is a different patch for newer musl versions, used in static distributions
+    patch -p1 <<EOF
 diff --git a/include/stdlib.h b/include/stdlib.h
 index b507ca3..8259e27 100644
 --- a/include/stdlib.h
@@ -51,10 +87,20 @@ index 4a6ebe4..0000000
 -	return realloc(ptr, m * n);
 -}
 EOF
+fi
+
+SHARED=
+if [ -n "${STATIC}" ]; then
+    SHARED="--disable-shared"
+else
+    SHARED="--enable-shared"
+    CFLAGS="${CFLAGS} -fPIC" CPPFLAGS="${CPPFLAGS} -fPIC"
+fi
+
 
-./configure \
+CFLAGS="${CFLAGS}" CPPFLAGS="${CPPFLAGS}" ./configure \
     --prefix=/tools/host \
-    --disable-shared
+    "${SHARED}"
 
 make -j `nproc`
 make -j `nproc` install DESTDIR=/build/out
diff --git a/cpython-unix/build-tcl.sh b/cpython-unix/build-tcl.sh
index f2650f3e..43a4a6ad 100755
--- a/cpython-unix/build-tcl.sh
+++ b/cpython-unix/build-tcl.sh
@@ -13,6 +13,15 @@ export PKG_CONFIG_PATH=${TOOLS_PATH}/deps/share/pkgconfig:${TOOLS_PATH}/deps/lib
 tar -xf tcl${TCL_VERSION}-src.tar.gz
 pushd tcl${TCL_VERSION}
 
+
+if [ -n "${STATIC}" ]; then
+	if echo "${TARGET_TRIPLE}" | grep -q -- "-unknown-linux-musl"; then
+		# tcl misbehaves when performing static musl builds
+		# `checking whether musl-clang accepts -g...` fails with a duplicate definition error
+		TARGET_TRIPLE="$(echo "${TARGET_TRIPLE}" | sed -e 's/-unknown-linux-musl/-unknown-linux-gnu/g')"
+	fi
+fi
+
 patch -p1 << 'EOF'
 diff --git a/unix/Makefile.in b/unix/Makefile.in
 --- a/unix/Makefile.in
diff --git a/cpython-unix/build-xextproto.sh b/cpython-unix/build-xextproto.sh
index fba2bd8f..090e3f0e 100755
--- a/cpython-unix/build-xextproto.sh
+++ b/cpython-unix/build-xextproto.sh
@@ -15,10 +15,21 @@ export PKG_CONFIG_PATH=/tools/deps/share/pkgconfig
 tar -xf xextproto-${XEXTPROTO_VERSION}.tar.gz
 pushd xextproto-${XEXTPROTO_VERSION}
 
+EXTRA_CONFIGURE_FLAGS=
+if [ -n "${CROSS_COMPILING}" ]; then
+    if echo "${TARGET_TRIPLE}" | grep -q -- "-unknown-linux-musl"; then
+    # xextproto does not support configuration of musl targets so we pretend the target matches the
+    # build triple and enable cross-compilation manually
+    TARGET_TRIPLE="$(echo "${TARGET_TRIPLE}" | sed -e 's/-unknown-linux-musl/-unknown-linux-gnu/g')"
+    EXTRA_CONFIGURE_FLAGS="cross_compiling=yes"
+    fi
+fi
+
 CFLAGS="${EXTRA_TARGET_CFLAGS} -fPIC" CPPFLAGS="${EXTRA_TARGET_CFLAGS} -fPIC" LDFLAGS="${EXTRA_TARGET_LDFLAGS}" ./configure \
     --build=${BUILD_TRIPLE} \
     --host=${TARGET_TRIPLE} \
-    --prefix=/tools/deps
+    --prefix=/tools/deps \
+    ${EXTRA_CONFIGURE_FLAGS}
 
 make -j `nproc`
 make -j `nproc` install DESTDIR=${ROOT}/out
diff --git a/cpython-unix/build-xproto.sh b/cpython-unix/build-xproto.sh
index d126ec01..6f3d2b6b 100755
--- a/cpython-unix/build-xproto.sh
+++ b/cpython-unix/build-xproto.sh
@@ -15,10 +15,21 @@ export PKG_CONFIG_PATH=${TOOLS_PATH}/deps/share/pkgconfig
 tar -xf xproto-${XPROTO_VERSION}.tar.gz
 pushd xproto-${XPROTO_VERSION}
 
+EXTRA_CONFIGURE_FLAGS=
+if [ -n "${CROSS_COMPILING}" ]; then
+    if echo "${TARGET_TRIPLE}" | grep -q -- "-unknown-linux-musl"; then
+    # xproto does not support configuration of musl targets so we pretend the target matches the
+    # build triple and enable cross-compilation manually
+    TARGET_TRIPLE="$(echo "${TARGET_TRIPLE}" | sed -e 's/-unknown-linux-musl/-unknown-linux-gnu/g')"
+    EXTRA_CONFIGURE_FLAGS="cross_compiling=yes"
+    fi
+fi
+
 CFLAGS="${EXTRA_TARGET_CFLAGS} -fPIC" CPPFLAGS="${EXTRA_TARGET_CFLAGS} -fPIC" LDFLAGS="${EXTRA_TARGET_LDFLAGS}" ./configure \
     --build=${BUILD_TRIPLE} \
     --host=${TARGET_TRIPLE} \
-    --prefix=/tools/deps
+    --prefix=/tools/deps \
+    ${EXTRA_CONFIGURE_FLAGS}
 
 make -j ${NUM_CPUS}
 make -j ${NUM_CPUS} install DESTDIR=${ROOT}/out
diff --git a/cpython-unix/build.py b/cpython-unix/build.py
index 97ceaebb..b34a1efe 100755
--- a/cpython-unix/build.py
+++ b/cpython-unix/build.py
@@ -123,8 +123,6 @@ def add_target_env(env, build_platform, target_triple, build_env):
             target_triple.replace("x86_64_v2-", "x86_64-")
             .replace("x86_64_v3-", "x86_64-")
             .replace("x86_64_v4-", "x86_64-")
-            # TODO should the musl target be normalized?
-            .replace("-unknown-linux-musl", "-unknown-linux-gnu")
         )
 
         # This will make x86_64_v2, etc count as cross-compiling. This is
@@ -260,6 +258,7 @@ def simple_build(
                 binutils=install_binutils(host_platform),
                 clang=True,
                 musl="musl" in target_triple,
+                static="static" in build_options,
             )
 
         for a in extra_archives or []:
@@ -274,6 +273,9 @@ def simple_build(
             ]["version"],
         }
 
+        if "static" in build_options:
+            env["STATIC"] = 1
+
         add_target_env(env, host_platform, target_triple, build_env)
 
         if entry in ("openssl-1.1", "openssl-3.0"):
@@ -325,26 +327,34 @@ def materialize_clang(host_platform: str, target_triple: str):
             dctx.copy_stream(ifh, ofh)
 
 
-def build_musl(client, image, host_platform: str, target_triple: str):
-    musl_archive = download_entry("musl", DOWNLOADS_PATH)
+def build_musl(client, image, host_platform: str, target_triple: str, build_options):
+    static = "static" in build_options
+    musl = "musl-static" if static else "musl"
+    musl_archive = download_entry(musl, DOWNLOADS_PATH)
 
     with build_environment(client, image) as build_env:
         build_env.install_toolchain(
-            BUILD, host_platform, target_triple, binutils=True, clang=True
+            BUILD,
+            host_platform,
+            target_triple,
+            binutils=True,
+            clang=True,
+            static=False,
         )
         build_env.copy_file(musl_archive)
         build_env.copy_file(SUPPORT / "build-musl.sh")
 
         env = {
-            "MUSL_VERSION": DOWNLOADS["musl"]["version"],
+            "MUSL_VERSION": DOWNLOADS[musl]["version"],
             "TOOLCHAIN": "llvm",
         }
 
+        if static:
+            env["STATIC"] = 1
+
         build_env.run("build-musl.sh", environment=env)
 
-        build_env.get_tools_archive(
-            toolchain_archive_path("musl", host_platform), "host"
-        )
+        build_env.get_tools_archive(toolchain_archive_path(musl, host_platform), "host")
 
 
 def build_libedit(
@@ -361,6 +371,7 @@ def build_libedit(
                 binutils=install_binutils(host_platform),
                 clang=True,
                 musl="musl" in target_triple,
+                static="static" in build_options,
             )
 
         build_env.install_artifact_archive(
@@ -395,6 +406,7 @@ def build_tix(
                 binutils=install_binutils(host_platform),
                 clang=True,
                 musl="musl" in target_triple,
+                static="static" in build_options,
             )
 
         depends = {"tcl", "tk"}
@@ -441,6 +453,7 @@ def build_cpython_host(
             target_triple,
             binutils=install_binutils(host_platform),
             clang=True,
+            static="static" in build_options,
         )
 
         build_env.copy_file(archive)
@@ -491,6 +504,7 @@ def python_build_info(
     target_triple,
     musl,
     lto,
+    static,
     extensions,
     extra_metadata,
 ):
@@ -509,7 +523,7 @@ def python_build_info(
             )
         )
 
-        if not musl:
+        if not static:
             bi["core"]["shared_lib"] = "install/lib/libpython%s%s.so.1.0" % (
                 version,
                 binary_suffix,
@@ -738,6 +752,7 @@ def build_cpython(
         python_archive,
         python_version=python_version,
         target_triple=target_triple,
+        build_options=parsed_build_options,
         extension_modules=ems,
     )
 
@@ -754,6 +769,7 @@ def build_cpython(
                 binutils=install_binutils(host_platform),
                 clang=True,
                 musl="musl" in target_triple,
+                static="static" in build_options,
             )
 
         packages = target_needs(TARGETS_CONFIG, target_triple, python_version)
@@ -828,6 +844,8 @@ def build_cpython(
             env["CPYTHON_OPTIMIZED"] = "1"
         if "lto" in parsed_build_options:
             env["CPYTHON_LTO"] = "1"
+        if "static" in parsed_build_options:
+            env["CPYTHON_STATIC"] = "1"
 
         add_target_env(env, host_platform, target_triple, build_env)
 
@@ -837,19 +855,28 @@ def build_cpython(
         crt_features = []
 
         if host_platform == "linux64":
-            if "musl" in target_triple:
+            if "static" in parsed_build_options:
                 crt_features.append("static")
             else:
                 extension_module_loading.append("shared-library")
-                crt_features.append("glibc-dynamic")
 
-                glibc_max_version = build_env.get_file("glibc_version.txt").strip()
-                if not glibc_max_version:
-                    raise Exception("failed to retrieve glibc max symbol version")
+                if "musl" in target_triple:
+                    crt_features.append("musl-dynamic")
 
-                crt_features.append(
-                    "glibc-max-symbol-version:%s" % glibc_max_version.decode("ascii")
-                )
+                    musl_version = DOWNLOADS["musl"]["version"]
+                    crt_features.append("musl-version:%s" % musl_version)
+
+                else:
+                    crt_features.append("glibc-dynamic")
+
+                    glibc_max_version = build_env.get_file("glibc_version.txt").strip()
+                    if not glibc_max_version:
+                        raise Exception("failed to retrieve glibc max symbol version")
+
+                    crt_features.append(
+                        "glibc-max-symbol-version:%s"
+                        % glibc_max_version.decode("ascii")
+                    )
 
             python_symbol_visibility = "global-default"
 
@@ -877,7 +904,9 @@ def build_cpython(
             "python_stdlib_test_packages": sorted(STDLIB_TEST_PACKAGES),
             "python_symbol_visibility": python_symbol_visibility,
             "python_extension_module_loading": extension_module_loading,
-            "libpython_link_mode": "static" if "musl" in target_triple else "shared",
+            "libpython_link_mode": (
+                "static" if "static" in parsed_build_options else "shared"
+            ),
             "crt_features": crt_features,
             "run_tests": "build/run_tests.py",
             "build_info": python_build_info(
@@ -887,6 +916,7 @@ def build_cpython(
                 target_triple,
                 "musl" in target_triple,
                 "lto" in parsed_build_options,
+                "static" in parsed_build_options,
                 enabled_extensions,
                 extra_metadata,
             ),
@@ -949,6 +979,7 @@ def main():
             print("unable to connect to Docker: %s" % e, file=sys.stderr)
             return 1
 
+    # Note these arguments must be synced with `build-main.py`
     parser = argparse.ArgumentParser()
     parser.add_argument(
         "--host-platform", required=True, help="Platform we are building from"
@@ -958,13 +989,19 @@ def main():
         required=True,
         help="Host triple that we are building Python for",
     )
-    optimizations = {"debug", "noopt", "pgo", "lto", "pgo+lto"}
+
+    # Construct possible options
+    options = set()
+    options.update({"debug", "noopt", "pgo", "lto", "pgo+lto"})
+    options.update({f"freethreaded+{option}" for option in options})
+    options.update({f"{option}+static" for option in options})
     parser.add_argument(
         "--options",
-        choices=optimizations.union({f"freethreaded+{o}" for o in optimizations}),
+        choices=options,
         default="noopt",
         help="Build options to apply when compiling Python",
     )
+
     parser.add_argument(
         "--toolchain",
         action="store_true",
@@ -1053,6 +1090,7 @@ def main():
                 get_image(client, ROOT, BUILD, "gcc"),
                 host_platform,
                 target_triple,
+                build_options,
             )
 
         elif action == "autoconf":
diff --git a/pythonbuild/buildenv.py b/pythonbuild/buildenv.py
index 65da541a..4b2a0e6e 100644
--- a/pythonbuild/buildenv.py
+++ b/pythonbuild/buildenv.py
@@ -76,6 +76,7 @@ def install_toolchain(
         binutils=False,
         musl=False,
         clang=False,
+        static=False,
     ):
         if binutils:
             self.install_toolchain_archive(build_dir, "binutils", host_platform)
@@ -86,7 +87,9 @@ def install_toolchain(
             )
 
         if musl:
-            self.install_toolchain_archive(build_dir, "musl", host_platform)
+            self.install_toolchain_archive(
+                build_dir, "musl-static" if static else "musl", host_platform
+            )
 
     def run(self, program, user="build", environment=None):
         if isinstance(program, str) and not program.startswith("/"):
@@ -197,6 +200,7 @@ def install_toolchain(
         binutils=False,
         musl=False,
         clang=False,
+        static=False,
     ):
         if binutils:
             self.install_toolchain_archive(build_dir, "binutils", platform)
@@ -207,7 +211,9 @@ def install_toolchain(
             )
 
         if musl:
-            self.install_toolchain_archive(build_dir, "musl", platform)
+            self.install_toolchain_archive(
+                build_dir, "musl-static" if static else "musl", platform
+            )
 
     def run(self, program, user="build", environment=None):
         if user != "build":
diff --git a/pythonbuild/cpython.py b/pythonbuild/cpython.py
index 50ad6f70..e59eecd3 100644
--- a/pythonbuild/cpython.py
+++ b/pythonbuild/cpython.py
@@ -227,6 +227,7 @@ def derive_setup_local(
     cpython_source_archive,
     python_version,
     target_triple,
+    build_options,
     extension_modules,
 ):
     """Derive the content of the Modules/Setup.local file."""
@@ -466,12 +467,11 @@ def derive_setup_local(
             enabled_extensions[name]["setup_line"] = name.encode("ascii")
             continue
 
-        # musl is static only. Ignore build-mode override.
-        if "musl" in target_triple:
-            section = "static"
-        else:
-            section = info.get("build-mode", "static")
-
+        # Force static linking if we're doing a fully static build, otherwise,
+        # respect the `build-mode` falling back to `static` if not defined.
+        section = (
+            "static" if "static" in build_options else info.get("build-mode", "static")
+        )
         enabled_extensions[name]["build-mode"] = section
 
         # Presumably this means the extension comes from the distribution's
diff --git a/pythonbuild/docker.py b/pythonbuild/docker.py
index 5428ce17..4269b2bd 100644
--- a/pythonbuild/docker.py
+++ b/pythonbuild/docker.py
@@ -158,9 +158,10 @@ def container_get_archive(container, path):
 
     new_data = io.BytesIO()
 
-    with tarfile.open(fileobj=old_data) as itf, tarfile.open(
-        fileobj=new_data, mode="w"
-    ) as otf:
+    with (
+        tarfile.open(fileobj=old_data) as itf,
+        tarfile.open(fileobj=new_data, mode="w") as otf,
+    ):
         for member in sorted(itf.getmembers(), key=operator.attrgetter("name")):
             file_data = itf.extractfile(member) if not member.linkname else None
             member.mtime = DEFAULT_MTIME
diff --git a/pythonbuild/downloads.py b/pythonbuild/downloads.py
index 6497026b..0340a68a 100644
--- a/pythonbuild/downloads.py
+++ b/pythonbuild/downloads.py
@@ -219,7 +219,15 @@
         "licenses": ["BSD-2-Clause"],
         "license_file": "LICENSE.mpdecimal.txt",
     },
+    # The musl toolchain for shared / dynamically linked builds
     "musl": {
+        "url": "https://musl.libc.org/releases/musl-1.2.2.tar.gz",
+        "size": 1055220,
+        "sha256": "9b969322012d796dc23dda27a35866034fa67d8fb67e0e2c45c913c3d43219dd",
+        "version": "1.2.2",
+    },
+    # The musl toolchain for static builds
+    "musl-static": {
         "url": "https://musl.libc.org/releases/musl-1.2.5.tar.gz",
         "size": 1080786,
         "sha256": "a9a118bbe84d8764da0ea0d28b3ab3fae8477fc7e4085d90102b8596fc7c75e4",
diff --git a/src/validation.rs b/src/validation.rs
index 4bb28de0..df0c940f 100644
--- a/src/validation.rs
+++ b/src/validation.rs
@@ -918,22 +918,38 @@ fn validate_elf<Elf: FileHeader<Endian = Endianness>>(
         allowed_libraries.extend(extra.iter().map(|x| x.to_string()));
     }
 
-    allowed_libraries.push(format!(
-        "$ORIGIN/../lib/libpython{}.so.1.0",
-        python_major_minor
-    ));
-    allowed_libraries.push(format!(
-        "$ORIGIN/../lib/libpython{}d.so.1.0",
-        python_major_minor
-    ));
-    allowed_libraries.push(format!(
-        "$ORIGIN/../lib/libpython{}t.so.1.0",
-        python_major_minor
-    ));
-    allowed_libraries.push(format!(
-        "$ORIGIN/../lib/libpython{}td.so.1.0",
-        python_major_minor
-    ));
+    if json.libpython_link_mode == "shared" {
+        if target_triple.contains("-musl") {
+            // On musl, we link to `libpython` and rely on `RUN PATH`
+            allowed_libraries.push(format!("libpython{}.so.1.0", python_major_minor));
+            allowed_libraries.push(format!("libpython{}d.so.1.0", python_major_minor));
+            allowed_libraries.push(format!("libpython{}t.so.1.0", python_major_minor));
+            allowed_libraries.push(format!("libpython{}td.so.1.0", python_major_minor));
+        } else {
+            // On glibc, we can use `$ORIGIN` for relative, reloctable linking
+            allowed_libraries.push(format!(
+                "$ORIGIN/../lib/libpython{}.so.1.0",
+                python_major_minor
+            ));
+            allowed_libraries.push(format!(
+                "$ORIGIN/../lib/libpython{}d.so.1.0",
+                python_major_minor
+            ));
+            allowed_libraries.push(format!(
+                "$ORIGIN/../lib/libpython{}t.so.1.0",
+                python_major_minor
+            ));
+            allowed_libraries.push(format!(
+                "$ORIGIN/../lib/libpython{}td.so.1.0",
+                python_major_minor
+            ));
+        }
+    }
+
+    if !json.build_options.contains("static") && target_triple.contains("-musl") {
+        // Allow linking musl `libc`
+        allowed_libraries.push("libc.so".to_string());
+    }
 
     // Allow the _crypt extension module - and only it - to link against libcrypt,
     // which is no longer universally present in Linux distros.
@@ -1719,8 +1735,7 @@ fn validate_distribution(
     };
 
     let is_debug = dist_filename.contains("-debug-");
-
-    let is_static = triple.contains("unknown-linux-musl");
+    let is_static = dist_filename.contains("+static");
 
     let mut tf = crate::open_distribution_archive(dist_path)?;
 
@@ -2074,12 +2089,17 @@ fn verify_distribution_behavior(dist_path: &Path) -> Result<Vec<String>> {
     std::fs::write(&test_file, PYTHON_VERIFICATIONS.as_bytes())?;
 
     eprintln!("  running interpreter tests (output should follow)");
-    let output = duct::cmd(python_exe, [test_file.display().to_string()])
+    let output = duct::cmd(&python_exe, [test_file.display().to_string()])
         .stdout_to_stderr()
         .unchecked()
         .env("TARGET_TRIPLE", &python_json.target_triple)
         .env("BUILD_OPTIONS", &python_json.build_options)
-        .run()?;
+        .run()
+        .context(format!(
+            "Failed to run `{} {}`",
+            python_exe.display(),
+            test_file.display()
+        ))?;
 
     if !output.status.success() {
         errors.push("errors running interpreter tests".to_string());
diff --git a/src/verify_distribution.py b/src/verify_distribution.py
index 46ac48c6..2131d7aa 100644
--- a/src/verify_distribution.py
+++ b/src/verify_distribution.py
@@ -53,7 +53,8 @@ def test_ctypes(self):
         import ctypes
 
         # pythonapi will be None on statically linked binaries.
-        if os.environ["TARGET_TRIPLE"].endswith("-unknown-linux-musl"):
+        is_static = "static" in os.environ["BUILD_OPTIONS"]
+        if is_static:
             self.assertIsNone(ctypes.pythonapi)
         else:
             self.assertIsNotNone(ctypes.pythonapi)

From 2e0477b65d7aa4015921cc7139314f15e4657fec Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Tue, 11 Mar 2025 17:04:40 -0500
Subject: [PATCH 057/157] Update release artifacts for musl to include
 `+static` variant (#556)

Follows #541

Tested locally with `just release-dry-run` and the artifacts on the
latest commit to `main`. Then used for
https://github.com/astral-sh/python-build-standalone/releases/tag/20250311
---
 src/release.rs | 16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/src/release.rs b/src/release.rs
index b645d8d1..10e562ca 100644
--- a/src/release.rs
+++ b/src/release.rs
@@ -133,6 +133,14 @@ pub static RELEASE_TRIPLES: Lazy<BTreeMap<&'static str, TripleRelease>> = Lazy::
     // Linux.
     let linux_suffixes_pgo = vec!["debug", "pgo+lto"];
     let linux_suffixes_nopgo = vec!["debug", "lto", "noopt"];
+    let linux_suffixes_musl = vec![
+        "debug",
+        "lto",
+        "noopt",
+        "debug+static",
+        "lto+static",
+        "noopt+static",
+    ];
     let linux_suffixes_pgo_freethreaded = vec!["freethreaded+debug", "freethreaded+pgo+lto"];
     let linux_suffixes_nopgo_freethreaded = vec![
         "freethreaded+debug",
@@ -270,7 +278,7 @@ pub static RELEASE_TRIPLES: Lazy<BTreeMap<&'static str, TripleRelease>> = Lazy::
     h.insert(
         "x86_64-unknown-linux-musl",
         TripleRelease {
-            suffixes: linux_suffixes_nopgo.clone(),
+            suffixes: linux_suffixes_musl.clone(),
             install_only_suffix: "lto",
             python_version_requirement: Some(VersionSpecifier::from_str("<3.14").unwrap()),
             conditional_suffixes: vec![],
@@ -279,7 +287,7 @@ pub static RELEASE_TRIPLES: Lazy<BTreeMap<&'static str, TripleRelease>> = Lazy::
     h.insert(
         "x86_64_v2-unknown-linux-musl",
         TripleRelease {
-            suffixes: linux_suffixes_nopgo.clone(),
+            suffixes: linux_suffixes_musl.clone(),
             install_only_suffix: "lto",
             python_version_requirement: Some(VersionSpecifier::from_str("<3.14").unwrap()),
             conditional_suffixes: vec![],
@@ -288,7 +296,7 @@ pub static RELEASE_TRIPLES: Lazy<BTreeMap<&'static str, TripleRelease>> = Lazy::
     h.insert(
         "x86_64_v3-unknown-linux-musl",
         TripleRelease {
-            suffixes: linux_suffixes_nopgo.clone(),
+            suffixes: linux_suffixes_musl.clone(),
             install_only_suffix: "lto",
             python_version_requirement: Some(VersionSpecifier::from_str("<3.14").unwrap()),
             conditional_suffixes: vec![],
@@ -297,7 +305,7 @@ pub static RELEASE_TRIPLES: Lazy<BTreeMap<&'static str, TripleRelease>> = Lazy::
     h.insert(
         "x86_64_v4-unknown-linux-musl",
         TripleRelease {
-            suffixes: linux_suffixes_nopgo.clone(),
+            suffixes: linux_suffixes_musl.clone(),
             install_only_suffix: "lto",
             python_version_requirement: Some(VersionSpecifier::from_str("<3.14").unwrap()),
             conditional_suffixes: vec![],

From 60c9f8884228c90ad8742970ffb564e04aa19051 Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Sat, 15 Mar 2025 15:56:12 -0500
Subject: [PATCH 058/157] Remove `tj-actions/changed-files` (#559)

The compromised version never ran here, but we'll move off this.
---
 .github/workflows/linux.yml   | 19 ++++++++++++-------
 .github/workflows/macos.yml   | 18 +++++++++++-------
 .github/workflows/windows.yml | 20 +++++++++++++-------
 3 files changed, 36 insertions(+), 21 deletions(-)

diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml
index e7281574..1206c0c1 100644
--- a/.github/workflows/linux.yml
+++ b/.github/workflows/linux.yml
@@ -130,9 +130,11 @@ jobs:
       matrix-0: ${{ steps.set-matrix.outputs.matrix-0 }}
       matrix-1: ${{ steps.set-matrix.outputs.matrix-1 }}
       any_builds: ${{ steps.set-matrix.outputs.any_builds }}
-      pythonbuild_changed: ${{ steps.changed.outputs.pythonbuild_any_changed }}
+      pythonbuild_changed: ${{ steps.check-pythonbuild.outputs.changed }}
     steps:
       - uses: actions/checkout@v4
+        with:
+          fetch-depth: 0  # fetch history for subsequent `git diff`
 
       - name: Set up Python
         uses: astral-sh/setup-uv@v4
@@ -167,12 +169,15 @@ jobs:
             echo "any_builds=false" >> $GITHUB_OUTPUT
           fi
 
-      - uses: tj-actions/changed-files@v45
-        id: changed
-        with:
-          files_yaml: |
-            pythonbuild:
-              - "src/*.rs"
+      - name: Check if the `pythonbuild` crate changed
+        id: check-pythonbuild
+        run: |
+          if git diff --quiet ${{ github.event.pull_request.base.sha || 'origin/main' }}...HEAD -- ':src/*.rs'; then
+              echo "changed=false" >> "$GITHUB_OUTPUT"
+          else
+              echo "changed=true" >> "$GITHUB_OUTPUT"
+          fi
+          
 
   build-0:
     needs:
diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml
index 50345e0e..2b5841e7 100644
--- a/.github/workflows/macos.yml
+++ b/.github/workflows/macos.yml
@@ -48,9 +48,11 @@ jobs:
     outputs:
       matrix: ${{ steps.set-matrix.outputs.matrix }}
       any_builds: ${{ steps.set-matrix.outputs.any_builds }}
-      pythonbuild_changed: ${{ steps.changed.outputs.pythonbuild_any_changed }}
+      pythonbuild_changed: ${{ steps.check-pythonbuild.outputs.changed }}
     steps:
       - uses: actions/checkout@v4
+        with:
+          fetch-depth: 0  # fetch history for subsequent `git diff`
 
       - name: Set up Python
         uses: astral-sh/setup-uv@v4
@@ -77,12 +79,14 @@ jobs:
             echo "any_builds=false" >> $GITHUB_OUTPUT
           fi
 
-      - uses: tj-actions/changed-files@v45
-        id: changed
-        with:
-          files_yaml: |
-            pythonbuild:
-              - "src/*.rs"
+      - name: Check if the `pythonbuild` crate changed
+        id: check-pythonbuild
+        run: |
+          if git diff --quiet ${{ github.event.pull_request.base.sha || 'origin/main' }}...HEAD -- ':src/*.rs'; then
+              echo "changed=false" >> "$GITHUB_OUTPUT"
+          else
+              echo "changed=true" >> "$GITHUB_OUTPUT"
+          fi
   build:
     needs:
       - generate-matrix
diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml
index 6065b439..42764636 100644
--- a/.github/workflows/windows.yml
+++ b/.github/workflows/windows.yml
@@ -48,9 +48,11 @@ jobs:
     outputs:
       matrix: ${{ steps.set-matrix.outputs.matrix }}
       any_builds: ${{ steps.set-matrix.outputs.any_builds }}
-      pythonbuild_changed: ${{ steps.changed.outputs.pythonbuild_any_changed }}
+      pythonbuild_changed: ${{ steps.check-pythonbuild.outputs.changed }}
     steps:
       - uses: actions/checkout@v4
+        with:
+          fetch-depth: 0  # fetch history for subsequent `git diff`
 
       - name: Set up Python
         uses: astral-sh/setup-uv@v4
@@ -77,12 +79,16 @@ jobs:
             echo "any_builds=false" >> $GITHUB_OUTPUT
           fi
 
-      - uses: tj-actions/changed-files@v45
-        id: changed
-        with:
-          files_yaml: |
-            pythonbuild:
-              - "src/*.rs"
+
+      - name: Check if the `pythonbuild` crate changed
+        id: check-pythonbuild
+        shell: bash
+        run: |
+          if git diff --quiet ${{ github.event.pull_request.base.sha || 'origin/main' }}...HEAD -- ':src/*.rs'; then
+              echo "changed=false" >> "$GITHUB_OUTPUT"
+          else
+              echo "changed=true" >> "$GITHUB_OUTPUT"
+          fi
 
   build:
     needs:

From c02f7ef8aa6c0747b7310136439e03ae8ea738f3 Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Sat, 15 Mar 2025 20:18:30 -0500
Subject: [PATCH 059/157] Pin third-party GitHub Actions (#560)

We should probably switch to Renovate's pin support here, but this is an
easy first step.
---
 .github/workflows/linux.yml   | 4 ++--
 .github/workflows/release.yml | 2 +-
 .github/workflows/windows.yml | 2 +-
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml
index 1206c0c1..a64e8360 100644
--- a/.github/workflows/linux.yml
+++ b/.github/workflows/linux.yml
@@ -76,10 +76,10 @@ jobs:
           python-version: '3.11'
 
       - name: Set up Docker Buildx
-        uses: docker/setup-buildx-action@v3
+        uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3
 
       - name: Login to GitHub Container Registry
-        uses: docker/login-action@v3
+        uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3
         with:
           registry: ghcr.io
           username: ${{ github.actor }}
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 7993fe5c..ce803392 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -35,7 +35,7 @@ jobs:
         with:
           submodules: recursive
 
-      - uses: extractions/setup-just@v2
+      - uses: extractions/setup-just@dd310ad5a97d8e7b41793f8ef055398d51ad4de6 # v2
 
       # Perform a release in dry-run mode.
       - run: just release-dry-run ${{ secrets.GITHUB_TOKEN }} ${{ github.event.inputs.sha }} ${{ github.event.inputs.tag }}
diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml
index 42764636..11434bb2 100644
--- a/.github/workflows/windows.yml
+++ b/.github/workflows/windows.yml
@@ -109,7 +109,7 @@ jobs:
           fetch-depth: 0
 
       - name: Install Cygwin Environment
-        uses: cygwin/cygwin-install-action@49f298a7ebb00d4b3ddf58000c3e78eff5fbd6b9
+        uses: cygwin/cygwin-install-action@49f298a7ebb00d4b3ddf58000c3e78eff5fbd6b9 # v2
         with:
           packages: autoconf automake libtool
 

From 88952bed36a419aa2812ba127bb04e3862b5636c Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Sat, 15 Mar 2025 20:18:48 -0500
Subject: [PATCH 060/157] Increase the number of retries on download failure
 (#555)

The max retry time before was 16s, here it's bumped to 128s (not
counting the previous retry times).

The previous time seems a bit low given the total job runtime and flaked
in

-
https://github.com/astral-sh/python-build-standalone/actions/runs/13793651007/job/38580117193
---
 pythonbuild/utils.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/pythonbuild/utils.py b/pythonbuild/utils.py
index 1d1e8f50..ca15a616 100644
--- a/pythonbuild/utils.py
+++ b/pythonbuild/utils.py
@@ -287,7 +287,7 @@ def download_to_path(url: str, path: pathlib.Path, size: int, sha256: str):
         )
     )
 
-    for attempt in range(5):
+    for attempt in range(8):
         try:
             try:
                 with tmp.open("wb") as fh:

From 0c9c364332d09d219df85cf669862cf5ab27ec62 Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Mon, 17 Mar 2025 11:30:20 -0500
Subject: [PATCH 061/157] Fix missing `length` in `IntegrityError` (#564)

This error is being raised over in
https://github.com/astral-sh/python-build-standalone/pull/563 but
failing because the length is missing?
---
 pythonbuild/utils.py | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/pythonbuild/utils.py b/pythonbuild/utils.py
index ca15a616..14d9a474 100644
--- a/pythonbuild/utils.py
+++ b/pythonbuild/utils.py
@@ -247,7 +247,8 @@ def secure_download_stream(url, size, sha256):
     if length != size or digest != sha256:
         raise IntegrityError(
             "integrity mismatch on %s: wanted size=%d, sha256=%s; got size=%d, sha256=%s"
-            % (url, size, sha256, length, digest)
+            % (url, size, sha256, length, digest),
+            length=length,
         )
 
 

From 1e0a3961482403c34800f80914397e85f73bea78 Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Mon, 17 Mar 2025 11:47:20 -0500
Subject: [PATCH 062/157] Bump to CPython 3.14.0a6 (#561)

---
 cpython-unix/build-cpython.sh                 |   3 -
 ...atch-jit-tail-call-compat-314-129820.patch | 227 ------------------
 pythonbuild/downloads.py                      |   8 +-
 3 files changed, 4 insertions(+), 234 deletions(-)
 delete mode 100644 cpython-unix/patch-jit-tail-call-compat-314-129820.patch

diff --git a/cpython-unix/build-cpython.sh b/cpython-unix/build-cpython.sh
index 350be3cf..5e66f053 100755
--- a/cpython-unix/build-cpython.sh
+++ b/cpython-unix/build-cpython.sh
@@ -448,9 +448,6 @@ if [ -n "${CPYTHON_OPTIMIZED}" ]; then
 
          if [[ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_14}" ]]; then
             patch -p1 -i "${ROOT}/patch-jit-llvm-version-3.14.patch"
-            # On 3.14, we also use the tail calling interpreter which was incompatible with the JIT
-            # until https://github.com/python/cpython/pull/129820 — backport that
-            patch -p1 -i "${ROOT}/patch-jit-tail-call-compat-314-129820.patch"
         fi
     fi
 fi
diff --git a/cpython-unix/patch-jit-tail-call-compat-314-129820.patch b/cpython-unix/patch-jit-tail-call-compat-314-129820.patch
deleted file mode 100644
index c612c5bc..00000000
--- a/cpython-unix/patch-jit-tail-call-compat-314-129820.patch
+++ /dev/null
@@ -1,227 +0,0 @@
-diff --git a/configure b/configure
-index 65b8e711cdccae..ee47feafc73fc1 100755
---- a/configure
-+++ b/configure
-@@ -29281,18 +29281,6 @@ esac
- fi
- 
- 
--# Do not enable tail-calling interpreter if tier 2 is enabled.
--if ${tier2_flags:+false} :
--then :
--
--    case "$ac_cv_tail_call" in yes*)
--
--printf "%s\n" "#define Py_TAIL_CALL_INTERP 1" >>confdefs.h
--
--    esac
--
--fi
--
- 
- case $ac_sys_system in
- AIX*)
-diff --git a/configure.ac b/configure.ac
-index 0c6063d87d654a..c68938ba9e168d 100644
---- a/configure.ac
-+++ b/configure.ac
-@@ -7041,19 +7041,6 @@ fi
- ],
- [AC_MSG_RESULT([no value specified])])
- 
--# Do not enable tail-calling interpreter if tier 2 is enabled.
--AS_VAR_IF(
--  [tier2_flags],
--  [],
--  [
--    case "$ac_cv_tail_call" in yes*)
--      AC_DEFINE([Py_TAIL_CALL_INTERP], [1],
--      [Define if the C compiler supports efficient proper tail calls.])
--    esac
--  ],
--  []
--)
--
- 
- case $ac_sys_system in
- AIX*)
-diff --git a/pyconfig.h.in b/pyconfig.h.in
-index 9ea01ad3fc0a31..4295b4f5ea5fbd 100644
---- a/pyconfig.h.in
-+++ b/pyconfig.h.in
-@@ -1718,7 +1718,7 @@
- /* The version of SunOS/Solaris as reported by `uname -r' without the dot. */
- #undef Py_SUNOS_VERSION
- 
--/* Define if the C compiler supports efficient proper tail calls. */
-+/* Define if you want to use tail-calling interpreters in CPython. */
- #undef Py_TAIL_CALL_INTERP
- 
- /* Define if you want to enable tracing references for debugging purpose */
-
-From dae88e3ca730576256a0b8d2bc9e78b8cacab645 Mon Sep 17 00:00:00 2001
-From: Ken Jin <28750310+Fidget-Spinner@users.noreply.github.com>
-Date: Sat, 8 Feb 2025 01:32:05 +0800
-Subject: [PATCH 2/6] Get JIT working minimally with tailcalling interpreter
-
----
- Python/ceval_macros.h | 19 +++++++++++++++++++
- 1 file changed, 19 insertions(+)
-
-diff --git a/Python/ceval_macros.h b/Python/ceval_macros.h
-index 44bb52a09aab5f..2c7729743b1705 100644
---- a/Python/ceval_macros.h
-+++ b/Python/ceval_macros.h
-@@ -384,6 +384,24 @@ _PyFrame_SetStackPointer(frame, stack_pointer)
- /* Tier-switching macros. */
- 
- #ifdef _Py_JIT
-+#ifdef Py_TAIL_CALL_INTERP
-+#define GOTO_TIER_TWO(EXECUTOR)                        \
-+do {                                                   \
-+    OPT_STAT_INC(traces_executed);                     \
-+    jit_func jitted = (EXECUTOR)->jit_code;            \
-+    next_instr = jitted(frame, stack_pointer, tstate); \
-+    Py_DECREF(tstate->previous_executor);              \
-+    tstate->previous_executor = NULL;                  \
-+    frame = tstate->current_frame;                     \
-+    if (next_instr == NULL) {                          \
-+        next_instr = frame->instr_ptr;                 \
-+        stack_pointer = _PyFrame_GetStackPointer(frame); \
-+        return _TAIL_CALL_error(TAIL_CALL_ARGS);       \
-+    }                                                  \
-+    stack_pointer = _PyFrame_GetStackPointer(frame);   \
-+    DISPATCH();                                        \
-+} while (0)
-+#else
- #define GOTO_TIER_TWO(EXECUTOR)                        \
- do {                                                   \
-     OPT_STAT_INC(traces_executed);                     \
-@@ -400,6 +418,7 @@ do {                                                   \
-     stack_pointer = _PyFrame_GetStackPointer(frame);   \
-     DISPATCH();                                        \
- } while (0)
-+#endif
- #else
- #define GOTO_TIER_TWO(EXECUTOR) \
- do { \
-
-From 230d497620d73e17a099326f7e54078e91254e5a Mon Sep 17 00:00:00 2001
-From: Ken Jin <28750310+Fidget-Spinner@users.noreply.github.com>
-Date: Tue, 11 Feb 2025 16:05:57 +0800
-Subject: [PATCH 3/6] Update ceval_macros.h
-
----
- Python/ceval_macros.h | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/Python/ceval_macros.h b/Python/ceval_macros.h
-index 2c7729743b1705..0f4dd61f367dbb 100644
---- a/Python/ceval_macros.h
-+++ b/Python/ceval_macros.h
-@@ -384,7 +384,7 @@ _PyFrame_SetStackPointer(frame, stack_pointer)
- /* Tier-switching macros. */
- 
- #ifdef _Py_JIT
--#ifdef Py_TAIL_CALL_INTERP
-+#if Py_TAIL_CALL_INTERP
- #define GOTO_TIER_TWO(EXECUTOR)                        \
- do {                                                   \
-     OPT_STAT_INC(traces_executed);                     \
-
-From c46391470ca8b4d6a4b9c0d9f75c7fcce6ac303a Mon Sep 17 00:00:00 2001
-From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com>
-Date: Tue, 11 Feb 2025 08:06:47 +0000
-Subject: [PATCH 4/6] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20blu?=
- =?UTF-8?q?rb=5Fit.?=
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
----
- .../next/Build/2025-02-11-08-06-44.gh-issue-129819.7rn4dY.rst    | 1 +
- 1 file changed, 1 insertion(+)
- create mode 100644 Misc/NEWS.d/next/Build/2025-02-11-08-06-44.gh-issue-129819.7rn4dY.rst
-
-diff --git a/Misc/NEWS.d/next/Build/2025-02-11-08-06-44.gh-issue-129819.7rn4dY.rst b/Misc/NEWS.d/next/Build/2025-02-11-08-06-44.gh-issue-129819.7rn4dY.rst
-new file mode 100644
-index 00000000000000..2463e4dba24ae9
---- /dev/null
-+++ b/Misc/NEWS.d/next/Build/2025-02-11-08-06-44.gh-issue-129819.7rn4dY.rst
-@@ -0,0 +1 @@
-+Allow building the JIT with the tailcall interpreter.
-
-From 105ab11ce4fcc3d659ccaf36197ea281b853e23a Mon Sep 17 00:00:00 2001
-From: Ken Jin <28750310+Fidget-Spinner@users.noreply.github.com>
-Date: Wed, 12 Feb 2025 16:14:23 +0800
-Subject: [PATCH 5/6] Address review
-
----
- Python/ceval_macros.h | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/Python/ceval_macros.h b/Python/ceval_macros.h
-index 0f4dd61f367dbb..9562ad9d349a11 100644
---- a/Python/ceval_macros.h
-+++ b/Python/ceval_macros.h
-@@ -396,7 +396,7 @@ do {                                                   \
-     if (next_instr == NULL) {                          \
-         next_instr = frame->instr_ptr;                 \
-         stack_pointer = _PyFrame_GetStackPointer(frame); \
--        return _TAIL_CALL_error(TAIL_CALL_ARGS);       \
-+        return JUMP_TO_LABEL(error);                   \
-     }                                                  \
-     stack_pointer = _PyFrame_GetStackPointer(frame);   \
-     DISPATCH();                                        \
-
-From 76c2c96fed4abc68e8879f3d65755d5cba8a4b16 Mon Sep 17 00:00:00 2001
-From: Ken Jin <28750310+Fidget-Spinner@users.noreply.github.com>
-Date: Thu, 13 Feb 2025 01:06:07 +0800
-Subject: [PATCH 6/6] one-liner
-
----
- Python/ceval_macros.h | 21 +--------------------
- 1 file changed, 1 insertion(+), 20 deletions(-)
-
-diff --git a/Python/ceval_macros.h b/Python/ceval_macros.h
-index 2422bf3bcf38f1..4f0071d5e1a09f 100644
---- a/Python/ceval_macros.h
-+++ b/Python/ceval_macros.h
-@@ -381,24 +381,6 @@ _PyFrame_SetStackPointer(frame, stack_pointer)
- /* Tier-switching macros. */
- 
- #ifdef _Py_JIT
--#if Py_TAIL_CALL_INTERP
--#define GOTO_TIER_TWO(EXECUTOR)                        \
--do {                                                   \
--    OPT_STAT_INC(traces_executed);                     \
--    jit_func jitted = (EXECUTOR)->jit_code;            \
--    next_instr = jitted(frame, stack_pointer, tstate); \
--    Py_DECREF(tstate->previous_executor);              \
--    tstate->previous_executor = NULL;                  \
--    frame = tstate->current_frame;                     \
--    if (next_instr == NULL) {                          \
--        next_instr = frame->instr_ptr;                 \
--        stack_pointer = _PyFrame_GetStackPointer(frame); \
--        return JUMP_TO_LABEL(error);                   \
--    }                                                  \
--    stack_pointer = _PyFrame_GetStackPointer(frame);   \
--    DISPATCH();                                        \
--} while (0)
--#else
- #define GOTO_TIER_TWO(EXECUTOR)                        \
- do {                                                   \
-     OPT_STAT_INC(traces_executed);                     \
-@@ -413,11 +395,10 @@ do {                                                   \
-     stack_pointer = _PyFrame_GetStackPointer(frame);   \
-     if (next_instr == NULL) {                          \
-         next_instr = frame->instr_ptr;                 \
--        goto error;                                    \
-+        JUMP_TO_LABEL(error);                          \
-     }                                                  \
-     DISPATCH();                                        \
- } while (0)
--#endif
- #else
- #define GOTO_TIER_TWO(EXECUTOR) \
- do { \
diff --git a/pythonbuild/downloads.py b/pythonbuild/downloads.py
index 0340a68a..158171ab 100644
--- a/pythonbuild/downloads.py
+++ b/pythonbuild/downloads.py
@@ -80,10 +80,10 @@
         "python_tag": "cp313",
     },
     "cpython-3.14": {
-        "url": "https://www.python.org/ftp/python/3.14.0/Python-3.14.0a5.tar.xz",
-        "size": 22859900,
-        "sha256": "74e83f26de1e4fb9eef1b56492cff92508834bb71ac13f5c580438ce9f093682",
-        "version": "3.14.0a5",
+        "url": "https://www.python.org/ftp/python/3.14.0/Python-3.14.0a6.tar.xz",
+        "size": 22956068,
+        "sha256": "8d6181e5331d9a2cd6ca405ae1230e88589a043f4768ebb443d3889d45c1c35c",
+        "version": "3.14.0a6",
         "licenses": ["Python-2.0", "CNRI-Python"],
         "license_file": "LICENSE.cpython.txt",
         "python_tag": "cp314",

From 19bdff5dc02b8c76af7c55072d156a58bef02d5f Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Mon, 17 Mar 2025 13:24:48 -0500
Subject: [PATCH 063/157] Use a mirror for bzip2 (#567)

A more targeted solution to

- #566
- #565
---
 pythonbuild/downloads.py | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/pythonbuild/downloads.py b/pythonbuild/downloads.py
index 158171ab..40b11a13 100644
--- a/pythonbuild/downloads.py
+++ b/pythonbuild/downloads.py
@@ -26,7 +26,9 @@
         "version": "2.43",
     },
     "bzip2": {
-        "url": "https://sourceware.org/pub/bzip2/bzip2-1.0.8.tar.gz",
+        # Mirror of `https://sourceware.org/pub/bzip2/bzip2-1.0.8.tar.gz` due to
+        # rate limiting
+        "url": "https://astral-sh.github.io/mirror/files/bzip2-1.0.8.tar.gz",
         "size": 810029,
         "sha256": "ab5a03176ee106d3f0fa90e381da478ddae405918153cca248e682cd0c4a2269",
         "version": "1.0.8",

From bdb07227039982bd6fbae6a2906766eb086069d7 Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Mon, 17 Mar 2025 13:25:07 -0500
Subject: [PATCH 064/157] Cache dependency downloads on Linux (#566)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

In https://github.com/astral-sh/python-build-standalone/pull/565 we note
we're seeing rate-limiting on downloads of bzip2 — which is blocking
development here. There, we increase the exponential backoff but we need
to reduce the number of downloads to address the root cause of the
issue. @geofft suggested caching these downloads, which makes a lot of
sense for us — there's already logic to validate the file if it exists
on disk.

I'm just starting with Linux.
---
 .github/workflows/linux.yml | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml
index a64e8360..8222d77d 100644
--- a/.github/workflows/linux.yml
+++ b/.github/workflows/linux.yml
@@ -216,6 +216,15 @@ jobs:
           path: build
           merge-multiple: true
 
+      - name: Cache downloads
+        uses: actions/cache@v4
+        with:
+          path: build/downloads
+          key: ${{ matrix.target_triple }}-${{ hashFiles('pythonbuild/downloads.py')}}
+          restore-keys: |
+            ${{ matrix.target_triple }}-${{ hashFiles('pythonbuild/downloads.py')}}
+            ${{ matrix.target_triple }}-
+
       - name: Load Docker Images
         run: |
           for f in build/image-*.tar.zst; do
@@ -307,6 +316,15 @@ jobs:
           path: build
           merge-multiple: true
 
+      - name: Cache downloads
+        uses: actions/cache@v4
+        with:
+          path: build/downloads
+          key: ${{ matrix.target_triple }}-${{ hashFiles('pythonbuild/downloads.py')}}
+          restore-keys: |
+            ${{ matrix.target_triple }}-${{ hashFiles('pythonbuild/downloads.py')}}
+            ${{ matrix.target_triple }}-
+
       - name: Load Docker Images
         run: |
           for f in build/image-*.tar.zst; do

From 4ef6f72f57069c2ca28d897afdd53a5b1b3f0f98 Mon Sep 17 00:00:00 2001
From: Quentin Gliech <quenting@element.io>
Date: Mon, 17 Mar 2025 19:27:59 +0100
Subject: [PATCH 065/157] Compile sqlite with FTS3 enhanced query syntax
 enabled (#562)

Fixes #550

This adds three compilation flags to the embedded sqlite module:

- `-DSQLITE_ENABLE_FTS3` to explicitly enable FTS3 support (which AFAIK
is already enabled by default)
- `-DSQLITE_ENABLE_FTS3_PARENTHESIS` to enable the enhanced FTS3 query
syntax (which isn't enabled by default)
- `-DSQLITE_ENABLE_FTS3_TOKENIZER` to enable the two-argument version of
the `fts3_tokenizer()` interface. It still has to be enabled on the
connection-level using `Connection.setconfig`

All those flags are enabled by default in the Debian build of SQLite,
and probably in other distributions as well.
---
 cpython-unix/build-sqlite.sh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/cpython-unix/build-sqlite.sh b/cpython-unix/build-sqlite.sh
index 2d44dc83..b045bb88 100755
--- a/cpython-unix/build-sqlite.sh
+++ b/cpython-unix/build-sqlite.sh
@@ -22,7 +22,7 @@ elif [ "${TARGET_TRIPLE}" = "x86_64-apple-ios" ]; then
     CONFIGURE_FLAGS="${CONFIGURE_FLAGS} ac_cv_search_system=no"
 fi
 
-CFLAGS="${EXTRA_TARGET_CFLAGS} -DSQLITE_ENABLE_DBSTAT_VTAB -fPIC" CPPFLAGS="${EXTRA_TARGET_CFLAGS} -fPIC" LDFLAGS="${EXTRA_TARGET_LDFLAGS}" ./configure ${CONFIGURE_FLAGS}
+CFLAGS="${EXTRA_TARGET_CFLAGS} -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_FTS3_PARENTHESIS -DSQLITE_ENABLE_FTS3_TOKENIZER -fPIC" CPPFLAGS="${EXTRA_TARGET_CFLAGS} -fPIC" LDFLAGS="${EXTRA_TARGET_LDFLAGS}" ./configure ${CONFIGURE_FLAGS}
 
 make -j ${NUM_CPUS}
 make -j ${NUM_CPUS} install DESTDIR=${ROOT}/out

From 7d8bb5e8cf054d88cbf505645257a25b8f46b286 Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Mon, 17 Mar 2025 15:36:19 -0500
Subject: [PATCH 066/157] Declare the `target_cxx` value for all targets (#563)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This value can leak into user builds through sysconfig so it is not
appropriate to use the `host_cxx`. See
https://github.com/astral-sh/uv/issues/12207

There's not a `musl-clang++` equivalent — so we skip this for those
targets.
---
 cpython-unix/build.py    |  2 +-
 cpython-unix/targets.yml | 29 +++++++++++++++++++++++++++++
 2 files changed, 30 insertions(+), 1 deletion(-)

diff --git a/cpython-unix/build.py b/cpython-unix/build.py
index b34a1efe..c90f7deb 100755
--- a/cpython-unix/build.py
+++ b/cpython-unix/build.py
@@ -103,7 +103,7 @@ def add_target_env(env, build_platform, target_triple, build_env):
     env["CC"] = settings["target_cc"]
     # We always set CXX, otherwise a build could bypass our toolchain
     # accidentally, e.g., on macOS where `g++` links to the system clang.
-    env["CXX"] = settings.get("target_cxx", settings.get("host_cxx"))
+    env["CXX"] = settings["target_cxx"]
 
     if settings.get("bolt_capable"):
         env["BOLT_CAPABLE"] = "1"
diff --git a/cpython-unix/targets.yml b/cpython-unix/targets.yml
index d3285891..1b179768 100644
--- a/cpython-unix/targets.yml
+++ b/cpython-unix/targets.yml
@@ -25,6 +25,10 @@
 # target_cc
 #    Path to C compiler to use for building binaries targeting the
 #    target architecture.
+
+# target_cxx
+#    Path to C++ compiler to use for building binaries targeting the
+#    target architecture.
 #
 # target_cflags
 #    List of extra compiler flags to use when building for the target.
@@ -69,6 +73,7 @@ aarch64-apple-darwin:
   host_cc: clang
   host_cxx: clang++
   target_cc: clang
+  target_cxx: clang++
   apple_sdk_platform: macosx
   target_cflags:
     - '-arch'
@@ -114,6 +119,7 @@ aarch64-apple-ios:
   host_cc: clang
   host_cxx: clang++
   target_cc: clang
+  target_cxx: clang++
   target_cflags:
     - '-arch'
     - 'arm64'
@@ -159,6 +165,7 @@ aarch64-unknown-linux-gnu:
   host_cc: /usr/bin/x86_64-linux-gnu-gcc
   host_cxx: /usr/bin/x86_64-linux-gnu-g++
   target_cc: /usr/bin/aarch64-linux-gnu-gcc
+  target_cxx: /usr/bin/aarch64-linux-gnu-g++
   needs:
     - autoconf
     - bdb
@@ -195,6 +202,7 @@ arm64-apple-tvos:
   host_cc: clang
   host_cxx: clang++
   target_cc: clang
+  target_cxx: clang++
   target_cflags:
     - '-arch'
     - 'arm64'
@@ -239,6 +247,7 @@ armv7-unknown-linux-gnueabi:
   host_cc: /usr/bin/x86_64-linux-gnu-gcc
   host_cxx: /usr/bin/x86_64-linux-gnu-g++
   target_cc: /usr/bin/arm-linux-gnueabi-gcc
+  target_cxx: /usr/bin/arm-linux-gnueabi-g++
   needs:
     - autoconf
     - bdb
@@ -279,6 +288,7 @@ armv7-unknown-linux-gnueabihf:
   host_cc: /usr/bin/x86_64-linux-gnu-gcc
   host_cxx: /usr/bin/x86_64-linux-gnu-g++
   target_cc: /usr/bin/arm-linux-gnueabihf-gcc
+  target_cxx: /usr/bin/arm-linux-gnueabihf-g++
   needs:
     - autoconf
     - bdb
@@ -319,6 +329,7 @@ i686-unknown-linux-gnu:
   host_cc: clang
   host_cxx: clang++
   target_cc: clang
+  target_cxx: clang++
   target_cflags:
     - '-m32'
     - '-fvisibility=hidden'
@@ -364,6 +375,7 @@ mips-unknown-linux-gnu:
   host_cc: /usr/bin/x86_64-linux-gnu-gcc
   host_cxx: /usr/bin/x86_64-linux-gnu-g++
   target_cc: /usr/bin/mips-linux-gnu-gcc
+  target_cxx: /usr/bin/mips-linux-gnu-g++
   needs:
     - autoconf
     - bdb
@@ -404,6 +416,7 @@ mipsel-unknown-linux-gnu:
   host_cc: /usr/bin/x86_64-linux-gnu-gcc
   host_cxx: /usr/bin/x86_64-linux-gnu-g++
   target_cc: /usr/bin/mipsel-linux-gnu-gcc
+  target_cxx: /usr/bin/mipsel-linux-gnu-g++
   needs:
     - autoconf
     - bdb
@@ -444,6 +457,7 @@ ppc64le-unknown-linux-gnu:
   host_cc: /usr/bin/x86_64-linux-gnu-gcc
   host_cxx: /usr/bin/x86_64-linux-gnu-g++
   target_cc: /usr/bin/powerpc64le-linux-gnu-gcc
+  target_cxx: /usr/bin/powerpc64le-linux-gnu-g++
   needs:
     - autoconf
     - bdb
@@ -484,6 +498,7 @@ riscv64-unknown-linux-gnu:
   host_cc: /usr/bin/x86_64-linux-gnu-gcc
   host_cxx: /usr/bin/x86_64-linux-gnu-g++
   target_cc: /usr/bin/riscv64-linux-gnu-gcc
+  target_cxx: /usr/bin/riscv64-linux-gnu-g++
   needs:
     - autoconf
     - bdb
@@ -524,6 +539,7 @@ s390x-unknown-linux-gnu:
   host_cc: /usr/bin/x86_64-linux-gnu-gcc
   host_cxx: /usr/bin/x86_64-linux-gnu-g++
   target_cc: /usr/bin/s390x-linux-gnu-gcc
+  target_cxx: /usr/bin/s390x-linux-gnu-g++
   needs:
     - autoconf
     - bdb
@@ -560,6 +576,7 @@ thumb7k-apple-watchos:
   host_cc: clang
   host_cxx: clang++
   target_cc: clang
+  target_cxx: clang++
   target_cflags:
     - '-arch'
     - 'armv7k'
@@ -609,6 +626,7 @@ x86_64-apple-darwin:
   host_cc: clang
   host_cxx: clang++
   target_cc: clang
+  target_cxx: clang++
   target_cflags:
     - '-arch'
     - 'x86_64'
@@ -653,6 +671,7 @@ x86_64-apple-ios:
   host_cc: clang
   host_cxx: clang++
   target_cc: clang
+  target_cxx: clang++
   target_cflags:
     - '-arch'
     - 'x86_64'
@@ -694,6 +713,7 @@ x86_64-apple-tvos:
   host_cc: clang
   host_cxx: clang++
   target_cc: clang
+  target_cxx: clang++
   target_cflags:
     - '-arch'
     - 'x86_64'
@@ -734,6 +754,7 @@ x86_64-apple-watchos:
   host_cc: clang
   host_cxx: clang++
   target_cc: clang
+  target_cxx: clang++
   target_cflags:
     - '-arch'
     - 'x86_64'
@@ -778,6 +799,7 @@ x86_64-unknown-linux-gnu:
   host_cc: clang
   host_cxx: clang++
   target_cc: clang
+  target_cxx: clang++
   target_cflags:
     - '-fvisibility=hidden'
     # Needed to prevent BOLT from crashing.
@@ -823,6 +845,7 @@ x86_64_v2-unknown-linux-gnu:
   host_cc: clang
   host_cxx: clang++
   target_cc: clang
+  target_cxx: clang++
   target_cflags:
     - '-march=x86-64-v2'
     - '-fvisibility=hidden'
@@ -869,6 +892,7 @@ x86_64_v3-unknown-linux-gnu:
   host_cc: clang
   host_cxx: clang++
   target_cc: clang
+  target_cxx: clang++
   target_cflags:
     - '-march=x86-64-v3'
     - '-fvisibility=hidden'
@@ -915,6 +939,7 @@ x86_64_v4-unknown-linux-gnu:
   host_cc: clang
   host_cxx: clang++
   target_cc: clang
+  target_cxx: clang++
   target_cflags:
     - '-march=x86-64-v4'
     - '-fvisibility=hidden'
@@ -961,6 +986,7 @@ x86_64-unknown-linux-musl:
   host_cc: clang
   host_cxx: clang++
   target_cc: musl-clang
+  target_cxx: clang++  # TODO: Explore a musl-clang++ shim?
   target_cflags:
     - '-fvisibility=hidden'
   needs:
@@ -1004,6 +1030,7 @@ x86_64_v2-unknown-linux-musl:
   host_cc: clang
   host_cxx: clang++
   target_cc: musl-clang
+  target_cxx: clang++  # TODO: Explore a musl-clang++ shim?
   target_cflags:
     - '-march=x86-64-v2'
     - '-fvisibility=hidden'
@@ -1048,6 +1075,7 @@ x86_64_v3-unknown-linux-musl:
   host_cc: clang
   host_cxx: clang++
   target_cc: musl-clang
+  target_cxx: clang++  # TODO: Explore a musl-clang++ shim?
   target_cflags:
     - '-march=x86-64-v3'
     - '-fvisibility=hidden'
@@ -1092,6 +1120,7 @@ x86_64_v4-unknown-linux-musl:
   host_cc: clang
   host_cxx: clang++
   target_cc: musl-clang
+  target_cxx: clang++  # TODO: Explore a musl-clang++ shim?
   target_cflags:
     - '-march=x86-64-v4'
     - '-fvisibility=hidden'

From 7311355eb8701b6573f1f71cae5960cfcfeae273 Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Thu, 20 Mar 2025 10:38:55 -0500
Subject: [PATCH 067/157] Fix merge-base calculation for change determination
 (#573)

See https://github.com/astral-sh/ruff/pull/16857
---
 .github/workflows/linux.yml   | 6 ++++--
 .github/workflows/macos.yml   | 6 +++++-
 .github/workflows/windows.yml | 7 ++++---
 3 files changed, 13 insertions(+), 6 deletions(-)

diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml
index 8222d77d..c0c21bd0 100644
--- a/.github/workflows/linux.yml
+++ b/.github/workflows/linux.yml
@@ -171,13 +171,15 @@ jobs:
 
       - name: Check if the `pythonbuild` crate changed
         id: check-pythonbuild
+        env:
+          BASE_REF: ${{ github.event.pull_request.base.ref || 'main' }}
         run: |
-          if git diff --quiet ${{ github.event.pull_request.base.sha || 'origin/main' }}...HEAD -- ':src/*.rs'; then
+          merge_base=$(git merge-base HEAD "origin/${BASE_REF}")
+          if git diff --quiet "${merge_base}...HEAD" -- ':src/*.rs'; then
               echo "changed=false" >> "$GITHUB_OUTPUT"
           else
               echo "changed=true" >> "$GITHUB_OUTPUT"
           fi
-          
 
   build-0:
     needs:
diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml
index 2b5841e7..af9a80f0 100644
--- a/.github/workflows/macos.yml
+++ b/.github/workflows/macos.yml
@@ -81,12 +81,16 @@ jobs:
 
       - name: Check if the `pythonbuild` crate changed
         id: check-pythonbuild
+        env:
+          BASE_REF: ${{ github.event.pull_request.base.ref || 'main' }}
         run: |
-          if git diff --quiet ${{ github.event.pull_request.base.sha || 'origin/main' }}...HEAD -- ':src/*.rs'; then
+          merge_base=$(git merge-base HEAD "origin/${BASE_REF}")
+          if git diff --quiet "${merge_base}...HEAD" -- ':src/*.rs'; then
               echo "changed=false" >> "$GITHUB_OUTPUT"
           else
               echo "changed=true" >> "$GITHUB_OUTPUT"
           fi
+
   build:
     needs:
       - generate-matrix
diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml
index 11434bb2..a7535c68 100644
--- a/.github/workflows/windows.yml
+++ b/.github/workflows/windows.yml
@@ -79,12 +79,13 @@ jobs:
             echo "any_builds=false" >> $GITHUB_OUTPUT
           fi
 
-
       - name: Check if the `pythonbuild` crate changed
         id: check-pythonbuild
-        shell: bash
+        env:
+          BASE_REF: ${{ github.event.pull_request.base.ref || 'main' }}
         run: |
-          if git diff --quiet ${{ github.event.pull_request.base.sha || 'origin/main' }}...HEAD -- ':src/*.rs'; then
+          merge_base=$(git merge-base HEAD "origin/${BASE_REF}")
+          if git diff --quiet "${merge_base}...HEAD" -- ':src/*.rs'; then
               echo "changed=false" >> "$GITHUB_OUTPUT"
           else
               echo "changed=true" >> "$GITHUB_OUTPUT"

From a870b62b591611acd2e75801d4363ab797806b1e Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Thu, 20 Mar 2025 17:09:21 -0500
Subject: [PATCH 068/157] Add support for Python 3.14 on musl (#568)

Closes #558
Follow-up to #443
---
 ci-targets.yaml               | 32 ++++++++++++++++++++++++++++++++
 cpython-unix/build-cpython.sh |  6 +++---
 2 files changed, 35 insertions(+), 3 deletions(-)

diff --git a/ci-targets.yaml b/ci-targets.yaml
index cd892ac9..b1f53aa8 100644
--- a/ci-targets.yaml
+++ b/ci-targets.yaml
@@ -256,6 +256,7 @@ linux:
       - "3.11"
       - "3.12"
       - "3.13"
+      - "3.14"
     build_options:
       - debug+static
       - noopt+static
@@ -263,6 +264,13 @@ linux:
       - debug
       - noopt
       - lto
+    # freethreaded builds require mimalloc which is not available on musl yet
+    # build_options_conditional:
+    #   - options:
+    #       - freethreaded+debug
+    #       - freethreaded+noopt
+    #       - freethreaded+lto
+    #     minimum-python-version: "3.13"
     run: true
 
   x86_64_v2-unknown-linux-musl:
@@ -275,6 +283,7 @@ linux:
       - "3.11"
       - "3.12"
       - "3.13"
+      - "3.14"
     build_options:
       - debug+static
       - noopt+static
@@ -282,6 +291,13 @@ linux:
       - debug
       - noopt
       - lto
+    # freethreaded builds require mimalloc which is not available on musl yet
+    # build_options_conditional:
+    #   - options:
+    #       - freethreaded+debug
+    #       - freethreaded+noopt
+    #       - freethreaded+lto
+    #     minimum-python-version: "3.13"
     run: true
 
   x86_64_v3-unknown-linux-musl:
@@ -294,6 +310,7 @@ linux:
       - "3.11"
       - "3.12"
       - "3.13"
+      - "3.14"
     build_options:
       - debug+static
       - noopt+static
@@ -301,6 +318,13 @@ linux:
       - debug
       - noopt
       - lto
+    # freethreaded builds require mimalloc which is not available on musl yet
+    # build_options_conditional:
+    #   - options:
+    #       - freethreaded+debug
+    #       - freethreaded+noopt
+    #       - freethreaded+lto
+    #     minimum-python-version: "3.13"
     run: true
 
   x86_64_v4-unknown-linux-musl:
@@ -313,6 +337,7 @@ linux:
       - "3.11"
       - "3.12"
       - "3.13"
+      - "3.14"
     build_options:
       - debug+static
       - noopt+static
@@ -320,6 +345,13 @@ linux:
       - debug
       - noopt
       - lto
+    # freethreaded builds require mimalloc which is not available on musl yet
+    # build_options_conditional:
+    #   - options:
+    #       - freethreaded+debug
+    #       - freethreaded+noopt
+    #       - freethreaded+lto
+    #     minimum-python-version: "3.13"
     run: true
 
 windows:
diff --git a/cpython-unix/build-cpython.sh b/cpython-unix/build-cpython.sh
index 5e66f053..bd045e91 100755
--- a/cpython-unix/build-cpython.sh
+++ b/cpython-unix/build-cpython.sh
@@ -391,7 +391,7 @@ if [ "${CC}" = "musl-clang" ]; then
     # provided by musl. These are part of the include files that are part of clang.
     # But musl-clang eliminates them from the default include path. So copy them into
     # place.
-    for h in /tools/${TOOLCHAIN}/lib/clang/*/include/*intrin.h /tools/${TOOLCHAIN}/lib/clang/*/include/{__wmmintrin_aes.h,__wmmintrin_pclmul.h,mm_malloc.h}; do
+    for h in /tools/${TOOLCHAIN}/lib/clang/*/include/*intrin.h /tools/${TOOLCHAIN}/lib/clang/*/include/{__wmmintrin_aes.h,__wmmintrin_pclmul.h,mm_malloc.h,cpuid.h}; do
         filename=$(basename "$h")
         if [ -e "/tools/host/include/${filename}" ]; then
             echo "${filename} already exists; don't need to copy!"
@@ -416,7 +416,7 @@ if [ -n "${CPYTHON_DEBUG}" ]; then
 fi
 
 # Explicitly enable mimalloc on 3.13+, it's already included by default but with this it'll fail
-# if it's missing from the system. The MUSL builds do not supprt mimalloc yet.
+# if it's missing from the system. The musl builds do not supprt mimalloc yet.
 if [[ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_13}" && "${CC}" != "musl-clang" ]]; then
     CONFIGURE_FLAGS="${CONFIGURE_FLAGS} --with-mimalloc"
 fi
@@ -974,7 +974,7 @@ s390x-unknown-linux-gnu)
 x86_64-unknown-linux-*)
     # In Python 3.13+, the musl target is identified in cross compiles and the output directory
     # is named accordingly.
-    if [ "${CC}" = "musl-clang" ] && [ "${PYTHON_MAJMIN_VERSION}" = "3.13" ]; then
+    if [[ "${CC}" = "musl-clang" && -n "${PYTHON_MEETS_MINIMUM_VERSION_3_13}" ]]; then
         PYTHON_ARCH="x86_64-linux-musl"
     else
         PYTHON_ARCH="x86_64-linux-gnu"

From f0abfc9cb1f6a985fc5561cf5435f7f6e8a64e5b Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Thu, 20 Mar 2025 17:27:55 -0500
Subject: [PATCH 069/157] Enable free-threaded builds of Python 3.14 on musl
 (#571)

Extends #568

---------

Co-authored-by: Aria Desires <aria.desires@gmail.com>
---
 ci-targets.yaml               | 52 ++++++++++++++++-------------------
 cpython-unix/build-cpython.sh | 20 ++++++++++++--
 2 files changed, 42 insertions(+), 30 deletions(-)

diff --git a/ci-targets.yaml b/ci-targets.yaml
index b1f53aa8..70078e87 100644
--- a/ci-targets.yaml
+++ b/ci-targets.yaml
@@ -264,13 +264,12 @@ linux:
       - debug
       - noopt
       - lto
-    # freethreaded builds require mimalloc which is not available on musl yet
-    # build_options_conditional:
-    #   - options:
-    #       - freethreaded+debug
-    #       - freethreaded+noopt
-    #       - freethreaded+lto
-    #     minimum-python-version: "3.13"
+    build_options_conditional:
+      - options:
+          - freethreaded+debug
+          - freethreaded+noopt
+          - freethreaded+lto
+        minimum-python-version: "3.13"
     run: true
 
   x86_64_v2-unknown-linux-musl:
@@ -291,13 +290,12 @@ linux:
       - debug
       - noopt
       - lto
-    # freethreaded builds require mimalloc which is not available on musl yet
-    # build_options_conditional:
-    #   - options:
-    #       - freethreaded+debug
-    #       - freethreaded+noopt
-    #       - freethreaded+lto
-    #     minimum-python-version: "3.13"
+    build_options_conditional:
+      - options:
+          - freethreaded+debug
+          - freethreaded+noopt
+          - freethreaded+lto
+        minimum-python-version: "3.13"
     run: true
 
   x86_64_v3-unknown-linux-musl:
@@ -318,13 +316,12 @@ linux:
       - debug
       - noopt
       - lto
-    # freethreaded builds require mimalloc which is not available on musl yet
-    # build_options_conditional:
-    #   - options:
-    #       - freethreaded+debug
-    #       - freethreaded+noopt
-    #       - freethreaded+lto
-    #     minimum-python-version: "3.13"
+    build_options_conditional:
+      - options:
+          - freethreaded+debug
+          - freethreaded+noopt
+          - freethreaded+lto
+        minimum-python-version: "3.13"
     run: true
 
   x86_64_v4-unknown-linux-musl:
@@ -345,13 +342,12 @@ linux:
       - debug
       - noopt
       - lto
-    # freethreaded builds require mimalloc which is not available on musl yet
-    # build_options_conditional:
-    #   - options:
-    #       - freethreaded+debug
-    #       - freethreaded+noopt
-    #       - freethreaded+lto
-    #     minimum-python-version: "3.13"
+    build_options_conditional:
+      - options:
+          - freethreaded+debug
+          - freethreaded+noopt
+          - freethreaded+lto
+        minimum-python-version: "3.13"
     run: true
 
 windows:
diff --git a/cpython-unix/build-cpython.sh b/cpython-unix/build-cpython.sh
index bd045e91..68d0bde2 100755
--- a/cpython-unix/build-cpython.sh
+++ b/cpython-unix/build-cpython.sh
@@ -401,6 +401,22 @@ if [ "${CC}" = "musl-clang" ]; then
     done
 fi
 
+# To enable mimalloc (which is hard requirement for free-threaded versions, but preferred in
+# general), we need `stdatomic.h` which is not provided by musl. It's a part of the include files
+# that are part of clang. But musl-clang eliminates them from the default include path. So copy it
+# into place.
+if [[ "${CC}" = "musl-clang" && -n "${PYTHON_MEETS_MINIMUM_VERSION_3_13}" ]]; then
+    for h in /tools/${TOOLCHAIN}/lib/clang/*/include/stdatomic.h; do
+        filename=$(basename "$h")
+        if [ -e "/tools/host/include/${filename}" ]; then
+            echo "${filename} already exists; don't need to copy!"
+            exit 1
+        fi
+        cp "$h" /tools/host/include/
+    done
+fi
+
+
 if [ -n "${CPYTHON_STATIC}" ]; then
     CFLAGS="${CFLAGS} -static"
     CPPFLAGS="${CPPFLAGS} -static"
@@ -416,8 +432,8 @@ if [ -n "${CPYTHON_DEBUG}" ]; then
 fi
 
 # Explicitly enable mimalloc on 3.13+, it's already included by default but with this it'll fail
-# if it's missing from the system. The musl builds do not supprt mimalloc yet.
-if [[ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_13}" && "${CC}" != "musl-clang" ]]; then
+# if it's missing from the system.
+if [[ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_13}" ]]; then
     CONFIGURE_FLAGS="${CONFIGURE_FLAGS} --with-mimalloc"
 fi
 

From 4df7acf2a98a59d22118ec1d2eb5717a157c8b81 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Fri, 4 Apr 2025 18:27:20 -0500
Subject: [PATCH 070/157] Bump openssl from 0.10.70 to 0.10.72 (#577)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Bumps [openssl](https://github.com/sfackler/rust-openssl) from 0.10.70
to 0.10.72.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/sfackler/rust-openssl/releases">openssl's
releases</a>.</em></p>
<blockquote>
<h2>openssl-v0.10.72</h2>
<h2>What's Changed</h2>
<ul>
<li>make set_rsa_oaep_md visible to boringssl config by <a
href="https://github.com/frncs-rss"><code>@​frncs-rss</code></a> in <a
href="https://redirect.github.com/sfackler/rust-openssl/pull/2372">sfackler/rust-openssl#2372</a></li>
<li>Fix typo in openssl-sys build script by <a
href="https://github.com/rushilmehra"><code>@​rushilmehra</code></a> in
<a
href="https://redirect.github.com/sfackler/rust-openssl/pull/2375">sfackler/rust-openssl#2375</a></li>
<li>Unify the two BoringSSL codepaths a bit and simplify init by <a
href="https://github.com/davidben"><code>@​davidben</code></a> in <a
href="https://redirect.github.com/sfackler/rust-openssl/pull/2377">sfackler/rust-openssl#2377</a></li>
<li>pkey_ctx: Fix link to the corresponding OpenSSL function by <a
href="https://github.com/Jakuje"><code>@​Jakuje</code></a> in <a
href="https://redirect.github.com/sfackler/rust-openssl/pull/2378">sfackler/rust-openssl#2378</a></li>
<li>fix test on MSRV by <a
href="https://github.com/alex"><code>@​alex</code></a> in <a
href="https://redirect.github.com/sfackler/rust-openssl/pull/2383">sfackler/rust-openssl#2383</a></li>
<li>Add support for AWS-LC to openssl and openssl-sys crates by <a
href="https://github.com/skmcgrail"><code>@​skmcgrail</code></a> in <a
href="https://redirect.github.com/sfackler/rust-openssl/pull/1805">sfackler/rust-openssl#1805</a></li>
<li>Enable additional capabilities for AWS-LC by <a
href="https://github.com/skmcgrail"><code>@​skmcgrail</code></a> in <a
href="https://redirect.github.com/sfackler/rust-openssl/pull/2386">sfackler/rust-openssl#2386</a></li>
<li>Use --experimental with bindgen-cli with aws-lc build by <a
href="https://github.com/skmcgrail"><code>@​skmcgrail</code></a> in <a
href="https://redirect.github.com/sfackler/rust-openssl/pull/2389">sfackler/rust-openssl#2389</a></li>
<li>Fixed two UAFs and bumped versions for release by <a
href="https://github.com/alex"><code>@​alex</code></a> in <a
href="https://redirect.github.com/sfackler/rust-openssl/pull/2390">sfackler/rust-openssl#2390</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/Jakuje"><code>@​Jakuje</code></a> made
their first contribution in <a
href="https://redirect.github.com/sfackler/rust-openssl/pull/2378">sfackler/rust-openssl#2378</a></li>
<li><a href="https://github.com/skmcgrail"><code>@​skmcgrail</code></a>
made their first contribution in <a
href="https://redirect.github.com/sfackler/rust-openssl/pull/1805">sfackler/rust-openssl#1805</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.71...openssl-v0.10.72">https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.71...openssl-v0.10.72</a></p>
<h2>openssl-v0.10.71</h2>
<h2>What's Changed</h2>
<ul>
<li>Expose rc2 ciphers on symm::Cipher by <a
href="https://github.com/alex"><code>@​alex</code></a> in <a
href="https://redirect.github.com/sfackler/rust-openssl/pull/2361">sfackler/rust-openssl#2361</a></li>
<li>add full Apache license file to openssl by <a
href="https://github.com/frncs-rss"><code>@​frncs-rss</code></a> in <a
href="https://redirect.github.com/sfackler/rust-openssl/pull/2366">sfackler/rust-openssl#2366</a></li>
<li>Release openssl v0.10.71 and openssl-sys v0.9.106 by <a
href="https://github.com/alex"><code>@​alex</code></a> in <a
href="https://redirect.github.com/sfackler/rust-openssl/pull/2369">sfackler/rust-openssl#2369</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/frncs-rss"><code>@​frncs-rss</code></a>
made their first contribution in <a
href="https://redirect.github.com/sfackler/rust-openssl/pull/2366">sfackler/rust-openssl#2366</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.70...openssl-v0.10.71">https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.70...openssl-v0.10.71</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/sfackler/rust-openssl/commit/87085bd67896b7f92e6de35d081f607a334beae4"><code>87085bd</code></a>
Merge pull request <a
href="https://redirect.github.com/sfackler/rust-openssl/issues/2390">#2390</a>
from alex/uaf-fix</li>
<li><a
href="https://github.com/sfackler/rust-openssl/commit/d1a12e21573e95727b2e38b8b65273cb389be7e4"><code>d1a12e2</code></a>
Fixed two UAFs and bumped versions for release</li>
<li><a
href="https://github.com/sfackler/rust-openssl/commit/7c7b2e6c9f95e77e56ab37af70b16de75beff387"><code>7c7b2e6</code></a>
Merge pull request <a
href="https://redirect.github.com/sfackler/rust-openssl/issues/2389">#2389</a>
from skmcgrail/aws-lc-follow-up</li>
<li><a
href="https://github.com/sfackler/rust-openssl/commit/34a477bff20cbe43492915338d3c12597430c345"><code>34a477b</code></a>
Use --experimental with bindgen-cli with aws-lc build</li>
<li><a
href="https://github.com/sfackler/rust-openssl/commit/d4bf0710640e4725b8b237968040aef3e5f4ab9a"><code>d4bf071</code></a>
Merge pull request <a
href="https://redirect.github.com/sfackler/rust-openssl/issues/2386">#2386</a>
from skmcgrail/aws-lc-follow-up</li>
<li><a
href="https://github.com/sfackler/rust-openssl/commit/a86bf670c4cba3ee5531838b52419356791d966e"><code>a86bf67</code></a>
Remove comment</li>
<li><a
href="https://github.com/sfackler/rust-openssl/commit/705dbfb2ee3f2d7151ff313d840bf558435d4379"><code>705dbfb</code></a>
Fix test</li>
<li><a
href="https://github.com/sfackler/rust-openssl/commit/e0df413d46a89303c42e15bf7d4566193b242466"><code>e0df413</code></a>
Skip final call for LibreSSL 4.1.0 for CCM mode</li>
<li><a
href="https://github.com/sfackler/rust-openssl/commit/2f1164b5e838d3665dd10a9fac19e22174289ea3"><code>2f1164b</code></a>
Enable additional capabilities for AWS-LC</li>
<li><a
href="https://github.com/sfackler/rust-openssl/commit/dde9ffb36071249ff98474eec853fd830aea44f5"><code>dde9ffb</code></a>
Merge pull request <a
href="https://redirect.github.com/sfackler/rust-openssl/issues/1805">#1805</a>
from skmcgrail/aws-lc-support-final</li>
<li>Additional commits viewable in <a
href="https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.70...openssl-v0.10.72">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=openssl&package-manager=cargo&previous-version=0.10.70&new-version=0.10.72)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/astral-sh/python-build-standalone/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
 Cargo.lock | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 3b391954..e6a3dd8a 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1330,9 +1330,9 @@ checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
 
 [[package]]
 name = "openssl"
-version = "0.10.70"
+version = "0.10.72"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "61cfb4e166a8bb8c9b55c500bc2308550148ece889be90f609377e58140f42c6"
+checksum = "fedfea7d58a1f73118430a55da6a286e7b044961736ce96a16a17068ea25e5da"
 dependencies = [
  "bitflags 2.8.0",
  "cfg-if",
@@ -1362,9 +1362,9 @@ checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e"
 
 [[package]]
 name = "openssl-sys"
-version = "0.9.105"
+version = "0.9.107"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8b22d5b84be05a8d6947c7cb71f7c849aa0f112acd4bf51c2a7c1c988ac0a9dc"
+checksum = "8288979acd84749c744a9014b4382d42b8f7b2592847b5afb2ed29e5d16ede07"
 dependencies = [
  "cc",
  "libc",

From 186813f11c67ce8f6b424b4c355f7052204a04cc Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Tue, 8 Apr 2025 22:36:14 -0500
Subject: [PATCH 071/157] Bump stable Python versions: 3.13.3, 3.12.10,
 3.11.12, 3.10.17 and 3.9.22 (#579)

---
 cpython-windows/build.py | 20 ++++++++++++--------
 pythonbuild/downloads.py | 40 ++++++++++++++++++++--------------------
 src/validation.rs        |  4 ++++
 3 files changed, 36 insertions(+), 28 deletions(-)

diff --git a/cpython-windows/build.py b/cpython-windows/build.py
index 47bdc493..7e4d78ac 100644
--- a/cpython-windows/build.py
+++ b/cpython-windows/build.py
@@ -564,14 +564,18 @@ def hack_project_files(
     except NoSearchStringError:
         pass
 
-    # Our custom OpenSSL build has applink.c in a different location
-    # from the binary OpenSSL distribution. Update it.
-    ssl_proj = pcbuild_path / "_ssl.vcxproj"
-    static_replace_in_file(
-        ssl_proj,
-        rb'<ClCompile Include="$(opensslIncludeDir)\applink.c">',
-        rb'<ClCompile Include="$(opensslIncludeDir)\openssl\applink.c">',
-    )
+    # Our custom OpenSSL build has applink.c in a different location from the
+    # binary OpenSSL distribution. This is no longer relevant for 3.12+ per
+    # https://github.com/python/cpython/pull/131839, so we allow it to fail.swe
+    try:
+        ssl_proj = pcbuild_path / "_ssl.vcxproj"
+        static_replace_in_file(
+            ssl_proj,
+            rb'<ClCompile Include="$(opensslIncludeDir)\applink.c">',
+            rb'<ClCompile Include="$(opensslIncludeDir)\openssl\applink.c">',
+        )
+    except NoSearchStringError:
+        pass
 
     # Python 3.12+ uses the the pre-built tk-windows-bin 8.6.12 which doesn't
     # have a standalone zlib DLL, so we remove references to it. For Python
diff --git a/pythonbuild/downloads.py b/pythonbuild/downloads.py
index 40b11a13..89f3ce08 100644
--- a/pythonbuild/downloads.py
+++ b/pythonbuild/downloads.py
@@ -37,46 +37,46 @@
         "license_file": "LICENSE.bzip2.txt",
     },
     "cpython-3.9": {
-        "url": "https://www.python.org/ftp/python/3.9.21/Python-3.9.21.tar.xz",
-        "size": 19647056,
-        "sha256": "3126f59592c9b0d798584755f2bf7b081fa1ca35ce7a6fea980108d752a05bb1",
-        "version": "3.9.21",
+        "url": "https://www.python.org/ftp/python/3.9.22/Python-3.9.22.tar.xz",
+        "size": 19652572,
+        "sha256": "8c136d199d3637a1fce98a16adc809c1d83c922d02d41f3614b34f8b6e7d38ec",
+        "version": "3.9.22",
         "licenses": ["Python-2.0", "CNRI-Python"],
         "license_file": "LICENSE.cpython.txt",
         "python_tag": "cp39",
     },
     "cpython-3.10": {
-        "url": "https://www.python.org/ftp/python/3.10.16/Python-3.10.16.tar.xz",
-        "size": 19610392,
-        "sha256": "bfb249609990220491a1b92850a07135ed0831e41738cf681d63cf01b2a8fbd1",
-        "version": "3.10.16",
+        "url": "https://www.python.org/ftp/python/3.10.17/Python-3.10.17.tar.xz",
+        "size": 19608144,
+        "sha256": "4c68050f049d1b4ac5aadd0df5f27941c0350d2a9e7ab0907ee5eb5225d9d6b0",
+        "version": "3.10.17",
         "licenses": ["Python-2.0", "CNRI-Python"],
         "license_file": "LICENSE.cpython.txt",
         "python_tag": "cp310",
     },
     "cpython-3.11": {
-        "url": "https://www.python.org/ftp/python/3.11.11/Python-3.11.11.tar.xz",
-        "size": 20085792,
-        "sha256": "2a9920c7a0cd236de33644ed980a13cbbc21058bfdc528febb6081575ed73be3",
-        "version": "3.11.11",
+        "url": "https://www.python.org/ftp/python/3.11.12/Python-3.11.12.tar.xz",
+        "size": 20112232,
+        "sha256": "849da87af4df137710c1796e276a955f7a85c9f971081067c8f565d15c352a09",
+        "version": "3.11.12",
         "licenses": ["Python-2.0", "CNRI-Python"],
         "license_file": "LICENSE.cpython.txt",
         "python_tag": "cp311",
     },
     "cpython-3.12": {
-        "url": "https://www.python.org/ftp/python/3.12.9/Python-3.12.9.tar.xz",
-        "size": 20502440,
-        "sha256": "7220835d9f90b37c006e9842a8dff4580aaca4318674f947302b8d28f3f81112",
-        "version": "3.12.9",
+        "url": "https://www.python.org/ftp/python/3.12.10/Python-3.12.10.tar.xz",
+        "size": 20520960,
+        "sha256": "07ab697474595e06f06647417d3c7fa97ded07afc1a7e4454c5639919b46eaea",
+        "version": "3.12.10",
         "licenses": ["Python-2.0", "CNRI-Python"],
         "license_file": "LICENSE.cpython.txt",
         "python_tag": "cp312",
     },
     "cpython-3.13": {
-        "url": "https://www.python.org/ftp/python/3.13.2/Python-3.13.2.tar.xz",
-        "size": 22621108,
-        "sha256": "d984bcc57cd67caab26f7def42e523b1c015bbc5dc07836cf4f0b63fa159eb56",
-        "version": "3.13.2",
+        "url": "https://www.python.org/ftp/python/3.13.3/Python-3.13.3.tar.xz",
+        "size": 22654240,
+        "sha256": "40f868bcbdeb8149a3149580bb9bfd407b3321cd48f0be631af955ac92c0e041",
+        "version": "3.13.3",
         "licenses": ["Python-2.0", "CNRI-Python"],
         "license_file": "LICENSE.cpython.txt",
         "python_tag": "cp313",
diff --git a/src/validation.rs b/src/validation.rs
index df0c940f..747cdaed 100644
--- a/src/validation.rs
+++ b/src/validation.rs
@@ -1596,6 +1596,10 @@ fn validate_extension_modules(
         ]);
     }
 
+    if is_windows && matches!(python_major_minor, "3.13") {
+        wanted.extend(["_suggestions"]);
+    }
+
     if (is_linux || is_macos) && matches!(python_major_minor, "3.13" | "3.14") {
         wanted.extend(["_suggestions", "_testexternalinspection"]);
     }

From 50e3f681bb441b78b07386ed1113f9c56716f433 Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Wed, 9 Apr 2025 10:43:46 -0500
Subject: [PATCH 072/157] Include Python 3.14 in published musl distributions
 (#582)

Follows #558
---
 .github/workflows/release.yml | 1 +
 src/release.rs                | 9 ++++-----
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index ce803392..7a06d07e 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -21,6 +21,7 @@ env:
 permissions:
   contents: write
   packages: write
+  releases: wrte
   # Permissions used for actions/attest-build-provenance
   id-token: write
   attestations: write
diff --git a/src/release.rs b/src/release.rs
index 10e562ca..9d6ec083 100644
--- a/src/release.rs
+++ b/src/release.rs
@@ -274,13 +274,12 @@ pub static RELEASE_TRIPLES: Lazy<BTreeMap<&'static str, TripleRelease>> = Lazy::
             }],
         },
     );
-    // TODO: Python 3.14 support on musl
     h.insert(
         "x86_64-unknown-linux-musl",
         TripleRelease {
             suffixes: linux_suffixes_musl.clone(),
             install_only_suffix: "lto",
-            python_version_requirement: Some(VersionSpecifier::from_str("<3.14").unwrap()),
+            python_version_requirement: None,
             conditional_suffixes: vec![],
         },
     );
@@ -289,7 +288,7 @@ pub static RELEASE_TRIPLES: Lazy<BTreeMap<&'static str, TripleRelease>> = Lazy::
         TripleRelease {
             suffixes: linux_suffixes_musl.clone(),
             install_only_suffix: "lto",
-            python_version_requirement: Some(VersionSpecifier::from_str("<3.14").unwrap()),
+            python_version_requirement: None,
             conditional_suffixes: vec![],
         },
     );
@@ -298,7 +297,7 @@ pub static RELEASE_TRIPLES: Lazy<BTreeMap<&'static str, TripleRelease>> = Lazy::
         TripleRelease {
             suffixes: linux_suffixes_musl.clone(),
             install_only_suffix: "lto",
-            python_version_requirement: Some(VersionSpecifier::from_str("<3.14").unwrap()),
+            python_version_requirement: None,
             conditional_suffixes: vec![],
         },
     );
@@ -307,7 +306,7 @@ pub static RELEASE_TRIPLES: Lazy<BTreeMap<&'static str, TripleRelease>> = Lazy::
         TripleRelease {
             suffixes: linux_suffixes_musl.clone(),
             install_only_suffix: "lto",
-            python_version_requirement: Some(VersionSpecifier::from_str("<3.14").unwrap()),
+            python_version_requirement: None,
             conditional_suffixes: vec![],
         },
     );

From 6b8bdb02afd0fe4e8b85614d8a9ccfbfea6efb53 Mon Sep 17 00:00:00 2001
From: Leonard de Ruijter <3049216+LeonarddeR@users.noreply.github.com>
Date: Wed, 7 May 2025 14:52:46 +0200
Subject: [PATCH 073/157] Docs: remove Windows static build quirk (#598)

The docs say that [Windows Static Distributions are Extremely
Brittle](https://github.com/astral-sh/python-build-standalone/blob/main/docs/quirks.rst#windows-static-distributions-are-extremely-brittle).
However, since #234, Windows static builds no longer exist, making this
documentation obsolete.

Fixes #597
---
 docs/quirks.rst | 27 ---------------------------
 1 file changed, 27 deletions(-)

diff --git a/docs/quirks.rst b/docs/quirks.rst
index 77e4d4fe..aeb8ec57 100644
--- a/docs/quirks.rst
+++ b/docs/quirks.rst
@@ -109,33 +109,6 @@ To use pip, run ``python.exe -m pip``. (It is generally a best practice to
 invoke pip via ``python -m pip`` on all platforms so you can be explicit
 about the ``python`` executable that pip uses.)
 
-.. _quirk_windows_static_distributions:
-
-Windows Static Distributions are Extremely Brittle
-==================================================
-
-This project produces statically linked CPython distributions for Windows.
-
-Building these distributions requires extensive patching of CPython's build
-system. There are many aspects of CPython, the standard library, and 3rd party
-libraries that make assumptions that things will be built as dynamic libraries
-and break in these static builds.
-
-Here is a list of known problems:
-
-* Most Windows extension modules link against ``pythonXY.dll`` (e.g.
-  ``python39.dll``) or ``python3.dll`` and will fail to load on the static
-  distributions. Extension modules will need to be explicitly recompiled
-  against the static distribution.
-* There is no supported *platform tag* for Windows static distributions and
-  therefore there is no supported way to distribute binary wheels targeting
-  the Python static distributions.
-* Aspects of OpenSSL (and therefore Python's ``ssl`` module) don't work when
-  OpenSSL is compiled/linked statically. You will get opaque run-time errors.
-
-It is **highly** recommended to extensively test your application against the
-static Windows distributions to ensure it works.
-
 .. _quirk_macos_linking:
 
 Linking Static Library on macOS

From 266955f557433a958aac393df9fd11e66fb4a570 Mon Sep 17 00:00:00 2001
From: Geoffrey Thomas <geofft@ldpreload.com>
Date: Sat, 19 Apr 2025 16:30:43 -0400
Subject: [PATCH 074/157] Statically link libpython into interpreter (but keep
 building libpython3.x.so)

---
 cpython-unix/build-cpython.sh                 |  9 ++
 ...tatic-libpython-for-interpreter-3.10.patch | 93 +++++++++++++++++++
 ...tatic-libpython-for-interpreter-3.11.patch | 69 ++++++++++++++
 ...static-libpython-for-interpreter-3.9.patch | 93 +++++++++++++++++++
 ...ble-static-libpython-for-interpreter.patch | 86 +++++++++++++++++
 5 files changed, 350 insertions(+)
 create mode 100644 cpython-unix/patch-python-configure-add-enable-static-libpython-for-interpreter-3.10.patch
 create mode 100644 cpython-unix/patch-python-configure-add-enable-static-libpython-for-interpreter-3.11.patch
 create mode 100644 cpython-unix/patch-python-configure-add-enable-static-libpython-for-interpreter-3.9.patch
 create mode 100644 cpython-unix/patch-python-configure-add-enable-static-libpython-for-interpreter.patch

diff --git a/cpython-unix/build-cpython.sh b/cpython-unix/build-cpython.sh
index 68d0bde2..4d5ae1c4 100755
--- a/cpython-unix/build-cpython.sh
+++ b/cpython-unix/build-cpython.sh
@@ -298,6 +298,14 @@ if [ -n "${PYTHON_MEETS_MAXIMUM_VERSION_3_10}" ]; then
     patch -p1 -i ${ROOT}/patch-configure-crypt-no-modify-libs.patch
 fi
 
+# Build a libpython3.x.so, but statically link the interpreter against
+# libpython.
+if [ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_12}" ]; then
+    patch -p1 -i "${ROOT}/patch-python-configure-add-enable-static-libpython-for-interpreter.patch"
+else
+    patch -p1 -i "${ROOT}/patch-python-configure-add-enable-static-libpython-for-interpreter-${PYTHON_MAJMIN_VERSION}.patch"
+fi
+
 # We patched configure.ac above. Reflect those changes.
 autoconf
 
@@ -382,6 +390,7 @@ CONFIGURE_FLAGS="
     --with-system-expat
     --with-system-libmpdec
     --without-ensurepip
+    --enable-static-libpython-for-interpreter
     ${EXTRA_CONFIGURE_FLAGS}"
 
 
diff --git a/cpython-unix/patch-python-configure-add-enable-static-libpython-for-interpreter-3.10.patch b/cpython-unix/patch-python-configure-add-enable-static-libpython-for-interpreter-3.10.patch
new file mode 100644
index 00000000..33bd662a
--- /dev/null
+++ b/cpython-unix/patch-python-configure-add-enable-static-libpython-for-interpreter-3.10.patch
@@ -0,0 +1,93 @@
+From 579a7cf9498ccfa656dd720a5db8dd6e04e97150 Mon Sep 17 00:00:00 2001
+From: Geoffrey Thomas <geofft@ldpreload.com>
+Date: Sat, 19 Apr 2025 11:13:40 -0400
+Subject: [PATCH 1/1] configure: add --enable-static-libpython-for-interpreter
+
+This option changes the behavior of --enable-shared to continue to build
+the libpython3.x.so shared library, but not use it for linking the
+python3 interpreter executable. Instead, the executable is linked
+directly against the libpython .o files as it would be with
+--disable-shared [in newer versions of Python].
+
+There are two benefits of this change. First, libpython uses
+thread-local storage, which is noticeably slower when used in a loaded
+module instead of in the main program, because the main program can take
+advantage of constant offsets from the thread state pointer but loaded
+modules have to dynamically call a function __tls_get_addr() to
+potentially allocate their thread-local storage area. (There is another
+thread-local storage model for dynamic libraries which mitigates most of
+this performance hit, but it comes at the cost of preventing
+dlopen("libpython3.x.so"), which is a use case we want to preserve.)
+
+Second, this improves the user experience around relocatable Python a
+little bit, in that we don't need to use an $ORIGIN-relative path to
+locate libpython3.x.so, which has some mild benefits around musl (which
+does not support $ORIGIN-relative DT_NEEDED, only $ORIGIN-relative
+DT_RPATH/DT_RUNPATH), users who want to make the interpreter setuid or
+setcap (which prevents processing $ORIGIN), etc.
+---
+ Makefile.pre.in |  4 +++-
+ configure.ac    | 18 ++++++++++++++++++
+ 2 files changed, 21 insertions(+), 1 deletion(-)
+
+diff --git a/Makefile.pre.in b/Makefile.pre.in
+index fa99dd86c41..84c00a5c071 100644
+--- a/Makefile.pre.in
++++ b/Makefile.pre.in
+@@ -458,6 +458,8 @@ LIBRARY_OBJS=	\
+ 		$(LIBRARY_OBJS_OMIT_FROZEN) \
+ 		Python/frozen.o
+ 
++LINK_PYTHON_OBJS=@LINK_PYTHON_OBJS@
++
+ ##########################################################################
+ # DTrace
+ 
+@@ -586,7 +588,7 @@ clinic: check-clean-src $(srcdir)/Modules/_blake2/blake2s_impl.c
+ 
+ # Build the interpreter
+ $(BUILDPYTHON):	Programs/python.o $(LIBRARY_DEPS)
+-	$(LINKCC) $(PY_CORE_LDFLAGS) $(LINKFORSHARED) -o $@ Programs/python.o $(BLDLIBRARY) $(LIBS) $(MODLIBS) $(SYSLIBS)
++	$(LINKCC) $(PY_CORE_LDFLAGS) $(LINKFORSHARED) -o $@ Programs/python.o $(LINK_PYTHON_OBJS) $(LIBS) $(MODLIBS) $(SYSLIBS)
+ 
+ platform: $(BUILDPYTHON) pybuilddir.txt
+ 	$(RUNSHARED) $(PYTHON_FOR_BUILD) -c 'import sys ; from sysconfig import get_platform ; print("%s-%d.%d" % (get_platform(), *sys.version_info[:2]))' >platform
+diff --git a/configure.ac b/configure.ac
+index ac3be3850a9..a07003a24ed 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -1093,6 +1093,17 @@ then
+ fi
+ AC_MSG_RESULT($enable_shared)
+ 
++AC_MSG_CHECKING([for --enable-static-libpython-for-interpreter])
++AC_ARG_ENABLE([static-libpython-for-interpreter],
++   AS_HELP_STRING([--enable-static-libpython-for-interpreter],
++                  [even with --enable-shared, statically link libpython into the interpreter (default is to use the shared library)]))
++
++if test -z "$enable_static_libpython_for_interpreter"
++then
++  enable_static_libpython_for_interpreter="no"
++fi
++AC_MSG_RESULT([$enable_static_libpython_for_interpreter])
++
+ AC_MSG_CHECKING(for --enable-profiling)
+ AC_ARG_ENABLE(profiling,
+               AS_HELP_STRING([--enable-profiling], [enable C-level code profiling with gprof (default is no)]))
+@@ -1198,6 +1209,13 @@ fi
+ 
+ AC_MSG_RESULT($LDLIBRARY)
+ 
++if test "$enable_static_libpython_for_interpreter" = "yes"; then
++    LINK_PYTHON_OBJS='$(LIBRARY_OBJS)'
++else
++    LINK_PYTHON_OBJS='$(BLDLIBRARY)'
++fi
++AC_SUBST(LINK_PYTHON_OBJS)
++
+ AC_SUBST(AR)
+ AC_CHECK_TOOLS(AR, ar aal, ar)
+ 
+-- 
+2.39.5 (Apple Git-154)
+
diff --git a/cpython-unix/patch-python-configure-add-enable-static-libpython-for-interpreter-3.11.patch b/cpython-unix/patch-python-configure-add-enable-static-libpython-for-interpreter-3.11.patch
new file mode 100644
index 00000000..4a9a7651
--- /dev/null
+++ b/cpython-unix/patch-python-configure-add-enable-static-libpython-for-interpreter-3.11.patch
@@ -0,0 +1,69 @@
+From a5182aec2c0597adb8a01298af120809fcf3187b Mon Sep 17 00:00:00 2001
+From: Geoffrey Thomas <geofft@ldpreload.com>
+Date: Sat, 19 Apr 2025 11:13:40 -0400
+Subject: [PATCH 1/1] configure: add --enable-static-libpython-for-interpreter
+
+This option changes the behavior of --enable-shared to continue to build
+the libpython3.x.so shared library, but not use it for linking the
+python3 interpreter executable. Instead, the executable is linked
+directly against the libpython .o files as it would be with
+--disable-shared.
+
+There are two benefits of this change. First, libpython uses
+thread-local storage, which is noticeably slower when used in a loaded
+module instead of in the main program, because the main program can take
+advantage of constant offsets from the thread state pointer but loaded
+modules have to dynamically call a function __tls_get_addr() to
+potentially allocate their thread-local storage area. (There is another
+thread-local storage model for dynamic libraries which mitigates most of
+this performance hit, but it comes at the cost of preventing
+dlopen("libpython3.x.so"), which is a use case we want to preserve.)
+
+Second, this improves the user experience around relocatable Python a
+little bit, in that we don't need to use an $ORIGIN-relative path to
+locate libpython3.x.so, which has some mild benefits around musl (which
+does not support $ORIGIN-relative DT_NEEDED, only $ORIGIN-relative
+DT_RPATH/DT_RUNPATH), users who want to make the interpreter setuid or
+setcap (which prevents processing $ORIGIN), etc.
+---
+ configure.ac | 17 ++++++++++++++++-
+ 1 file changed, 16 insertions(+), 1 deletion(-)
+
+diff --git a/configure.ac b/configure.ac
+index ab5e1de6fab..6783c36da4d 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -1419,6 +1419,17 @@ fi],
+ [AC_MSG_RESULT(yes)])
+ AC_SUBST(STATIC_LIBPYTHON)
+ 
++AC_MSG_CHECKING([for --enable-static-libpython-for-interpreter])
++AC_ARG_ENABLE([static-libpython-for-interpreter],
++   AS_HELP_STRING([--enable-static-libpython-for-interpreter],
++                  [even with --enable-shared, statically link libpython into the interpreter (default is to use the shared library)]))
++
++if test -z "$enable_static_libpython_for_interpreter"
++then
++  enable_static_libpython_for_interpreter="no"
++fi
++AC_MSG_RESULT([$enable_static_libpython_for_interpreter])
++
+ AC_MSG_CHECKING(for --enable-profiling)
+ AC_ARG_ENABLE(profiling,
+               AS_HELP_STRING([--enable-profiling], [enable C-level code profiling with gprof (default is no)]))
+@@ -1563,7 +1574,11 @@ if test "$PY_ENABLE_SHARED" = 1 || test "$enable_framework" ; then
+         LIBRARY_DEPS="\$(LIBRARY) $LIBRARY_DEPS"
+     fi
+     # Link Python program to the shared library
+-    LINK_PYTHON_OBJS='$(BLDLIBRARY)'
++    if test "$enable_static_libpython_for_interpreter" = "yes"; then
++        LINK_PYTHON_OBJS='$(LIBRARY_OBJS)'
++    else
++        LINK_PYTHON_OBJS='$(BLDLIBRARY)'
++    fi
+ else
+     if test "$STATIC_LIBPYTHON" = 0; then
+         # Build Python needs object files but don't need to build
+-- 
+2.39.5 (Apple Git-154)
+
diff --git a/cpython-unix/patch-python-configure-add-enable-static-libpython-for-interpreter-3.9.patch b/cpython-unix/patch-python-configure-add-enable-static-libpython-for-interpreter-3.9.patch
new file mode 100644
index 00000000..d2c0a45c
--- /dev/null
+++ b/cpython-unix/patch-python-configure-add-enable-static-libpython-for-interpreter-3.9.patch
@@ -0,0 +1,93 @@
+From 5ae9112a87d45c3aff5ee269ff8e2e49ca278ed3 Mon Sep 17 00:00:00 2001
+From: Geoffrey Thomas <geofft@ldpreload.com>
+Date: Sat, 19 Apr 2025 11:13:40 -0400
+Subject: [PATCH 1/1] configure: add --enable-static-libpython-for-interpreter
+
+This option changes the behavior of --enable-shared to continue to build
+the libpython3.x.so shared library, but not use it for linking the
+python3 interpreter executable. Instead, the executable is linked
+directly against the libpython .o files as it would be with
+--disable-shared [in newer versions of Python].
+
+There are two benefits of this change. First, libpython uses
+thread-local storage, which is noticeably slower when used in a loaded
+module instead of in the main program, because the main program can take
+advantage of constant offsets from the thread state pointer but loaded
+modules have to dynamically call a function __tls_get_addr() to
+potentially allocate their thread-local storage area. (There is another
+thread-local storage model for dynamic libraries which mitigates most of
+this performance hit, but it comes at the cost of preventing
+dlopen("libpython3.x.so"), which is a use case we want to preserve.)
+
+Second, this improves the user experience around relocatable Python a
+little bit, in that we don't need to use an $ORIGIN-relative path to
+locate libpython3.x.so, which has some mild benefits around musl (which
+does not support $ORIGIN-relative DT_NEEDED, only $ORIGIN-relative
+DT_RPATH/DT_RUNPATH), users who want to make the interpreter setuid or
+setcap (which prevents processing $ORIGIN), etc.
+---
+ Makefile.pre.in |  4 +++-
+ configure.ac    | 18 ++++++++++++++++++
+ 2 files changed, 21 insertions(+), 1 deletion(-)
+
+diff --git a/Makefile.pre.in b/Makefile.pre.in
+index a276d535c7f..193439aa73e 100644
+--- a/Makefile.pre.in
++++ b/Makefile.pre.in
+@@ -460,6 +460,8 @@ LIBRARY_OBJS=	\
+ 		$(LIBRARY_OBJS_OMIT_FROZEN) \
+ 		Python/frozen.o
+ 
++LINK_PYTHON_OBJS=@LINK_PYTHON_OBJS@
++
+ ##########################################################################
+ # DTrace
+ 
+@@ -589,7 +591,7 @@ clinic: check-clean-src $(srcdir)/Modules/_blake2/blake2s_impl.c
+ 
+ # Build the interpreter
+ $(BUILDPYTHON):	Programs/python.o $(LIBRARY) $(LDLIBRARY) $(PY3LIBRARY) $(EXPORTSYMS)
+-	$(LINKCC) $(PY_CORE_LDFLAGS) $(LINKFORSHARED) -o $@ Programs/python.o $(BLDLIBRARY) $(LIBS) $(MODLIBS) $(SYSLIBS)
++	$(LINKCC) $(PY_CORE_LDFLAGS) $(LINKFORSHARED) -o $@ Programs/python.o $(LINK_PYTHON_OBJS) $(LIBS) $(MODLIBS) $(SYSLIBS)
+ 
+ platform: $(BUILDPYTHON) pybuilddir.txt
+ 	$(RUNSHARED) $(PYTHON_FOR_BUILD) -c 'import sys ; from sysconfig import get_platform ; print("%s-%d.%d" % (get_platform(), *sys.version_info[:2]))' >platform
+diff --git a/configure.ac b/configure.ac
+index aa515da4655..122b11def62 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -1106,6 +1106,17 @@ then
+ fi
+ AC_MSG_RESULT($enable_shared)
+ 
++AC_MSG_CHECKING([for --enable-static-libpython-for-interpreter])
++AC_ARG_ENABLE([static-libpython-for-interpreter],
++   AS_HELP_STRING([--enable-static-libpython-for-interpreter],
++                  [even with --enable-shared, statically link libpython into the interpreter (default is to use the shared library)]))
++
++if test -z "$enable_static_libpython_for_interpreter"
++then
++  enable_static_libpython_for_interpreter="no"
++fi
++AC_MSG_RESULT([$enable_static_libpython_for_interpreter])
++
+ AC_MSG_CHECKING(for --enable-profiling)
+ AC_ARG_ENABLE(profiling,
+               AS_HELP_STRING([--enable-profiling], [enable C-level code profiling with gprof (default is no)]))
+@@ -1211,6 +1222,13 @@ fi
+ 
+ AC_MSG_RESULT($LDLIBRARY)
+ 
++if test "$enable_static_libpython_for_interpreter" = "yes"; then
++    LINK_PYTHON_OBJS='$(LIBRARY_OBJS)'
++else
++    LINK_PYTHON_OBJS='$(BLDLIBRARY)'
++fi
++AC_SUBST(LINK_PYTHON_OBJS)
++
+ AC_SUBST(AR)
+ AC_CHECK_TOOLS(AR, ar aal, ar)
+ 
+-- 
+2.39.5 (Apple Git-154)
+
diff --git a/cpython-unix/patch-python-configure-add-enable-static-libpython-for-interpreter.patch b/cpython-unix/patch-python-configure-add-enable-static-libpython-for-interpreter.patch
new file mode 100644
index 00000000..b8d23b52
--- /dev/null
+++ b/cpython-unix/patch-python-configure-add-enable-static-libpython-for-interpreter.patch
@@ -0,0 +1,86 @@
+From 439f6e6bb62482a98fb6765d723cedea12f3b10f Mon Sep 17 00:00:00 2001
+From: Geoffrey Thomas <geofft@ldpreload.com>
+Date: Sat, 19 Apr 2025 11:13:40 -0400
+Subject: [PATCH 1/1] configure: add --enable-static-libpython-for-interpreter
+
+This option changes the behavior of --enable-shared to continue to build
+the libpython3.x.so shared library, but not use it for linking the
+python3 interpreter executable. Instead, the executable is linked
+directly against the libpython .o files as it would be with
+--disable-shared.
+
+There are two benefits of this change. First, libpython uses
+thread-local storage, which is noticeably slower when used in a loaded
+module instead of in the main program, because the main program can take
+advantage of constant offsets from the thread state pointer but loaded
+modules have to dynamically call a function __tls_get_addr() to
+potentially allocate their thread-local storage area. (There is another
+thread-local storage model for dynamic libraries which mitigates most of
+this performance hit, but it comes at the cost of preventing
+dlopen("libpython3.x.so"), which is a use case we want to preserve.)
+
+Second, this improves the user experience around relocatable Python a
+little bit, in that we don't need to use an $ORIGIN-relative path to
+locate libpython3.x.so, which has some mild benefits around musl (which
+does not support $ORIGIN-relative DT_NEEDED, only $ORIGIN-relative
+DT_RPATH/DT_RUNPATH), users who want to make the interpreter setuid or
+setcap (which prevents processing $ORIGIN), etc.
+---
+ configure.ac | 24 +++++++++++++++++++++---
+ 1 file changed, 21 insertions(+), 3 deletions(-)
+
+diff --git a/configure.ac b/configure.ac
+index 004797b5233..a3a5ac1cdce 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -1502,6 +1502,17 @@ fi],
+ [AC_MSG_RESULT([yes])])
+ AC_SUBST([STATIC_LIBPYTHON])
+ 
++AC_MSG_CHECKING([for --enable-static-libpython-for-interpreter])
++AC_ARG_ENABLE([static-libpython-for-interpreter],
++   AS_HELP_STRING([--enable-static-libpython-for-interpreter],
++                  [even with --enable-shared, statically link libpython into the interpreter (default is to use the shared library)]))
++
++if test -z "$enable_static_libpython_for_interpreter"
++then
++  enable_static_libpython_for_interpreter="no"
++fi
++AC_MSG_RESULT([$enable_static_libpython_for_interpreter])
++
+ AC_MSG_CHECKING([for --enable-profiling])
+ AC_ARG_ENABLE([profiling],
+               AS_HELP_STRING([--enable-profiling], [enable C-level code profiling with gprof (default is no)]))
+@@ -1660,7 +1671,11 @@ if test "$PY_ENABLE_SHARED" = 1 || test "$enable_framework" ; then
+         LIBRARY_DEPS="\$(LIBRARY) $LIBRARY_DEPS"
+     fi
+     # Link Python program to the shared library
+-    LINK_PYTHON_OBJS='$(BLDLIBRARY)'
++    if test "$enable_static_libpython_for_interpreter" = "yes"; then
++        LINK_PYTHON_OBJS='$(LIBRARY_OBJS)'
++    else
++        LINK_PYTHON_OBJS='$(BLDLIBRARY)'
++    fi
+ else
+     if test "$STATIC_LIBPYTHON" = 0; then
+         # Build Python needs object files but don't need to build
+@@ -2166,11 +2181,14 @@ if test "$Py_BOLT" = 'true' ; then
+   fi
+ fi
+ 
+-dnl Enable BOLT of libpython if built.
++dnl Enable BOLT of libpython if built and used by the python3 binary.
++dnl (If it is built but not used, we cannot profile it.)
+ AC_SUBST([BOLT_BINARIES])
+ BOLT_BINARIES='$(BUILDPYTHON)'
+ AS_VAR_IF([enable_shared], [yes], [
+-  BOLT_BINARIES="${BOLT_BINARIES} \$(INSTSONAME)"
++  AS_VAR_IF([enable_static_libpython_for_interpreter], [no], [
++    BOLT_BINARIES="${BOLT_BINARIES} \$(INSTSONAME)"
++  ])
+ ])
+ 
+ AC_ARG_VAR(
+-- 
+2.39.5 (Apple Git-154)
+

From a205448b21a2c2cd5aa740963e7e0fa745995111 Mon Sep 17 00:00:00 2001
From: Geoffrey Thomas <geofft@ldpreload.com>
Date: Tue, 6 May 2025 15:52:35 -0400
Subject: [PATCH 075/157] Fix bad -pthread default when cross-compiling

Also, switch to using cross_compiling=yes instead of patching
./configure in place, which allows us to move rerunning autoconf to
right before running ./configure, avoiding the risk of patching
./configure.ac too late.

See #599.
---
 cpython-unix/build-cpython.sh                | 29 ++++++++++++--------
 cpython-unix/build.py                        | 17 ++++++++++--
 cpython-unix/patch-force-cross-compile.patch | 20 --------------
 3 files changed, 33 insertions(+), 33 deletions(-)
 delete mode 100644 cpython-unix/patch-force-cross-compile.patch

diff --git a/cpython-unix/build-cpython.sh b/cpython-unix/build-cpython.sh
index 4d5ae1c4..08db7a54 100755
--- a/cpython-unix/build-cpython.sh
+++ b/cpython-unix/build-cpython.sh
@@ -306,17 +306,6 @@ else
     patch -p1 -i "${ROOT}/patch-python-configure-add-enable-static-libpython-for-interpreter-${PYTHON_MAJMIN_VERSION}.patch"
 fi
 
-# We patched configure.ac above. Reflect those changes.
-autoconf
-
-# configure assumes cross compiling when host != target and doesn't provide a way to
-# override. Our target triple normalization may lead configure into thinking we
-# aren't cross-compiling when we are. So force a static "yes" value when our
-# build system says we are cross-compiling.
-if [ -n "${CROSS_COMPILING}" ]; then
-  patch -p1 -i ${ROOT}/patch-force-cross-compile.patch
-fi
-
 # BOLT instrumented binaries segfault in some test_embed tests for unknown reasons.
 # On 3.12 (minimum BOLT version), the segfault causes the test harness to
 # abort and BOLT optimization uses the partial test results. On 3.13, the segfault
@@ -582,6 +571,14 @@ else
 fi
 
 if [ -n "${CROSS_COMPILING}" ]; then
+    # configure assumes cross compiling when host != target and doesn't
+    # provide a way to override. Our target triple normalization may
+    # lead configure into thinking we aren't cross-compiling when we
+    # are. So force a static "yes" value when our build system says we
+    # are cross-compiling.
+    # See also https://savannah.gnu.org/support/?110348
+    CONFIGURE_FLAGS="${CONFIGURE_FLAGS} cross_compiling=yes"
+
     # configure doesn't like a handful of scenarios when cross-compiling.
     #
     # getaddrinfo buggy test fails for some reason. So we short-circuit it.
@@ -598,8 +595,18 @@ if [ -n "${CROSS_COMPILING}" ]; then
     if [ "${PYBUILD_PLATFORM}" != "macos" ]; then
         CONFIGURE_FLAGS="${CONFIGURE_FLAGS} ac_cv_working_tzset=yes"
     fi
+
+    # Also, it cannot detect whether the compiler supports -pthread or
+    # not, and conservatively defaults to no, which is not the right
+    # default on relatively modern compilers.
+    CONFIGURE_FLAGS="${CONFIGURE_FLAGS} ac_cv_pthread=yes"
+
+    # TODO: There are probably more of these, see #399.
 fi
 
+# We patched configure.ac above. Reflect those changes.
+autoconf
+
 CFLAGS=$CFLAGS CPPFLAGS=$CFLAGS LDFLAGS=$LDFLAGS \
     ./configure ${CONFIGURE_FLAGS}
 
diff --git a/cpython-unix/build.py b/cpython-unix/build.py
index c90f7deb..c17c84cd 100755
--- a/cpython-unix/build.py
+++ b/cpython-unix/build.py
@@ -562,6 +562,7 @@ def python_build_info(
     bi["object_file_format"] = object_file_format
 
     # Determine allowed libaries on Linux
+    libs = extra_metadata["python_config_vars"].get("LIBS", "").split()
     mips = target_triple.split("-")[0] in {"mips", "mipsel"}
     linux_allowed_system_libraries = LINUX_ALLOW_SYSTEM_LIBRARIES.copy()
     if mips and version == "3.13":
@@ -569,14 +570,26 @@ def python_build_info(
         linux_allowed_system_libraries.add("atomic")
     riscv = target_triple.split("-")[0] in {"riscv64"}
     if riscv:
-        # RISC-V binary often comes with libatomic on old GCC versions
+        # On older GCC versions, RISC-V sub-word atomic operations require a
+        # helper function found in libatomic. To facilitate this, GCC <15 adds
+        # "-latomic" to the definition of "-pthread". We think it's generally
+        # reasonable on RISC-V systems (but not all Linux systems in general)
+        # to expect a libatomic system library is installed.
+        #
+        # Because "-latomic" is implicitly added by "-pthread", it may not be
+        # found in the LIBS sysconfig variable, but we need to pretend it is so
+        # that it gets into PYTHON.json (in particular, so that the validation
+        # script accepts this dependency).
+        #
         # See https://github.com/riscvarchive/riscv-gcc/issues/12
         # https://github.com/riscvarchive/riscv-gcc/issues/337
         # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86005
+        # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104338
+        # https://github.com/gcc-mirror/gcc/commit/203f3060dd363361b172f7295f42bb6bf5ac0b3b
         linux_allowed_system_libraries.add("atomic")
+        libs.append("-latomic")
 
     # Add in core linking annotations.
-    libs = extra_metadata["python_config_vars"].get("LIBS", "").split()
     skip = False
     for i, lib in enumerate(libs):
         if skip:
diff --git a/cpython-unix/patch-force-cross-compile.patch b/cpython-unix/patch-force-cross-compile.patch
deleted file mode 100644
index 35f2c6db..00000000
--- a/cpython-unix/patch-force-cross-compile.patch
+++ /dev/null
@@ -1,20 +0,0 @@
-diff --git a/configure b/configure
-index d078887b2f..8f1ea07cd8 100755
---- a/configure
-+++ b/configure
-@@ -1329,14 +1329,7 @@ build=$build_alias
- host=$host_alias
- target=$target_alias
-
--# FIXME: To remove some day.
--if test "x$host_alias" != x; then
--  if test "x$build_alias" = x; then
--    cross_compiling=maybe
--  elif test "x$build_alias" != "x$host_alias"; then
--    cross_compiling=yes
--  fi
--fi
-+cross_compiling=yes
-
- ac_tool_prefix=
- test -n "$host_alias" && ac_tool_prefix=$host_alias-

From 46a3737cca179db1858533a8b68d923c51a91e3b Mon Sep 17 00:00:00 2001
From: Geoffrey Thomas <geofft@ldpreload.com>
Date: Fri, 16 May 2025 13:27:39 -0400
Subject: [PATCH 076/157] Skip --enable-static-libpython-on-interpreter on
 macos for now (#604)

---
 cpython-unix/build-cpython.sh | 25 ++++++++++++++++---------
 1 file changed, 16 insertions(+), 9 deletions(-)

diff --git a/cpython-unix/build-cpython.sh b/cpython-unix/build-cpython.sh
index 08db7a54..6505b629 100755
--- a/cpython-unix/build-cpython.sh
+++ b/cpython-unix/build-cpython.sh
@@ -298,14 +298,6 @@ if [ -n "${PYTHON_MEETS_MAXIMUM_VERSION_3_10}" ]; then
     patch -p1 -i ${ROOT}/patch-configure-crypt-no-modify-libs.patch
 fi
 
-# Build a libpython3.x.so, but statically link the interpreter against
-# libpython.
-if [ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_12}" ]; then
-    patch -p1 -i "${ROOT}/patch-python-configure-add-enable-static-libpython-for-interpreter.patch"
-else
-    patch -p1 -i "${ROOT}/patch-python-configure-add-enable-static-libpython-for-interpreter-${PYTHON_MAJMIN_VERSION}.patch"
-fi
-
 # BOLT instrumented binaries segfault in some test_embed tests for unknown reasons.
 # On 3.12 (minimum BOLT version), the segfault causes the test harness to
 # abort and BOLT optimization uses the partial test results. On 3.13, the segfault
@@ -379,10 +371,25 @@ CONFIGURE_FLAGS="
     --with-system-expat
     --with-system-libmpdec
     --without-ensurepip
-    --enable-static-libpython-for-interpreter
     ${EXTRA_CONFIGURE_FLAGS}"
 
 
+# Build a libpython3.x.so, but statically link the interpreter against
+# libpython.
+#
+# For now skip this on macos, because it causes some linker failures. Note that
+# this patch mildly conflicts with the macos-only patch-python-link-modules
+# applied above, so you will need to resolve that conflict if you re-enable
+# this for macos.
+if [ "${PYBUILD_PLATFORM}" != "macos" ]; then
+    if [ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_12}" ]; then
+        patch -p1 -i "${ROOT}/patch-python-configure-add-enable-static-libpython-for-interpreter.patch"
+    else
+        patch -p1 -i "${ROOT}/patch-python-configure-add-enable-static-libpython-for-interpreter-${PYTHON_MAJMIN_VERSION}.patch"
+    fi
+    CONFIGURE_FLAGS="${CONFIGURE_FLAGS} --enable-static-libpython-for-interpreter"
+fi
+
 if [ "${CC}" = "musl-clang" ]; then
     # In order to build the _blake2 extension module with SSE3+ instructions, we need
     # musl-clang to find headers that provide access to the intrinsics, as they are not

From 0c3baa4211d5ee5287f1d9b2c838b22ea53d0369 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Randy=20D=C3=B6ring?=
 <30527984+radoering@users.noreply.github.com>
Date: Sat, 17 May 2025 05:07:28 +0200
Subject: [PATCH 077/157] Fix potential filedescriptor leak by not applying
 `-hugify` (#594)

With `-hugify` the following tests fail with Python 3.12 and 3.13 on
Linux:

```
python -m test -v -m test_pass_fds_redirected test_subprocess.py
python -m test -v -m test_no_* test_cmd_line.py
python -m test -v -m test_close_file test_posix.py
```

Resolves: #586
---
 .../patch-configure-bolt-apply-flags-128514.patch         | 8 --------
 1 file changed, 8 deletions(-)

diff --git a/cpython-unix/patch-configure-bolt-apply-flags-128514.patch b/cpython-unix/patch-configure-bolt-apply-flags-128514.patch
index e810a482..e9d86432 100644
--- a/cpython-unix/patch-configure-bolt-apply-flags-128514.patch
+++ b/cpython-unix/patch-configure-bolt-apply-flags-128514.patch
@@ -12,11 +12,3 @@ index ee034e5a962..f1a69b7d4a7 100644
       -icf=1
       -inline-all
       -split-eh
-@@ -2196,6 +2197,7 @@ then
-      -dyno-stats
-      -use-gnu-stack
-      -frame-opt=hot
-+     -hugify
-    ")]
-   )
- fi

From 0964f0f89b5a1ed02397fcf856f9c34d3d62bc0e Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Fri, 16 May 2025 22:37:51 -0500
Subject: [PATCH 078/157] Bump to 3.14.0a7 (#580)

The big changes here are:

- Switching to zlib-ng on Windows
(https://github.com/python/cpython/pull/131438)
- Using hmac for hashing functions
(https://github.com/python/cpython/pull/130157)

---------

Co-authored-by: Geoffrey Thomas <geofft@ldpreload.com>
---
 cpython-unix/extension-modules.yml | 36 +++++++++++++++++++++++++-----
 cpython-windows/build.py           | 34 +++++++++++++++++++++-------
 pythonbuild/downloads.py           | 17 ++++++++++----
 src/validation.rs                  |  4 +++-
 4 files changed, 73 insertions(+), 18 deletions(-)

diff --git a/cpython-unix/extension-modules.yml b/cpython-unix/extension-modules.yml
index a8ff460f..c5207857 100644
--- a/cpython-unix/extension-modules.yml
+++ b/cpython-unix/extension-modules.yml
@@ -38,9 +38,6 @@ _blake2:
       - Modules/_hacl/include
       - Modules/_hacl/internal
       minimum-python-version: "3.14"
-  links-conditional:
-    - name: :libHacl_Hash_Blake2.a
-      minimum-python-version: "3.14"
   defines-conditional:
     - define: _BSD_SOURCE
       minimum-python-version: "3.14"
@@ -311,6 +308,25 @@ _heapq:
   sources:
     - _heapqmodule.c
 
+_hmac:
+  minimum-python-version: '3.14'
+  sources:
+    - hmacmodule.c
+    - _hacl/Hacl_HMAC.c
+    - _hacl/Hacl_Streaming_HMAC.c
+  includes:
+    - Modules/_hacl/
+    - Modules/_hacl/include/
+  links:
+    - :libHacl_Hash_Blake2.a
+    - :libHacl_Hash_SHA1.a
+    - :libHacl_Hash_SHA2.a
+    - :libHacl_Hash_SHA3.a
+    - :libHacl_Hash_MD5.a
+  defines:
+    - _BSD_SOURCE
+    - _DEFAULT_SOURCE
+
 _imp:
   config-c-only: true
 
@@ -362,6 +378,7 @@ _md5:
   sources-conditional:
     - source: _hacl/Hacl_Hash_MD5.c
       minimum-python-version: "3.12"
+      maximum-python-version: "3.13"
   defines-conditional:
     - define: _BSD_SOURCE
       minimum-python-version: "3.12"
@@ -438,6 +455,7 @@ _sha1:
   sources-conditional:
     - source: _hacl/Hacl_Hash_SHA1.c
       minimum-python-version: "3.12"
+      maximum-python-version: "3.13"
   includes:
     - Modules/_hacl/include
   defines-conditional:
@@ -457,7 +475,9 @@ _sha2:
   minimum-python-version: "3.12"
   sources:
     - sha2module.c
-    - _hacl/Hacl_Hash_SHA2.c
+  sources-conditional:
+    - source: _hacl/Hacl_Hash_SHA2.c
+      maximum-python-version: "3.13"
   includes:
     - Modules/_hacl/include
   defines:
@@ -471,9 +491,9 @@ _sha3:
       maximum-python-version: "3.11"
     - source: sha3module.c
       minimum-python-version: "3.12"
-
     - source: _hacl/Hacl_Hash_SHA3.c
       minimum-python-version: "3.12"
+      maximum-python-version: "3.13"
   includes:
     - Modules/_hacl/include
   defines-conditional:
@@ -700,6 +720,12 @@ _tracemalloc:
   required-targets:
     - .*
 
+_types:
+  minimum-python-version: "3.14"
+  setup-enabled: true
+  sources:
+    - _typesmodule.c
+
 _typing:
   minimum-python-version: "3.11"
   setup-enabled-conditional:
diff --git a/cpython-windows/build.py b/cpython-windows/build.py
index 7e4d78ac..4da24476 100644
--- a/cpython-windows/build.py
+++ b/cpython-windows/build.py
@@ -346,6 +346,7 @@ def hack_props(
     pcbuild_path: pathlib.Path,
     arch: str,
     python_version: str,
+    zlib_entry: str,
 ):
     # TODO can we pass props into msbuild.exe?
 
@@ -355,7 +356,7 @@ def hack_props(
     bzip2_version = DOWNLOADS["bzip2"]["version"]
     sqlite_version = DOWNLOADS["sqlite"]["version"]
     xz_version = DOWNLOADS["xz"]["version"]
-    zlib_version = DOWNLOADS["zlib"]["version"]
+    zlib_version = DOWNLOADS[zlib_entry]["version"]
 
     mpdecimal_version = DOWNLOADS["mpdecimal"]["version"]
 
@@ -369,7 +370,8 @@ def hack_props(
     libffi_path = td / "libffi"
     tcltk_path = td / ("cpython-bin-deps-%s" % tcltk_commit)
     xz_path = td / ("xz-%s" % xz_version)
-    zlib_path = td / ("zlib-%s" % zlib_version)
+    zlib_prefix = "cpython-source-deps-" if zlib_entry == "zlib-ng" else ""
+    zlib_path = td / ("%s%s-%s" % (zlib_prefix, zlib_entry, zlib_version))
     mpdecimal_path = td / ("mpdecimal-%s" % mpdecimal_version)
 
     openssl_root = td / "openssl" / arch
@@ -410,6 +412,10 @@ def hack_props(
             elif b"<zlibDir" in line:
                 line = b"<zlibDir>%s\\</zlibDir>" % zlib_path
 
+            # On 3.14+, it's zlib-ng and the name changed
+            elif b"<zlibNgDir" in line:
+                line = b"<zlibNgDir>%s\\</zlibNgDir>" % zlib_path
+
             elif b"<mpdecimalDir" in line:
                 line = b"<mpdecimalDir>%s\\</mpdecimalDir>" % mpdecimal_path
 
@@ -484,6 +490,7 @@ def hack_project_files(
     cpython_source_path: pathlib.Path,
     build_directory: str,
     python_version: str,
+    zlib_entry: str,
 ):
     """Hacks Visual Studio project files to work with our build."""
 
@@ -494,6 +501,7 @@ def hack_project_files(
         pcbuild_path,
         build_directory,
         python_version,
+        zlib_entry,
     )
 
     # Our SQLite directory is named weirdly. This throws off version detection
@@ -913,6 +921,7 @@ def collect_python_build_artifacts(
     arch: str,
     config: str,
     openssl_entry: str,
+    zlib_entry: str,
     freethreaded: bool,
 ):
     """Collect build artifacts from Python.
@@ -993,6 +1002,7 @@ def collect_python_build_artifacts(
     depends_projects |= {
         "liblzma",
         "sqlite3",
+        "zlib-ng",
     }
 
     known_projects = (
@@ -1142,6 +1152,9 @@ def find_additional_dependencies(project: pathlib.Path):
                 if name == "openssl":
                     name = openssl_entry
 
+                if name == "zlib":
+                    name = zlib_entry
+
                 # On 3.14+, we use the latest tcl/tk version
                 if ext == "_tkinter" and python_majmin == "314":
                     name = name.replace("-8612", "")
@@ -1213,16 +1226,19 @@ def build_cpython(
     # The python.props file keys off MSBUILD, so it needs to be set.
     os.environ["MSBUILD"] = str(msbuild)
 
-    bzip2_archive = download_entry("bzip2", BUILD)
-    sqlite_archive = download_entry("sqlite", BUILD)
-    xz_archive = download_entry("xz", BUILD)
-    zlib_archive = download_entry("zlib", BUILD)
-
     python_archive = download_entry(python_entry_name, BUILD)
     entry = DOWNLOADS[python_entry_name]
-
     python_version = entry["version"]
 
+    zlib_entry = (
+        "zlib-ng" if meets_python_minimum_version(python_version, "3.14") else "zlib"
+    )
+
+    bzip2_archive = download_entry("bzip2", BUILD)
+    sqlite_archive = download_entry("sqlite", BUILD)
+    xz_archive = download_entry("xz", BUILD)
+    zlib_archive = download_entry(zlib_entry, BUILD)
+
     setuptools_wheel = download_entry("setuptools", BUILD)
     pip_wheel = download_entry("pip", BUILD)
 
@@ -1328,6 +1344,7 @@ def build_cpython(
             cpython_source_path,
             build_directory,
             python_version=python_version,
+            zlib_entry=zlib_entry,
         )
 
         if pgo:
@@ -1528,6 +1545,7 @@ def build_cpython(
             build_directory,
             artifact_config,
             openssl_entry=openssl_entry,
+            zlib_entry=zlib_entry,
             freethreaded=freethreaded,
         )
 
diff --git a/pythonbuild/downloads.py b/pythonbuild/downloads.py
index 89f3ce08..8a5bb89f 100644
--- a/pythonbuild/downloads.py
+++ b/pythonbuild/downloads.py
@@ -82,10 +82,10 @@
         "python_tag": "cp313",
     },
     "cpython-3.14": {
-        "url": "https://www.python.org/ftp/python/3.14.0/Python-3.14.0a6.tar.xz",
-        "size": 22956068,
-        "sha256": "8d6181e5331d9a2cd6ca405ae1230e88589a043f4768ebb443d3889d45c1c35c",
-        "version": "3.14.0a6",
+        "url": "https://www.python.org/ftp/python/3.14.0/Python-3.14.0a7.tar.xz",
+        "size": 23015952,
+        "sha256": "71adbcec3ac9edf93308e55cfb4184f2eb4b16fda2bb0a5a382929ed29c8386d",
+        "version": "3.14.0a7",
         "licenses": ["Python-2.0", "CNRI-Python"],
         "license_file": "LICENSE.cpython.txt",
         "python_tag": "cp314",
@@ -446,4 +446,13 @@
         "licenses": ["Zlib"],
         "license_file": "LICENSE.zlib.txt",
     },
+    "zlib-ng": {
+        "url": "https://github.com/python/cpython-source-deps/archive/refs/tags/zlib-ng-2.2.4.tar.gz",
+        "size": 2415819,
+        "sha256": "00bbd88709bc416cb96160ab61d3e1c8f76e106799af7328d0fe434dc7dd5004",
+        "version": "2.2.4",
+        "library_names": ["z"],
+        "licenses": ["Zlib"],
+        "license_file": "LICENSE.zlib-ng.txt",
+    },
 }
diff --git a/src/validation.rs b/src/validation.rs
index 747cdaed..55139df7 100644
--- a/src/validation.rs
+++ b/src/validation.rs
@@ -763,6 +763,8 @@ const GLOBAL_EXTENSIONS_PYTHON_3_14: &[&str] = &[
     "_tokenize",
     "_typing",
     "_zoneinfo",
+    "_hmac",
+    "_types",
 ];
 
 const GLOBAL_EXTENSIONS_MACOS: &[&str] = &["_scproxy"];
@@ -1596,7 +1598,7 @@ fn validate_extension_modules(
         ]);
     }
 
-    if is_windows && matches!(python_major_minor, "3.13") {
+    if is_windows && matches!(python_major_minor, "3.13" | "3.14") {
         wanted.extend(["_suggestions"]);
     }
 

From ff2c84ed74b557bb37c9cbd4a1c85fba21f94c09 Mon Sep 17 00:00:00 2001
From: Gregory Szorc <gregory.szorc@gmail.com>
Date: Fri, 16 May 2025 20:38:09 -0700
Subject: [PATCH 079/157] Update LLVM toolchains to 21.0.4 (#606)

Let's stay modern.
---
 pythonbuild/downloads.py | 24 ++++++++++++------------
 src/release.rs           |  6 +++---
 2 files changed, 15 insertions(+), 15 deletions(-)

diff --git a/pythonbuild/downloads.py b/pythonbuild/downloads.py
index 8a5bb89f..2e26586f 100644
--- a/pythonbuild/downloads.py
+++ b/pythonbuild/downloads.py
@@ -187,24 +187,24 @@
     },
     # Remember to update LLVM_URL in src/release.rs whenever upgrading.
     "llvm-20-x86_64-linux": {
-        "url": "https://github.com/indygreg/toolchain-tools/releases/download/toolchain-bootstrap%2F20250308/llvm-20.1.0+20250308-gnu_only-x86_64-unknown-linux-gnu.tar.zst",
-        "size": 283261860,
-        "sha256": "41d3d74e21e064e2e59a4e89feca74d58a5e9e95f73877f3c9ed82ca95607b47",
-        "version": "20.1.0+20240308",
+        "url": "https://github.com/indygreg/toolchain-tools/releases/download/toolchain-bootstrap%2F20250511/llvm-20.1.4+20250511-gnu_only-x86_64-unknown-linux-gnu.tar.zst",
+        "size": 299883811,
+        "sha256": "32374eb8b32fc79e9022f21eefc848d75fa3c46e68054a5dfc1f68d6f2f20429",
+        "version": "20.1.4+20250511",
     },
     # Remember to update LLVM_URL in src/release.rs whenever upgrading.
     "llvm-aarch64-macos": {
-        "url": "https://github.com/indygreg/toolchain-tools/releases/download/toolchain-bootstrap%2F20250308/llvm-20.1.0+20250308-aarch64-apple-darwin.tar.zst",
-        "size": 161006322,
-        "sha256": "9897bfaab16c930258f614250a1ade1a8f32df027181bd54a61d24b5a04e284c",
-        "version": "20.1.0+20240308",
+        "url": "https://github.com/indygreg/toolchain-tools/releases/download/toolchain-bootstrap%2F20250511/llvm-20.1.4+20250511-aarch64-apple-darwin.tar.zst",
+        "size": 152858186,
+        "sha256": "d44bf8256b2468339c3b4491edb9c799ab89e466d98d098391286dc86e86a63b",
+        "version": "20.1.4+20250511",
     },
     # Remember to update LLVM_URL in src/release.rs whenever upgrading.
     "llvm-x86_64-macos": {
-        "url": "https://github.com/indygreg/toolchain-tools/releases/download/toolchain-bootstrap%2F20250308/llvm-20.1.0+20250308-x86_64-apple-darwin.tar.zst",
-        "size": 160133882,
-        "sha256": "95cfcb79d752e81735a7a7f7c4cb5a7c16360b6e9a75658a1bd50ce0547d4ad5",
-        "version": "20.1.0+20240308",
+        "url": "https://github.com/indygreg/toolchain-tools/releases/download/toolchain-bootstrap%2F20250511/llvm-20.1.4+20250511-x86_64-apple-darwin.tar.zst",
+        "size": 160140682,
+        "sha256": "31b35734b678ad22471e31cf6a173c54819a3bca9ffefd4a70d8cdb935d67501",
+        "version": "20.1.4+20250511",
     },
     "m4": {
         "url": "https://ftp.gnu.org/gnu/m4/m4-1.4.19.tar.xz",
diff --git a/src/release.rs b/src/release.rs
index 9d6ec083..b731a241 100644
--- a/src/release.rs
+++ b/src/release.rs
@@ -569,14 +569,14 @@ pub fn produce_install_only_stripped(tar_gz_path: &Path, llvm_dir: &Path) -> Res
 static LLVM_URL: Lazy<Url> = Lazy::new(|| {
     if cfg!(target_os = "macos") {
         if std::env::consts::ARCH == "aarch64" {
-            Url::parse("https://github.com/indygreg/toolchain-tools/releases/download/toolchain-bootstrap%2F20250308/llvm-20.1.0+20250308-aarch64-apple-darwin.tar.zst").unwrap()
+            Url::parse("https://github.com/indygreg/toolchain-tools/releases/download/toolchain-bootstrap%2F20250511/llvm-20.1.4+20250511-aarch64-apple-darwin.tar.zst").unwrap()
         } else if std::env::consts::ARCH == "x86_64" {
-            Url::parse("https://github.com/indygreg/toolchain-tools/releases/download/toolchain-bootstrap%2F20250308/llvm-20.1.0+20250308-x86_64-apple-darwin.tar.zst").unwrap()
+            Url::parse("https://github.com/indygreg/toolchain-tools/releases/download/toolchain-bootstrap%2F20250511/llvm-20.1.4+20250511-x86_64-apple-darwin.tar.zst").unwrap()
         } else {
             panic!("unsupported macOS architecture");
         }
     } else if cfg!(target_os = "linux") {
-        Url::parse("https://github.com/indygreg/toolchain-tools/releases/download/toolchain-bootstrap%2F20250308/llvm-20.1.0+20250308-gnu_only-x86_64-unknown-linux-gnu.tar.zst").unwrap()
+        Url::parse("https://github.com/indygreg/toolchain-tools/releases/download/toolchain-bootstrap%2F20250511/llvm-20.1.4+20250511-gnu_only-x86_64-unknown-linux-gnu.tar.zst").unwrap()
     } else {
         panic!("unsupported platform");
     }

From fd80b9a76de53a9294995e6bf3a5912842084fcc Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Fri, 16 May 2025 22:39:42 -0500
Subject: [PATCH 080/157] Bump tokio from 1.43.0 to 1.43.1 (#578)

Bumps [tokio](https://github.com/tokio-rs/tokio) from 1.43.0 to 1.43.1.
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/tokio-rs/tokio/commit/a7b658c35bd40f6811e557aeb97cbb361b612c56"><code>a7b658c</code></a>
chore: prepare Tokio v1.43.1 release</li>
<li><a
href="https://github.com/tokio-rs/tokio/commit/c1c8d1033d637d7027fdc137ec8008c5801cbc0d"><code>c1c8d10</code></a>
Merge remote-tracking branch 'origin/tokio-1.38.x' into
forward-port-1.38.x</li>
<li><a
href="https://github.com/tokio-rs/tokio/commit/aa303bc2051f7c21b48bb7bfcafe8fd4f39afd21"><code>aa303bc</code></a>
chore: prepare Tokio v1.38.2 release</li>
<li><a
href="https://github.com/tokio-rs/tokio/commit/7b6ccb515ff067151ed62db835f735e5653f8784"><code>7b6ccb5</code></a>
chore: backport CI fixes</li>
<li><a
href="https://github.com/tokio-rs/tokio/commit/4b174ce2c95fe1d1a217917db93fcc935e17e0da"><code>4b174ce</code></a>
sync: fix cloning value when receiving from broadcast channel</li>
<li>See full diff in <a
href="https://github.com/tokio-rs/tokio/compare/tokio-1.43.0...tokio-1.43.1">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=tokio&package-manager=cargo&previous-version=1.43.0&new-version=1.43.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/astral-sh/python-build-standalone/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
 Cargo.lock | 4 ++--
 Cargo.toml | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index e6a3dd8a..418e84a0 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2417,9 +2417,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
 
 [[package]]
 name = "tokio"
-version = "1.43.0"
+version = "1.43.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3d61fa4ffa3de412bfea335c6ecff681de2b609ba3c77ef3e00e521813a9ed9e"
+checksum = "492a604e2fd7f814268a378409e6c92b5525d747d10db9a229723f55a417958c"
 dependencies = [
  "backtrace",
  "bytes",
diff --git a/Cargo.toml b/Cargo.toml
index e3826630..82f02982 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -36,7 +36,7 @@ sha2 = "0.10.8"
 tar = "0.4.40"
 tempfile = "3.10.0"
 text-stub-library = "0.9.0"
-tokio = "1.36.0"
+tokio = "1.43.1"
 url = "2.5.0"
 version-compare = "0.1.1"
 zip = "0.6.6"

From d0325a815823c5340c474010d62c54f86e8cd6e4 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Fri, 16 May 2025 22:39:58 -0500
Subject: [PATCH 081/157] Bump jinja2 from 3.1.3 to 3.1.6 (#584)

Bumps [jinja2](https://github.com/pallets/jinja) from 3.1.3 to 3.1.6.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/pallets/jinja/releases">jinja2's
releases</a>.</em></p>
<blockquote>
<h2>3.1.6</h2>
<p>This is the Jinja 3.1.6 security release, which fixes security issues
but does not otherwise change behavior and should not result in breaking
changes compared to the latest feature release.</p>
<p>PyPI: <a
href="https://pypi.org/project/Jinja2/3.1.6/">https://pypi.org/project/Jinja2/3.1.6/</a>
Changes: <a
href="https://jinja.palletsprojects.com/en/stable/changes/#version-3-1-6">https://jinja.palletsprojects.com/en/stable/changes/#version-3-1-6</a></p>
<ul>
<li>The <code>|attr</code> filter does not bypass the environment's
attribute lookup, allowing the sandbox to apply its checks. <a
href="https://github.com/pallets/jinja/security/advisories/GHSA-cpwx-vrp4-4pq7">https://github.com/pallets/jinja/security/advisories/GHSA-cpwx-vrp4-4pq7</a></li>
</ul>
<h2>3.1.5</h2>
<p>This is the Jinja 3.1.5 security fix release, which fixes security
issues and bugs but does not otherwise change behavior and should not
result in breaking changes compared to the latest feature release.</p>
<p>PyPI: <a
href="https://pypi.org/project/Jinja2/3.1.5/">https://pypi.org/project/Jinja2/3.1.5/</a>
Changes: <a
href="https://jinja.palletsprojects.com/changes/#version-3-1-5">https://jinja.palletsprojects.com/changes/#version-3-1-5</a>
Milestone: <a
href="https://github.com/pallets/jinja/milestone/16?closed=1">https://github.com/pallets/jinja/milestone/16?closed=1</a></p>
<ul>
<li>The sandboxed environment handles indirect calls to
<code>str.format</code>, such as by passing a stored reference to a
filter that calls its argument. <a
href="https://github.com/pallets/jinja/security/advisories/GHSA-q2x7-8rv6-6q7h">GHSA-q2x7-8rv6-6q7h</a></li>
<li>Escape template name before formatting it into error messages, to
avoid issues with names that contain f-string syntax. <a
href="https://redirect.github.com/pallets/jinja/issues/1792">#1792</a>,
<a
href="https://github.com/pallets/jinja/security/advisories/GHSA-gmj6-6f8f-6699">GHSA-gmj6-6f8f-6699</a></li>
<li>Sandbox does not allow <code>clear</code> and <code>pop</code> on
known mutable sequence types. <a
href="https://redirect.github.com/pallets/jinja/issues/2032">#2032</a></li>
<li>Calling sync <code>render</code> for an async template uses
<code>asyncio.run</code>. <a
href="https://redirect.github.com/pallets/jinja/issues/1952">#1952</a></li>
<li>Avoid unclosed <code>auto_aiter</code> warnings. <a
href="https://redirect.github.com/pallets/jinja/issues/1960">#1960</a></li>
<li>Return an <code>aclose</code>-able <code>AsyncGenerator</code> from
<code>Template.generate_async</code>. <a
href="https://redirect.github.com/pallets/jinja/issues/1960">#1960</a></li>
<li>Avoid leaving <code>root_render_func()</code> unclosed in
<code>Template.generate_async</code>. <a
href="https://redirect.github.com/pallets/jinja/issues/1960">#1960</a></li>
<li>Avoid leaving async generators unclosed in blocks, includes and
extends. <a
href="https://redirect.github.com/pallets/jinja/issues/1960">#1960</a></li>
<li>The runtime uses the correct <code>concat</code> function for the
current environment when calling block references. <a
href="https://redirect.github.com/pallets/jinja/issues/1701">#1701</a></li>
<li>Make <code>|unique</code> async-aware, allowing it to be used after
another async-aware filter. <a
href="https://redirect.github.com/pallets/jinja/issues/1781">#1781</a></li>
<li><code>|int</code> filter handles <code>OverflowError</code> from
scientific notation. <a
href="https://redirect.github.com/pallets/jinja/issues/1921">#1921</a></li>
<li>Make compiling deterministic for tuple unpacking in a <code>{% set
... %}</code> call. <a
href="https://redirect.github.com/pallets/jinja/issues/2021">#2021</a></li>
<li>Fix dunder protocol (<code>copy</code>/<code>pickle</code>/etc)
interaction with <code>Undefined</code> objects. <a
href="https://redirect.github.com/pallets/jinja/issues/2025">#2025</a></li>
<li>Fix <code>copy</code>/<code>pickle</code> support for the internal
<code>missing</code> object. <a
href="https://redirect.github.com/pallets/jinja/issues/2027">#2027</a></li>
<li><code>Environment.overlay(enable_async)</code> is applied correctly.
<a
href="https://redirect.github.com/pallets/jinja/issues/2061">#2061</a></li>
<li>The error message from <code>FileSystemLoader</code> includes the
paths that were searched. <a
href="https://redirect.github.com/pallets/jinja/issues/1661">#1661</a></li>
<li><code>PackageLoader</code> shows a clearer error message when the
package does not contain the templates directory. <a
href="https://redirect.github.com/pallets/jinja/issues/1705">#1705</a></li>
<li>Improve annotations for methods returning copies. <a
href="https://redirect.github.com/pallets/jinja/issues/1880">#1880</a></li>
<li><code>urlize</code> does not add <code>mailto:</code> to values like
<code>@a@b</code>. <a
href="https://redirect.github.com/pallets/jinja/issues/1870">#1870</a></li>
<li>Tests decorated with <code>@pass_context</code> can be used with the
<code>|select</code> filter. <a
href="https://redirect.github.com/pallets/jinja/issues/1624">#1624</a></li>
<li>Using <code>set</code> for multiple assignment (<code>a, b = 1,
2</code>) does not fail when the target is a namespace attribute. <a
href="https://redirect.github.com/pallets/jinja/issues/1413">#1413</a></li>
<li>Using <code>set</code> in all branches of <code>{% if %}{% elif %}{%
else %}</code> blocks does not cause the variable to be considered
initially undefined. <a
href="https://redirect.github.com/pallets/jinja/issues/1253">#1253</a></li>
</ul>
<h2>3.1.4</h2>
<p>This is the Jinja 3.1.4 security release, which fixes security issues
and bugs but does not otherwise change behavior and should not result in
breaking changes.</p>
<p>PyPI: <a
href="https://pypi.org/project/Jinja2/3.1.4/">https://pypi.org/project/Jinja2/3.1.4/</a>
Changes: <a
href="https://jinja.palletsprojects.com/en/3.1.x/changes/#version-3-1-4">https://jinja.palletsprojects.com/en/3.1.x/changes/#version-3-1-4</a></p>
<ul>
<li>The <code>xmlattr</code> filter does not allow keys with
<code>/</code> solidus, <code>&gt;</code> greater-than sign, or
<code>=</code> equals sign, in addition to disallowing spaces.
Regardless of any validation done by Jinja, user input should never be
used as keys to this filter, or must be separately validated first.
GHSA-h75v-3vvj-5mfj</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/pallets/jinja/blob/main/CHANGES.rst">jinja2's
changelog</a>.</em></p>
<blockquote>
<h2>Version 3.1.6</h2>
<p>Released 2025-03-05</p>
<ul>
<li>The <code>|attr</code> filter does not bypass the environment's
attribute lookup,
allowing the sandbox to apply its checks.
:ghsa:<code>cpwx-vrp4-4pq7</code></li>
</ul>
<h2>Version 3.1.5</h2>
<p>Released 2024-12-21</p>
<ul>
<li>The sandboxed environment handles indirect calls to
<code>str.format</code>, such as
by passing a stored reference to a filter that calls its argument.
:ghsa:<code>q2x7-8rv6-6q7h</code></li>
<li>Escape template name before formatting it into error messages, to
avoid
issues with names that contain f-string syntax.
:issue:<code>1792</code>, :ghsa:<code>gmj6-6f8f-6699</code></li>
<li>Sandbox does not allow <code>clear</code> and <code>pop</code> on
known mutable sequence
types. :issue:<code>2032</code></li>
<li>Calling sync <code>render</code> for an async template uses
<code>asyncio.run</code>.
:pr:<code>1952</code></li>
<li>Avoid unclosed <code>auto_aiter</code> warnings.
:pr:<code>1960</code></li>
<li>Return an <code>aclose</code>-able <code>AsyncGenerator</code> from
<code>Template.generate_async</code>. :pr:<code>1960</code></li>
<li>Avoid leaving <code>root_render_func()</code> unclosed in
<code>Template.generate_async</code>. :pr:<code>1960</code></li>
<li>Avoid leaving async generators unclosed in blocks, includes and
extends.
:pr:<code>1960</code></li>
<li>The runtime uses the correct <code>concat</code> function for the
current environment
when calling block references. :issue:<code>1701</code></li>
<li>Make <code>|unique</code> async-aware, allowing it to be used after
another
async-aware filter. :issue:<code>1781</code></li>
<li><code>|int</code> filter handles <code>OverflowError</code> from
scientific notation.
:issue:<code>1921</code></li>
<li>Make compiling deterministic for tuple unpacking in a <code>{% set
... %}</code>
call. :issue:<code>2021</code></li>
<li>Fix dunder protocol (<code>copy</code>/<code>pickle</code>/etc)
interaction with <code>Undefined</code>
objects. :issue:<code>2025</code></li>
<li>Fix <code>copy</code>/<code>pickle</code> support for the internal
<code>missing</code> object.
:issue:<code>2027</code></li>
<li><code>Environment.overlay(enable_async)</code> is applied correctly.
:pr:<code>2061</code></li>
<li>The error message from <code>FileSystemLoader</code> includes the
paths that were
searched. :issue:<code>1661</code></li>
<li><code>PackageLoader</code> shows a clearer error message when the
package does not
contain the templates directory. :issue:<code>1705</code></li>
<li>Improve annotations for methods returning copies.
:pr:<code>1880</code></li>
<li><code>urlize</code> does not add <code>mailto:</code> to values like
<code>@a@b</code>. :pr:<code>1870</code></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/pallets/jinja/commit/15206881c006c79667fe5154fe80c01c65410679"><code>1520688</code></a>
release version 3.1.6</li>
<li><a
href="https://github.com/pallets/jinja/commit/90457bbf33b8662926ae65cdde4c4c32e756e403"><code>90457bb</code></a>
Merge commit from fork</li>
<li><a
href="https://github.com/pallets/jinja/commit/065334d1ee5b7210e1a0a93c37238c86858f2af7"><code>065334d</code></a>
attr filter uses env.getattr</li>
<li><a
href="https://github.com/pallets/jinja/commit/033c20015c7ca899ab52eb921bb0f08e6d3dd145"><code>033c200</code></a>
start version 3.1.6</li>
<li><a
href="https://github.com/pallets/jinja/commit/bc68d4efa99c5f77334f0e519628558059ae8c35"><code>bc68d4e</code></a>
use global contributing guide (<a
href="https://redirect.github.com/pallets/jinja/issues/2070">#2070</a>)</li>
<li><a
href="https://github.com/pallets/jinja/commit/247de5e0c5062a792eb378e50e13e692885ee486"><code>247de5e</code></a>
use global contributing guide</li>
<li><a
href="https://github.com/pallets/jinja/commit/ab8218c7a1b66b62e0ad6b941bd514e3a64a358f"><code>ab8218c</code></a>
use project advisory link instead of global</li>
<li><a
href="https://github.com/pallets/jinja/commit/b4ffc8ff299dfd360064bea4cd2f862364601ad2"><code>b4ffc8f</code></a>
release version 3.1.5 (<a
href="https://redirect.github.com/pallets/jinja/issues/2066">#2066</a>)</li>
<li><a
href="https://github.com/pallets/jinja/commit/877f6e51be8e1765b06d911cfaa9033775f051d1"><code>877f6e5</code></a>
release version 3.1.5</li>
<li><a
href="https://github.com/pallets/jinja/commit/8d588592653b052f957b720e1fc93196e06f207f"><code>8d58859</code></a>
remove test pypi</li>
<li>Additional commits viewable in <a
href="https://github.com/pallets/jinja/compare/3.1.3...3.1.6">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=jinja2&package-manager=pip&previous-version=3.1.3&new-version=3.1.6)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/astral-sh/python-build-standalone/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
 requirements.win.txt | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/requirements.win.txt b/requirements.win.txt
index aa1a25c6..4890be56 100644
--- a/requirements.win.txt
+++ b/requirements.win.txt
@@ -110,9 +110,9 @@ idna==3.6 \
     --hash=sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca \
     --hash=sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f
     # via requests
-jinja2==3.1.3 \
-    --hash=sha256:7d6d50dd97d52cbc355597bd845fabfbac3f551e1f99619e39a35ce8c370b5fa \
-    --hash=sha256:ac8bd6544d4bb2c9792bf3a159e80bba8fda7f07e81bc3aed565432d5925ba90
+jinja2==3.1.6 \
+    --hash=sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d \
+    --hash=sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67
     # via -r requirements.in
 jsonschema==4.21.1 \
     --hash=sha256:7996507afae316306f9e2290407761157c6f78002dcf7419acb99822143d1c6f \

From cae484dd5e5a5b2b9b88abadaf4c9f09facfce49 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Fri, 16 May 2025 22:40:18 -0500
Subject: [PATCH 082/157] Bump ring from 0.17.8 to 0.17.14 (#605)

Bumps [ring](https://github.com/briansmith/ring) from 0.17.8 to 0.17.14.
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/briansmith/ring/blob/main/RELEASES.md">ring's
changelog</a>.</em></p>
<blockquote>
<h1>Version 0.17.14 (2025-03-11)</h1>
<p>Fixed a performance bug in the AVX2-based AES-GCM implementation
added in
<em>ring</em> 0.17.13. This will be another notable performance
improvement for most
newish x86-64 systems. The performance issue impacted not just
AES-GCM.</p>
<p>Compatibility with GNU binutils 2.29 (used on Amazon Linux 2), and
probably
even earlier versions, was restored. It is expected that <em>ring</em>
0.17.14 will
build on all the systems that 0.17.12 would build on.</p>
<h1>Version 0.17.13 (2025-03-06)</h1>
<p>Increased MSRV to 1.66.0 to avoid bugs in earlier versions so that we
can
safely use <code>core::arch::x86_64::__cpuid</code> and
<code>core::arch::x86::__cpuid</code> from
Rust in future releases.</p>
<p>AVX2-based VAES-CLMUL implementation. This will be a notable
performance
improvement for most newish x86-64 systems. This will likely raise the
minimum
binutils version supported for very old Linux distros.</p>
<h1>Version 0.17.12 (2025-03-05)</h1>
<p>Bug fix: <a
href="https://redirect.github.com/briansmith/ring/pull/2447">briansmith/ring#2447</a>
for denial of service (DoS).</p>
<ul>
<li>
<p>Fixes a panic in
<code>ring::aead::quic::HeaderProtectionKey::new_mask()</code> when
integer overflow checking is enabled. In the QUIC protocol, an attacker
can
induce this panic by sending a specially-crafted packet. Even
unintentionally
it is likely to occur in 1 out of every 2**32 packets sent and/or
received.</p>
</li>
<li>
<p>Fixes a panic on 64-bit targets in <code>ring::aead::{AES_128_GCM,
AES_256_GCM}</code>
when overflow checking is enabled, when encrypting/decrypting
approximately
68,719,476,700 bytes (about 64 gigabytes) of data in a single chunk.
Protocols
like TLS and SSH are not affected by this because those protocols break
large
amounts of data into small chunks. Similarly, most applications will not
attempt to encrypt/decrypt 64GB of data in one chunk.</p>
</li>
</ul>
<p>Overflow checking is not enabled in release mode by default, but
<code>RUSTFLAGS=&quot;-C overflow-checks&quot;</code> or
<code>overflow-checks = true</code> in the Cargo.toml
profile can override this. Overflow checking is usually enabled by
default in
debug mode.</p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a
href="https://github.com/briansmith/ring/commits">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=ring&package-manager=cargo&previous-version=0.17.8&new-version=0.17.14)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/astral-sh/python-build-standalone/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
 Cargo.lock | 11 ++---------
 1 file changed, 2 insertions(+), 9 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 418e84a0..b0db1676 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1828,15 +1828,14 @@ dependencies = [
 
 [[package]]
 name = "ring"
-version = "0.17.8"
+version = "0.17.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d"
+checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7"
 dependencies = [
  "cc",
  "cfg-if",
  "getrandom 0.2.15",
  "libc",
- "spin",
  "untrusted",
  "windows-sys 0.52.0",
 ]
@@ -2201,12 +2200,6 @@ dependencies = [
  "windows-sys 0.52.0",
 ]
 
-[[package]]
-name = "spin"
-version = "0.9.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
-
 [[package]]
 name = "stable_deref_trait"
 version = "1.2.0"

From 45cca0981ec96516c24ab12fbb94da5b03f40c38 Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Sat, 17 May 2025 08:03:47 -0500
Subject: [PATCH 083/157] Fix zlib-ng project expectation for <3.14 (#614)

See failure at
https://github.com/astral-sh/python-build-standalone/actions/runs/15081267283/job/42398255249

Introduced by #580
---
 cpython-windows/build.py | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/cpython-windows/build.py b/cpython-windows/build.py
index 4da24476..e981a8ac 100644
--- a/cpython-windows/build.py
+++ b/cpython-windows/build.py
@@ -1002,9 +1002,11 @@ def collect_python_build_artifacts(
     depends_projects |= {
         "liblzma",
         "sqlite3",
-        "zlib-ng",
     }
 
+    if zlib_entry == "zlib-ng":
+        depends_projects |= {"zlib-ng"}
+
     known_projects = (
         ignore_projects | other_projects | depends_projects | extension_projects
     )

From ae06f31b0d8046e21d4aa2a98732822f87c84854 Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Sat, 17 May 2025 08:21:49 -0500
Subject: [PATCH 084/157] Include free-threaded Python in published musl
 distributions (#583)

---
 .github/workflows/release.yml |  1 -
 src/release.rs                | 25 +++++++++++++++++++++----
 2 files changed, 21 insertions(+), 5 deletions(-)

diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 7a06d07e..ce803392 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -21,7 +21,6 @@ env:
 permissions:
   contents: write
   packages: write
-  releases: wrte
   # Permissions used for actions/attest-build-provenance
   id-token: write
   attestations: write
diff --git a/src/release.rs b/src/release.rs
index b731a241..60e46c99 100644
--- a/src/release.rs
+++ b/src/release.rs
@@ -141,6 +141,11 @@ pub static RELEASE_TRIPLES: Lazy<BTreeMap<&'static str, TripleRelease>> = Lazy::
         "lto+static",
         "noopt+static",
     ];
+    let linux_suffixes_musl_freethreaded = vec![
+        "freethreaded+debug",
+        "freethreaded+lto",
+        "freethreaded+noopt",
+    ];
     let linux_suffixes_pgo_freethreaded = vec!["freethreaded+debug", "freethreaded+pgo+lto"];
     let linux_suffixes_nopgo_freethreaded = vec![
         "freethreaded+debug",
@@ -280,7 +285,10 @@ pub static RELEASE_TRIPLES: Lazy<BTreeMap<&'static str, TripleRelease>> = Lazy::
             suffixes: linux_suffixes_musl.clone(),
             install_only_suffix: "lto",
             python_version_requirement: None,
-            conditional_suffixes: vec![],
+            conditional_suffixes: vec![ConditionalSuffixes {
+                python_version_requirement: VersionSpecifier::from_str(">=3.13").unwrap(),
+                suffixes: linux_suffixes_musl_freethreaded.clone(),
+            }],
         },
     );
     h.insert(
@@ -289,7 +297,10 @@ pub static RELEASE_TRIPLES: Lazy<BTreeMap<&'static str, TripleRelease>> = Lazy::
             suffixes: linux_suffixes_musl.clone(),
             install_only_suffix: "lto",
             python_version_requirement: None,
-            conditional_suffixes: vec![],
+            conditional_suffixes: vec![ConditionalSuffixes {
+                python_version_requirement: VersionSpecifier::from_str(">=3.13").unwrap(),
+                suffixes: linux_suffixes_musl_freethreaded.clone(),
+            }],
         },
     );
     h.insert(
@@ -298,7 +309,10 @@ pub static RELEASE_TRIPLES: Lazy<BTreeMap<&'static str, TripleRelease>> = Lazy::
             suffixes: linux_suffixes_musl.clone(),
             install_only_suffix: "lto",
             python_version_requirement: None,
-            conditional_suffixes: vec![],
+            conditional_suffixes: vec![ConditionalSuffixes {
+                python_version_requirement: VersionSpecifier::from_str(">=3.13").unwrap(),
+                suffixes: linux_suffixes_musl_freethreaded.clone(),
+            }],
         },
     );
     h.insert(
@@ -307,7 +321,10 @@ pub static RELEASE_TRIPLES: Lazy<BTreeMap<&'static str, TripleRelease>> = Lazy::
             suffixes: linux_suffixes_musl.clone(),
             install_only_suffix: "lto",
             python_version_requirement: None,
-            conditional_suffixes: vec![],
+            conditional_suffixes: vec![ConditionalSuffixes {
+                python_version_requirement: VersionSpecifier::from_str(">=3.13").unwrap(),
+                suffixes: linux_suffixes_musl_freethreaded.clone(),
+            }],
         },
     );
 

From fec8f6ba351eda91d146498c65a6bc80c006e3d3 Mon Sep 17 00:00:00 2001
From: Gregory Szorc <gregory.szorc@gmail.com>
Date: Sun, 18 May 2025 16:31:37 -0700
Subject: [PATCH 085/157] Replace various *proto packages with xorgproto (#609)

As part of trying to stand up native Linux ARM builds, I ran into a
failure with xproto's config.guess not recognizing ARM. That package not
releasing since 2016 clued me in that it was likely not a required part
of X11 any more.

I looked at Debian's dependency tree and there was no xproto in sight.
But there was an xorgproto. And sure enough if you install xorgproto
instead of xproto in the build environment, things "just work."

Clued into the potential for outdated packages, I looked at other proto
packages. I pulled the thread and inputproto, kbproto, and xextproto all
appeared to be dead and replaced by xorgproto.

So this commit deletes inputproto, kbproto, xextproto, and xproto and
effectively replaces their use with xorgproto.

Good riddance.
---
 cpython-unix/Makefile            | 20 ++----------------
 cpython-unix/build-inputproto.sh | 24 ----------------------
 cpython-unix/build-kbproto.sh    | 24 ----------------------
 cpython-unix/build-xextproto.sh  | 35 --------------------------------
 cpython-unix/build-xproto.sh     | 35 --------------------------------
 cpython-unix/build.py            | 12 ++---------
 pythonbuild/downloads.py         | 24 ----------------------
 7 files changed, 4 insertions(+), 170 deletions(-)
 delete mode 100755 cpython-unix/build-inputproto.sh
 delete mode 100755 cpython-unix/build-kbproto.sh
 delete mode 100755 cpython-unix/build-xextproto.sh
 delete mode 100755 cpython-unix/build-xproto.sh

diff --git a/cpython-unix/Makefile b/cpython-unix/Makefile
index 0e859784..196b6bbf 100644
--- a/cpython-unix/Makefile
+++ b/cpython-unix/Makefile
@@ -117,12 +117,6 @@ $(OUTDIR)/bzip2-$(BZIP2_VERSION)-$(PACKAGE_SUFFIX).tar: $(PYTHON_DEP_DEPENDS) $(
 $(OUTDIR)/expat-$(EXPAT_VERSION)-$(PACKAGE_SUFFIX).tar: $(PYTHON_DEP_DEPENDS) $(HERE)/build-expat.sh
 	$(RUN_BUILD) --docker-image $(DOCKER_IMAGE_BUILD) expat
 
-$(OUTDIR)/inputproto-$(INPUTPROTO_VERSION)-$(PACKAGE_SUFFIX).tar: $(PYTHON_DEP_DEPENDS) $(HERE)/build-inputproto.sh
-	$(RUN_BUILD) --docker-image $(DOCKER_IMAGE_BUILD) inputproto
-
-$(OUTDIR)/kbproto-$(KBPROTO_VERSION)-$(PACKAGE_SUFFIX).tar: $(PYTHON_DEP_DEPENDS) $(HERE)/build-kbproto.sh
-	$(RUN_BUILD) --docker-image $(DOCKER_IMAGE_BUILD) kbproto
-
 $(OUTDIR)/libffi-3.3-$(LIBFFI_3.3_VERSION)-$(PACKAGE_SUFFIX).tar: $(PYTHON_DEP_DEPENDS) $(HERE)/build-libffi-3.3.sh
 	$(RUN_BUILD) --docker-image $(DOCKER_IMAGE_BUILD) libffi-3.3
 
@@ -135,10 +129,6 @@ $(OUTDIR)/libpthread-stubs-$(LIBPTHREAD_STUBS_VERSION)-$(PACKAGE_SUFFIX).tar: $(
 LIBX11_DEPENDS = \
     $(PYTHON_DEP_DEPENDS) \
     $(HERE)/build-libX11.sh \
-    $(OUTDIR)/xproto-$(XPROTO_VERSION)-$(PACKAGE_SUFFIX).tar \
-    $(OUTDIR)/xextproto-$(XEXTPROTO_VERSION)-$(PACKAGE_SUFFIX).tar \
-    $(OUTDIR)/kbproto-$(KBPROTO_VERSION)-$(PACKAGE_SUFFIX).tar \
-    $(OUTDIR)/inputproto-$(INPUTPROTO_VERSION)-$(PACKAGE_SUFFIX).tar \
     $(OUTDIR)/libxcb-$(LIBXCB_VERSION)-$(PACKAGE_SUFFIX).tar \
     $(OUTDIR)/xtrans-$(XTRANS_VERSION)-$(PACKAGE_SUFFIX).tar \
     $(OUTDIR)/xorgproto-$(XORGPROTO_VERSION)-$(PACKAGE_SUFFIX).tar \
@@ -151,7 +141,7 @@ LIBXAU_DEPENDS = \
     $(PYTHON_DEP_DEPENDS) \
     $(HERE)/build-libXau.sh \
     $(OUTDIR)/x11-util-macros-$(X11_UTIL_MACROS_VERSION)-$(PACKAGE_SUFFIX).tar \
-    $(OUTDIR)/xproto-$(XPROTO_VERSION)-$(PACKAGE_SUFFIX).tar \
+    $(OUTDIR)/xorgproto-$(XORGPROTO_VERSION)-$(PACKAGE_SUFFIX).tar \
     $(NULL)
 
 $(OUTDIR)/libXau-$(LIBXAU_VERSION)-$(PACKAGE_SUFFIX).tar: $(LIBXAU_DEPENDS)
@@ -163,7 +153,7 @@ LIBXCB_DEPENDS = \
     $(OUTDIR)/image-$(DOCKER_IMAGE_XCB).tar \
     $(OUTDIR)/xcb-proto-$(XCB_PROTO_VERSION)-$(PACKAGE_SUFFIX).tar \
     $(OUTDIR)/libXau-$(LIBXAU_VERSION)-$(PACKAGE_SUFFIX).tar \
-    $(OUTDIR)/xproto-$(XPROTO_VERSION)-$(PACKAGE_SUFFIX).tar \
+    $(OUTDIR)/xorgproto-$(XORGPROTO_VERSION)-$(PACKAGE_SUFFIX).tar \
     $(OUTDIR)/libpthread-stubs-$(LIBPTHREAD_STUBS_VERSION)-$(PACKAGE_SUFFIX).tar \
     $(NULL)
 
@@ -231,15 +221,9 @@ $(OUTDIR)/x11-util-macros-$(X11_UTIL_MACROS_VERSION)-$(PACKAGE_SUFFIX).tar: $(PY
 $(OUTDIR)/xcb-proto-$(XCB_PROTO_VERSION)-$(PACKAGE_SUFFIX).tar: $(PYTHON_DEP_DEPENDS) $(HERE)/build-xcb-proto.sh
 	$(RUN_BUILD) --docker-image $(DOCKER_IMAGE_XCB) xcb-proto
 
-$(OUTDIR)/xextproto-$(XEXTPROTO_VERSION)-$(PACKAGE_SUFFIX).tar: $(PYTHON_DEP_DEPENDS) $(HERE)/build-xextproto.sh
-	$(RUN_BUILD) --docker-image $(DOCKER_IMAGE_BUILD) xextproto
-
 $(OUTDIR)/xorgproto-$(XORGPROTO_VERSION)-$(PACKAGE_SUFFIX).tar: $(PYTHON_DEP_DEPENDS) $(HERE)/build-xorgproto.sh
 	$(RUN_BUILD) --docker-image $(DOCKER_IMAGE_BUILD) xorgproto
 
-$(OUTDIR)/xproto-$(XPROTO_VERSION)-$(PACKAGE_SUFFIX).tar: $(PYTHON_DEP_DEPENDS) $(HERE)/build-xproto.sh
-	$(RUN_BUILD) --docker-image $(DOCKER_IMAGE_BUILD) xproto
-
 $(OUTDIR)/xtrans-$(XTRANS_VERSION)-$(PACKAGE_SUFFIX).tar: $(PYTHON_DEP_DEPENDS) $(HERE)/build-xtrans.sh
 	$(RUN_BUILD) --docker-image $(DOCKER_IMAGE_BUILD) xtrans
 
diff --git a/cpython-unix/build-inputproto.sh b/cpython-unix/build-inputproto.sh
deleted file mode 100755
index 9ab52363..00000000
--- a/cpython-unix/build-inputproto.sh
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/usr/bin/env bash
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at https://mozilla.org/MPL/2.0/.
-
-set -ex
-
-ROOT=`pwd`
-
-pkg-config --version
-
-export PATH=/tools/${TOOLCHAIN}/bin:/tools/host/bin:$PATH
-export PKG_CONFIG_PATH=/tools/deps/share/pkgconfig
-
-tar -xf inputproto-${INPUTPROTO_VERSION}.tar.gz
-pushd inputproto-${INPUTPROTO_VERSION}
-
-CFLAGS="${EXTRA_TARGET_CFLAGS} -fPIC" CPPFLAGS="${EXTRA_TARGET_CFLAGS} -fPIC" LDFLAGS="${EXTRA_TARGET_LDFLAGS}" ./configure \
-    --build=${BUILD_TRIPLE} \
-    --host=${TARGET_TRIPLE} \
-    --prefix=/tools/deps
-
-make -j `nproc`
-make -j `nproc` install DESTDIR=${ROOT}/out
diff --git a/cpython-unix/build-kbproto.sh b/cpython-unix/build-kbproto.sh
deleted file mode 100755
index 031493e8..00000000
--- a/cpython-unix/build-kbproto.sh
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/usr/bin/env bash
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at https://mozilla.org/MPL/2.0/.
-
-set -ex
-
-ROOT=`pwd`
-
-pkg-config --version
-
-export PATH=/tools/${TOOLCHAIN}/bin:/tools/host/bin:$PATH
-export PKG_CONFIG_PATH=/tools/deps/share/pkgconfig
-
-tar -xf kbproto-${KBPROTO_VERSION}.tar.gz
-pushd kbproto-${KBPROTO_VERSION}
-
-CFLAGS="${EXTRA_TARGET_CFLAGS} -fPIC" CPPFLAGS="${EXTRA_TARGET_CFLAGS} -fPIC" LDFLAGS="${EXTRA_TARGET_LDFLAGS}" ./configure \
-    --build=${BUILD_TRIPLE} \
-    --host=${TARGET_TRIPLE} \
-    --prefix=/tools/deps
-
-make -j `nproc`
-make -j `nproc` install DESTDIR=${ROOT}/out
diff --git a/cpython-unix/build-xextproto.sh b/cpython-unix/build-xextproto.sh
deleted file mode 100755
index 090e3f0e..00000000
--- a/cpython-unix/build-xextproto.sh
+++ /dev/null
@@ -1,35 +0,0 @@
-#!/usr/bin/env bash
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at https://mozilla.org/MPL/2.0/.
-
-set -ex
-
-ROOT=`pwd`
-
-pkg-config --version
-
-export PATH=/tools/${TOOLCHAIN}/bin:/tools/host/bin:$PATH
-export PKG_CONFIG_PATH=/tools/deps/share/pkgconfig
-
-tar -xf xextproto-${XEXTPROTO_VERSION}.tar.gz
-pushd xextproto-${XEXTPROTO_VERSION}
-
-EXTRA_CONFIGURE_FLAGS=
-if [ -n "${CROSS_COMPILING}" ]; then
-    if echo "${TARGET_TRIPLE}" | grep -q -- "-unknown-linux-musl"; then
-    # xextproto does not support configuration of musl targets so we pretend the target matches the
-    # build triple and enable cross-compilation manually
-    TARGET_TRIPLE="$(echo "${TARGET_TRIPLE}" | sed -e 's/-unknown-linux-musl/-unknown-linux-gnu/g')"
-    EXTRA_CONFIGURE_FLAGS="cross_compiling=yes"
-    fi
-fi
-
-CFLAGS="${EXTRA_TARGET_CFLAGS} -fPIC" CPPFLAGS="${EXTRA_TARGET_CFLAGS} -fPIC" LDFLAGS="${EXTRA_TARGET_LDFLAGS}" ./configure \
-    --build=${BUILD_TRIPLE} \
-    --host=${TARGET_TRIPLE} \
-    --prefix=/tools/deps \
-    ${EXTRA_CONFIGURE_FLAGS}
-
-make -j `nproc`
-make -j `nproc` install DESTDIR=${ROOT}/out
diff --git a/cpython-unix/build-xproto.sh b/cpython-unix/build-xproto.sh
deleted file mode 100755
index 6f3d2b6b..00000000
--- a/cpython-unix/build-xproto.sh
+++ /dev/null
@@ -1,35 +0,0 @@
-#!/usr/bin/env bash
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at https://mozilla.org/MPL/2.0/.
-
-set -ex
-
-ROOT=`pwd`
-
-pkg-config --version
-
-export PATH=${TOOLS_PATH}/${TOOLCHAIN}/bin:${TOOLS_PATH}/host/bin:$PATH
-export PKG_CONFIG_PATH=${TOOLS_PATH}/deps/share/pkgconfig
-
-tar -xf xproto-${XPROTO_VERSION}.tar.gz
-pushd xproto-${XPROTO_VERSION}
-
-EXTRA_CONFIGURE_FLAGS=
-if [ -n "${CROSS_COMPILING}" ]; then
-    if echo "${TARGET_TRIPLE}" | grep -q -- "-unknown-linux-musl"; then
-    # xproto does not support configuration of musl targets so we pretend the target matches the
-    # build triple and enable cross-compilation manually
-    TARGET_TRIPLE="$(echo "${TARGET_TRIPLE}" | sed -e 's/-unknown-linux-musl/-unknown-linux-gnu/g')"
-    EXTRA_CONFIGURE_FLAGS="cross_compiling=yes"
-    fi
-fi
-
-CFLAGS="${EXTRA_TARGET_CFLAGS} -fPIC" CPPFLAGS="${EXTRA_TARGET_CFLAGS} -fPIC" LDFLAGS="${EXTRA_TARGET_LDFLAGS}" ./configure \
-    --build=${BUILD_TRIPLE} \
-    --host=${TARGET_TRIPLE} \
-    --prefix=/tools/deps \
-    ${EXTRA_CONFIGURE_FLAGS}
-
-make -j ${NUM_CPUS}
-make -j ${NUM_CPUS} install DESTDIR=${ROOT}/out
diff --git a/cpython-unix/build.py b/cpython-unix/build.py
index c17c84cd..f058e93a 100755
--- a/cpython-unix/build.py
+++ b/cpython-unix/build.py
@@ -1135,8 +1135,6 @@ def main():
             "bdb",
             "bzip2",
             "expat",
-            "inputproto",
-            "kbproto",
             "libffi-3.3",
             "libffi",
             "libpthread-stubs",
@@ -1150,9 +1148,7 @@ def main():
             "tcl",
             "uuid",
             "x11-util-macros",
-            "xextproto",
             "xorgproto",
-            "xproto",
             "xtrans",
             "xz",
             "zlib",
@@ -1182,15 +1178,11 @@ def main():
                 build_options=build_options,
                 dest_archive=dest_archive,
                 extra_archives={
-                    "inputproto",
-                    "kbproto",
                     "libpthread-stubs",
                     "libXau",
                     "libxcb",
                     "x11-util-macros",
-                    "xextproto",
                     "xorgproto",
-                    "xproto",
                     "xtrans",
                 },
             )
@@ -1205,7 +1197,7 @@ def main():
                 target_triple=target_triple,
                 build_options=build_options,
                 dest_archive=dest_archive,
-                extra_archives={"x11-util-macros", "xproto"},
+                extra_archives={"x11-util-macros", "xorgproto"},
             )
 
         elif action == "xcb-proto":
@@ -1230,7 +1222,7 @@ def main():
                 target_triple=target_triple,
                 build_options=build_options,
                 dest_archive=dest_archive,
-                extra_archives={"libpthread-stubs", "libXau", "xcb-proto", "xproto"},
+                extra_archives={"libpthread-stubs", "libXau", "xcb-proto", "xorgproto"},
             )
 
         elif action == "tix":
diff --git a/pythonbuild/downloads.py b/pythonbuild/downloads.py
index 2e26586f..c6fd2214 100644
--- a/pythonbuild/downloads.py
+++ b/pythonbuild/downloads.py
@@ -99,24 +99,12 @@
         "licenses": ["MIT"],
         "license_file": "LICENSE.expat.txt",
     },
-    "inputproto": {
-        "url": "https://www.x.org/archive/individual/proto/inputproto-2.3.2.tar.gz",
-        "size": 244334,
-        "sha256": "10eaadd531f38f7c92ab59ef0708ca195caf3164a75c4ed99f0c04f2913f6ef3",
-        "version": "2.3.2",
-    },
     "jom-windows-bin": {
         "url": "http://download.qt.io/official_releases/jom/jom_1_1_4.zip",
         "size": 1696930,
         "sha256": "d533c1ef49214229681e90196ed2094691e8c4a0a0bef0b2c901debcb562682b",
         "version": "1.1.4",
     },
-    "kbproto": {
-        "url": "https://www.x.org/archive/individual/proto/kbproto-1.0.7.tar.gz",
-        "size": 325858,
-        "sha256": "828cb275b91268b1a3ea950d5c0c5eb076c678fdf005d517411f89cc8c3bb416",
-        "version": "1.0.7",
-    },
     "libedit": {
         "url": "https://thrysoee.dk/editline/libedit-20240808-3.1.tar.gz",
         "size": 538611,
@@ -397,12 +385,6 @@
         "sha256": "85cd21e9d9fbc341d0dbf11eace98d55d7db89fda724b0e598855fcddf0944fd",
         "version": "1.14.1",
     },
-    "xextproto": {
-        "url": "https://www.x.org/archive/individual/proto/xextproto-7.3.0.tar.gz",
-        "size": 290814,
-        "sha256": "1b1bcdf91221e78c6c33738667a57bd9aaa63d5953174ad8ed9929296741c9f5",
-        "version": "7.3.0",
-    },
     # Newer versions from at least 2023 have build failures for reasons we haven't
     # fully investigated.
     "xorgproto": {
@@ -411,12 +393,6 @@
         "sha256": "38ad1d8316515785d53c5162b4b7022918e03c11d72a5bd9df0a176607f42bca",
         "version": "2019.1",
     },
-    "xproto": {
-        "url": "https://www.x.org/archive/individual/proto/xproto-7.0.31.tar.gz",
-        "size": 367979,
-        "sha256": "6d755eaae27b45c5cc75529a12855fed5de5969b367ed05003944cf901ed43c7",
-        "version": "7.0.31",
-    },
     "xtrans": {
         "url": "https://www.x.org/archive/individual/lib/xtrans-1.5.0.tar.gz",
         "size": 230197,

From 1abd74dac86b2e674b768ce8c524e9f0275ea09c Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Mon, 19 May 2025 16:55:43 -0500
Subject: [PATCH 086/157] Allow enabling the JIT on aarch64 macOS (#544)

Follows #538
---
 cpython-unix/build-cpython.sh           | 15 ++++-
 cpython-unix/patch-jit-cflags-313.patch | 80 +++++++++++++++++++++++++
 cpython-unix/patch-jit-cflags-314.patch | 70 ++++++++++++++++++++++
 3 files changed, 162 insertions(+), 3 deletions(-)
 create mode 100644 cpython-unix/patch-jit-cflags-313.patch
 create mode 100644 cpython-unix/patch-jit-cflags-314.patch

diff --git a/cpython-unix/build-cpython.sh b/cpython-unix/build-cpython.sh
index 6505b629..39d810e3 100755
--- a/cpython-unix/build-cpython.sh
+++ b/cpython-unix/build-cpython.sh
@@ -455,12 +455,21 @@ if [ -n "${CPYTHON_OPTIMIZED}" ]; then
     # Allow users to enable the experimental JIT on 3.13+
     if [[ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_13}" ]]; then
 
-        # The JIT build is failing on macOS due to compiler errors
-        # Only enable on Linux / 3.13 until that's fixed upstream
-        if [[ "${PYBUILD_PLATFORM}" != "macos" ]]; then
+        # Do not enable on x86-64 macOS because the JIT requires macOS 11+ and we are currently
+        # using 10.15 as a miniumum version.
+        if [ "${TARGET_TRIPLE}" != "x86_64-apple-darwin" ]; then
             CONFIGURE_FLAGS="${CONFIGURE_FLAGS} --enable-experimental-jit=yes-off"
         fi
 
+        # Respect CFLAGS during JIT compilation.
+        # Backports https://github.com/python/cpython/pull/134276
+        if [ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_14}" ]; then
+            patch -p1 -i ${ROOT}/patch-jit-cflags-314.patch
+        elif [ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_13}" ]; then
+            patch -p1 -i ${ROOT}/patch-jit-cflags-313.patch
+        fi
+
+
         if [[ -n "${PYTHON_MEETS_MAXIMUM_VERSION_3_13}" ]]; then
             # On 3.13, LLVM 18 is hard-coded into the configure script. Override it to our toolchain
             # version.
diff --git a/cpython-unix/patch-jit-cflags-313.patch b/cpython-unix/patch-jit-cflags-313.patch
new file mode 100644
index 00000000..d82d1eed
--- /dev/null
+++ b/cpython-unix/patch-jit-cflags-313.patch
@@ -0,0 +1,80 @@
+diff --git a/Tools/jit/_targets.py b/Tools/jit/_targets.py
+index 50b5d923a35..4a71476026f 100644
+--- a/Tools/jit/_targets.py
++++ b/Tools/jit/_targets.py
+@@ -10,6 +10,7 @@
+ import sys
+ import tempfile
+ import typing
++import shlex
+ 
+ import _llvm
+ import _schema
+@@ -44,6 +45,17 @@ class _Target(typing.Generic[_S, _R]):
+     stable: bool = False
+     debug: bool = False
+     verbose: bool = False
++    cflags: str = ""
++    known_symbols: dict[str, int] = dataclasses.field(default_factory=dict)
++
++    def _get_nop(self) -> bytes:
++        if re.fullmatch(r"aarch64-.*", self.triple):
++            nop = b"\x1f\x20\x03\xD5"
++        elif re.fullmatch(r"x86_64-.*|i686.*", self.triple):
++            nop = b"\x90"
++        else:
++            raise ValueError(f"NOP not defined for {self.triple}")
++        return nop
+ 
+     def _compute_digest(self, out: pathlib.Path) -> str:
+         hasher = hashlib.sha256()
+@@ -114,6 +126,7 @@ async def _compile(
+             return _stencils.StencilGroup()
+         o = tempdir / f"{opname}.o"
+         args = [
++            *shlex.split(self.cflags),
+             f"--target={self.triple}",
+             "-DPy_BUILD_CORE_MODULE",
+             "-D_DEBUG" if self.debug else "-DNDEBUG",
+diff --git a/Tools/jit/build.py b/Tools/jit/build.py
+index 4a23c6f0afa..618b53804db 100644
+--- a/Tools/jit/build.py
++++ b/Tools/jit/build.py
+@@ -22,7 +22,11 @@
+     parser.add_argument(
+         "-v", "--verbose", action="store_true", help="echo commands as they are run"
+     )
++    parser.add_argument(
++        "--with-cflags", help="additional flags to pass to the compiler", default=""
++    )
+     args = parser.parse_args()
+     args.target.debug = args.debug
+     args.target.verbose = args.verbose
++    args.target.cflags = args.with_cflags
+     args.target.build(pathlib.Path.cwd(), comment=comment, force=args.force)
+diff --git a/configure b/configure
+index 1cd1f690f7b..7fb6c4adfea 100755
+--- a/configure
++++ b/configure
+@@ -8326,7 +8326,7 @@ then :
+ 
+ else $as_nop
+   as_fn_append CFLAGS_NODIST " $jit_flags"
+-           REGEN_JIT_COMMAND="\$(PYTHON_FOR_REGEN) \$(srcdir)/Tools/jit/build.py $host"
++           REGEN_JIT_COMMAND="\$(PYTHON_FOR_REGEN) \$(srcdir)/Tools/jit/build.py $host --with-cflags=\"\$(CONFIGURE_CFLAGS)\""
+            JIT_STENCILS_H="jit_stencils.h"
+            if test "x$Py_DEBUG" = xtrue
+ then :
+diff --git a/configure.ac b/configure.ac
+index 3fcb18922c5..616999a96b2 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -1846,7 +1846,7 @@ AS_VAR_IF([jit_flags],
+           [],
+           [AS_VAR_APPEND([CFLAGS_NODIST], [" $jit_flags"])
+            AS_VAR_SET([REGEN_JIT_COMMAND],
+-                      ["\$(PYTHON_FOR_REGEN) \$(srcdir)/Tools/jit/build.py $host"])
++                      ["\$(PYTHON_FOR_REGEN) \$(srcdir)/Tools/jit/build.py $host --with-cflags=\"\$(CONFIGURE_CFLAGS)\""])
+            AS_VAR_SET([JIT_STENCILS_H], ["jit_stencils.h"])
+            AS_VAR_IF([Py_DEBUG],
+                      [true],
diff --git a/cpython-unix/patch-jit-cflags-314.patch b/cpython-unix/patch-jit-cflags-314.patch
new file mode 100644
index 00000000..81f6fd02
--- /dev/null
+++ b/cpython-unix/patch-jit-cflags-314.patch
@@ -0,0 +1,70 @@
+diff --git a/Tools/jit/_targets.py b/Tools/jit/_targets.py
+index b3b065652e0..d361f57382e 100644
+--- a/Tools/jit/_targets.py
++++ b/Tools/jit/_targets.py
+@@ -10,6 +10,7 @@
+ import sys
+ import tempfile
+ import typing
++import shlex
+ 
+ import _llvm
+ import _schema
+@@ -42,6 +43,7 @@ class _Target(typing.Generic[_S, _R]):
+     stable: bool = False
+     debug: bool = False
+     verbose: bool = False
++    cflags: str = ""
+     known_symbols: dict[str, int] = dataclasses.field(default_factory=dict)
+ 
+     def _get_nop(self) -> bytes:
+@@ -115,6 +117,7 @@ async def _compile(
+     ) -> _stencils.StencilGroup:
+         o = tempdir / f"{opname}.o"
+         args = [
++            *shlex.split(self.cflags),
+             f"--target={self.triple}",
+             "-DPy_BUILD_CORE_MODULE",
+             "-D_DEBUG" if self.debug else "-DNDEBUG",
+diff --git a/Tools/jit/build.py b/Tools/jit/build.py
+index a8cb0f67c36..663874ad439 100644
+--- a/Tools/jit/build.py
++++ b/Tools/jit/build.py
+@@ -22,7 +22,11 @@
+     parser.add_argument(
+         "-v", "--verbose", action="store_true", help="echo commands as they are run"
+     )
++    parser.add_argument(
++        "--with-cflags", help="additional flags to pass to the compiler", default=""
++    )
+     args = parser.parse_args()
+     args.target.debug = args.debug
+     args.target.verbose = args.verbose
++    args.target.cflags = args.with_cflags
+     args.target.build(pathlib.Path.cwd(), comment=comment, force=args.force)
+diff --git a/configure b/configure
+index 1b75ddfa26d..3c9e550b5d3 100755
+--- a/configure
++++ b/configure
+@@ -8399,7 +8399,7 @@ then :
+ 
+ else case e in #(
+   e) as_fn_append CFLAGS_NODIST " $jit_flags"
+-           REGEN_JIT_COMMAND="\$(PYTHON_FOR_REGEN) \$(srcdir)/Tools/jit/build.py $host"
++           REGEN_JIT_COMMAND="\$(PYTHON_FOR_REGEN) \$(srcdir)/Tools/jit/build.py $host --with-cflags=\"\$(CONFIGURE_CFLAGS)\""
+            JIT_STENCILS_H="jit_stencils.h"
+            if test "x$Py_DEBUG" = xtrue
+ then :
+diff --git a/configure.ac b/configure.ac
+index c449bb5ebb3..5f9d08a4ee7 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -1827,7 +1827,7 @@ AS_VAR_IF([jit_flags],
+           [],
+           [AS_VAR_APPEND([CFLAGS_NODIST], [" $jit_flags"])
+            AS_VAR_SET([REGEN_JIT_COMMAND],
+-                      ["\$(PYTHON_FOR_REGEN) \$(srcdir)/Tools/jit/build.py $host"])
++                      ["\$(PYTHON_FOR_REGEN) \$(srcdir)/Tools/jit/build.py $host --with-cflags=\"\$(CONFIGURE_CFLAGS)\""])
+            AS_VAR_SET([JIT_STENCILS_H], ["jit_stencils.h"])
+            AS_VAR_IF([Py_DEBUG],
+                      [true],

From 7fb77ff39f3465bdccdff31ce4c0639fd0fa9f1d Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 19 May 2025 20:22:57 -0500
Subject: [PATCH 087/157] Bump requests from 2.31.0 to 2.32.2 (#611)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Bumps [requests](https://github.com/psf/requests) from 2.31.0 to 2.32.2.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/psf/requests/releases">requests's
releases</a>.</em></p>
<blockquote>
<h2>v2.32.2</h2>
<h2>2.32.2 (2024-05-21)</h2>
<p><strong>Deprecations</strong></p>
<ul>
<li>
<p>To provide a more stable migration for custom HTTPAdapters impacted
by the CVE changes in 2.32.0, we've renamed <code>_get_connection</code>
to
a new public API, <code>get_connection_with_tls_context</code>. Existing
custom
HTTPAdapters will need to migrate their code to use this new API.
<code>get_connection</code> is considered deprecated in all versions of
Requests&gt;=2.32.0.</p>
<p>A minimal (2-line) example has been provided in the linked PR to ease
migration, but we strongly urge users to evaluate if their custom
adapter
is subject to the same issue described in CVE-2024-35195. (<a
href="https://redirect.github.com/psf/requests/issues/6710">#6710</a>)</p>
</li>
</ul>
<h2>v2.32.1</h2>
<h2>2.32.1 (2024-05-20)</h2>
<p><strong>Bugfixes</strong></p>
<ul>
<li>Add missing test certs to the sdist distributed on PyPI.</li>
</ul>
<h2>v2.32.0</h2>
<h2>2.32.0 (2024-05-20)</h2>
<h2>🐍 PYCON US 2024 EDITION 🐍</h2>
<p><strong>Security</strong></p>
<ul>
<li>Fixed an issue where setting <code>verify=False</code> on the first
request from a
Session will cause subsequent requests to the <em>same origin</em> to
also ignore
cert verification, regardless of the value of <code>verify</code>.
(<a
href="https://github.com/psf/requests/security/advisories/GHSA-9wx4-h78v-vm56">https://github.com/psf/requests/security/advisories/GHSA-9wx4-h78v-vm56</a>)</li>
</ul>
<p><strong>Improvements</strong></p>
<ul>
<li><code>verify=True</code> now reuses a global SSLContext which should
improve
request time variance between first and subsequent requests. It should
also minimize certificate load time on Windows systems when using a
Python
version built with OpenSSL 3.x. (<a
href="https://redirect.github.com/psf/requests/issues/6667">#6667</a>)</li>
<li>Requests now supports optional use of character detection
(<code>chardet</code> or <code>charset_normalizer</code>) when
repackaged or vendored.
This enables <code>pip</code> and other projects to minimize their
vendoring
surface area. The <code>Response.text()</code> and
<code>apparent_encoding</code> APIs
will default to <code>utf-8</code> if neither library is present. (<a
href="https://redirect.github.com/psf/requests/issues/6702">#6702</a>)</li>
</ul>
<p><strong>Bugfixes</strong></p>
<ul>
<li>Fixed bug in length detection where emoji length was incorrectly
calculated in the request content-length. (<a
href="https://redirect.github.com/psf/requests/issues/6589">#6589</a>)</li>
<li>Fixed deserialization bug in JSONDecodeError. (<a
href="https://redirect.github.com/psf/requests/issues/6629">#6629</a>)</li>
<li>Fixed bug where an extra leading <code>/</code> (path separator)
could lead
urllib3 to unnecessarily reparse the request URI. (<a
href="https://redirect.github.com/psf/requests/issues/6644">#6644</a>)</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/psf/requests/blob/main/HISTORY.md">requests's
changelog</a>.</em></p>
<blockquote>
<h2>2.32.2 (2024-05-21)</h2>
<p><strong>Deprecations</strong></p>
<ul>
<li>
<p>To provide a more stable migration for custom HTTPAdapters impacted
by the CVE changes in 2.32.0, we've renamed <code>_get_connection</code>
to
a new public API, <code>get_connection_with_tls_context</code>. Existing
custom
HTTPAdapters will need to migrate their code to use this new API.
<code>get_connection</code> is considered deprecated in all versions of
Requests&gt;=2.32.0.</p>
<p>A minimal (2-line) example has been provided in the linked PR to ease
migration, but we strongly urge users to evaluate if their custom
adapter
is subject to the same issue described in CVE-2024-35195. (<a
href="https://redirect.github.com/psf/requests/issues/6710">#6710</a>)</p>
</li>
</ul>
<h2>2.32.1 (2024-05-20)</h2>
<p><strong>Bugfixes</strong></p>
<ul>
<li>Add missing test certs to the sdist distributed on PyPI.</li>
</ul>
<h2>2.32.0 (2024-05-20)</h2>
<p><strong>Security</strong></p>
<ul>
<li>Fixed an issue where setting <code>verify=False</code> on the first
request from a
Session will cause subsequent requests to the <em>same origin</em> to
also ignore
cert verification, regardless of the value of <code>verify</code>.
(<a
href="https://github.com/psf/requests/security/advisories/GHSA-9wx4-h78v-vm56">https://github.com/psf/requests/security/advisories/GHSA-9wx4-h78v-vm56</a>)</li>
</ul>
<p><strong>Improvements</strong></p>
<ul>
<li><code>verify=True</code> now reuses a global SSLContext which should
improve
request time variance between first and subsequent requests. It should
also minimize certificate load time on Windows systems when using a
Python
version built with OpenSSL 3.x. (<a
href="https://redirect.github.com/psf/requests/issues/6667">#6667</a>)</li>
<li>Requests now supports optional use of character detection
(<code>chardet</code> or <code>charset_normalizer</code>) when
repackaged or vendored.
This enables <code>pip</code> and other projects to minimize their
vendoring
surface area. The <code>Response.text()</code> and
<code>apparent_encoding</code> APIs
will default to <code>utf-8</code> if neither library is present. (<a
href="https://redirect.github.com/psf/requests/issues/6702">#6702</a>)</li>
</ul>
<p><strong>Bugfixes</strong></p>
<ul>
<li>Fixed bug in length detection where emoji length was incorrectly
calculated in the request content-length. (<a
href="https://redirect.github.com/psf/requests/issues/6589">#6589</a>)</li>
<li>Fixed deserialization bug in JSONDecodeError. (<a
href="https://redirect.github.com/psf/requests/issues/6629">#6629</a>)</li>
<li>Fixed bug where an extra leading <code>/</code> (path separator)
could lead
urllib3 to unnecessarily reparse the request URI. (<a
href="https://redirect.github.com/psf/requests/issues/6644">#6644</a>)</li>
</ul>
<p><strong>Deprecations</strong></p>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/psf/requests/commit/88dce9d854797c05d0ff296b70e0430535ef8aaf"><code>88dce9d</code></a>
v2.32.2</li>
<li><a
href="https://github.com/psf/requests/commit/c98e4d133ef29c46a9b68cd783087218a8075e05"><code>c98e4d1</code></a>
Merge pull request <a
href="https://redirect.github.com/psf/requests/issues/6710">#6710</a>
from nateprewitt/api_rename</li>
<li><a
href="https://github.com/psf/requests/commit/92075b330a30b9883f466a43d3f7566ab849f91b"><code>92075b3</code></a>
Add deprecation warning</li>
<li><a
href="https://github.com/psf/requests/commit/aa1461b68aa73e2f6ec0e78c8853b635c76fd099"><code>aa1461b</code></a>
Move _get_connection to get_connection_with_tls_context</li>
<li><a
href="https://github.com/psf/requests/commit/970e8cec988421bd43da57350723b05c8ce8dc7e"><code>970e8ce</code></a>
v2.32.1</li>
<li><a
href="https://github.com/psf/requests/commit/d6ebc4a2f1f68b7e355fb7e4dd5ffc0845547f9f"><code>d6ebc4a</code></a>
v2.32.0</li>
<li><a
href="https://github.com/psf/requests/commit/9a40d1277807f0a4f26c9a37eea8ec90faa8aadc"><code>9a40d12</code></a>
Avoid reloading root certificates to improve concurrent performance (<a
href="https://redirect.github.com/psf/requests/issues/6667">#6667</a>)</li>
<li><a
href="https://github.com/psf/requests/commit/0c030f78d24f29a459dbf39b28b4cc765e2153d7"><code>0c030f7</code></a>
Merge pull request <a
href="https://redirect.github.com/psf/requests/issues/6702">#6702</a>
from nateprewitt/no_char_detection</li>
<li><a
href="https://github.com/psf/requests/commit/555b870eb19d497ddb67042645420083ec8efb02"><code>555b870</code></a>
Allow character detection dependencies to be optional in post-packaging
steps</li>
<li><a
href="https://github.com/psf/requests/commit/d6dded3f00afcf56a7e866cb0732799045301eb0"><code>d6dded3</code></a>
Merge pull request <a
href="https://redirect.github.com/psf/requests/issues/6700">#6700</a>
from franekmagiera/update-redirect-to-invalid-uri-test</li>
<li>Additional commits viewable in <a
href="https://github.com/psf/requests/compare/v2.31.0...v2.32.2">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=requests&package-manager=pip&previous-version=2.31.0&new-version=2.32.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/astral-sh/python-build-standalone/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
 requirements.win.txt | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/requirements.win.txt b/requirements.win.txt
index 4890be56..c0b8bf46 100644
--- a/requirements.win.txt
+++ b/requirements.win.txt
@@ -267,9 +267,9 @@ referencing==0.33.0 \
     # via
     #   jsonschema
     #   jsonschema-specifications
-requests==2.31.0 \
-    --hash=sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f \
-    --hash=sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1
+requests==2.32.2 \
+    --hash=sha256:dd951ff5ecf3e3b3aa26b40703ba77495dab41da839ae72ef3c8e5d8e2433289 \
+    --hash=sha256:fc06670dd0ed212426dfeb94fc1b983d917c4f9847c863f313c9dfaaffb7c23c
     # via docker
 rpds-py==0.18.0 \
     --hash=sha256:01e36a39af54a30f28b73096dd39b6802eddd04c90dbe161c1b8dbe22353189f \

From 23e06486f87e2f4b1d7f9db9c58a2127f3c70f3f Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 19 May 2025 20:23:09 -0500
Subject: [PATCH 088/157] Bump certifi from 2024.2.2 to 2024.7.4 (#612)

Bumps [certifi](https://github.com/certifi/python-certifi) from 2024.2.2
to 2024.7.4.
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/certifi/python-certifi/commit/bd8153872e9c6fc98f4023df9c2deaffea2fa463"><code>bd81538</code></a>
2024.07.04 (<a
href="https://redirect.github.com/certifi/python-certifi/issues/295">#295</a>)</li>
<li><a
href="https://github.com/certifi/python-certifi/commit/06a2cbf21f345563dde6c28b60e29d57e9b210b3"><code>06a2cbf</code></a>
Bump peter-evans/create-pull-request from 6.0.5 to 6.1.0 (<a
href="https://redirect.github.com/certifi/python-certifi/issues/294">#294</a>)</li>
<li><a
href="https://github.com/certifi/python-certifi/commit/13bba02b72bac97c432c277158bc04b4d2a6bc23"><code>13bba02</code></a>
Bump actions/checkout from 4.1.6 to 4.1.7 (<a
href="https://redirect.github.com/certifi/python-certifi/issues/293">#293</a>)</li>
<li><a
href="https://github.com/certifi/python-certifi/commit/e8abcd0e62b334c164b95d49fcabdc9ecbca0554"><code>e8abcd0</code></a>
Bump pypa/gh-action-pypi-publish from 1.8.14 to 1.9.0 (<a
href="https://redirect.github.com/certifi/python-certifi/issues/292">#292</a>)</li>
<li><a
href="https://github.com/certifi/python-certifi/commit/124f4adf171e15cd9a91a8b6e0325ecc97be8fe1"><code>124f4ad</code></a>
2024.06.02 (<a
href="https://redirect.github.com/certifi/python-certifi/issues/291">#291</a>)</li>
<li><a
href="https://github.com/certifi/python-certifi/commit/c2196ce5d6ee675b27755a19948480a7823e2c6a"><code>c2196ce</code></a>
--- (<a
href="https://redirect.github.com/certifi/python-certifi/issues/290">#290</a>)</li>
<li><a
href="https://github.com/certifi/python-certifi/commit/fefdeec7588ff1c05214b85a552afcad5fdb51b2"><code>fefdeec</code></a>
Bump actions/checkout from 4.1.4 to 4.1.5 (<a
href="https://redirect.github.com/certifi/python-certifi/issues/289">#289</a>)</li>
<li><a
href="https://github.com/certifi/python-certifi/commit/3c5fb1560b826a7f83f1f9750173ff766492c9cf"><code>3c5fb15</code></a>
Bump actions/download-artifact from 4.1.6 to 4.1.7 (<a
href="https://redirect.github.com/certifi/python-certifi/issues/286">#286</a>)</li>
<li><a
href="https://github.com/certifi/python-certifi/commit/4a9569a3eb58db8548536fc16c5c5c7af946a5b1"><code>4a9569a</code></a>
Bump actions/checkout from 4.1.2 to 4.1.4 (<a
href="https://redirect.github.com/certifi/python-certifi/issues/287">#287</a>)</li>
<li><a
href="https://github.com/certifi/python-certifi/commit/1fc808626a895a916b1e4c2b63abae6c5eafdbe3"><code>1fc8086</code></a>
Bump peter-evans/create-pull-request from 6.0.4 to 6.0.5 (<a
href="https://redirect.github.com/certifi/python-certifi/issues/288">#288</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/certifi/python-certifi/compare/2024.02.02...2024.07.04">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=certifi&package-manager=pip&previous-version=2024.2.2&new-version=2024.7.4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/astral-sh/python-build-standalone/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
 requirements.win.txt | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/requirements.win.txt b/requirements.win.txt
index c0b8bf46..4fc9c31e 100644
--- a/requirements.win.txt
+++ b/requirements.win.txt
@@ -6,9 +6,9 @@ attrs==23.2.0 \
     # via
     #   jsonschema
     #   referencing
-certifi==2024.2.2 \
-    --hash=sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f \
-    --hash=sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1
+certifi==2024.7.4 \
+    --hash=sha256:5a1e7645bc0ec61a09e26c36f6106dd4cf40c6db3a1fb6352b0244e7fb057c7b \
+    --hash=sha256:c198e21b1289c2ab85ee4e67bb4b4ef3ead0892059901a8d5b622f24a1101e90
     # via requests
 charset-normalizer==3.3.2 \
     --hash=sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027 \

From 7c83f655d43b16957356f80265691d0b9fbbf683 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 19 May 2025 20:23:18 -0500
Subject: [PATCH 089/157] Bump urllib3 from 2.2.1 to 2.2.2 (#613)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Bumps [urllib3](https://github.com/urllib3/urllib3) from 2.2.1 to 2.2.2.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/urllib3/urllib3/releases">urllib3's
releases</a>.</em></p>
<blockquote>
<h2>2.2.2</h2>
<h2>🚀 urllib3 is fundraising for HTTP/2 support</h2>
<p><a
href="https://sethmlarson.dev/urllib3-is-fundraising-for-http2-support">urllib3
is raising ~$40,000 USD</a> to release HTTP/2 support and ensure
long-term sustainable maintenance of the project after a sharp decline
in financial support for 2023. If your company or organization uses
Python and would benefit from HTTP/2 support in Requests, pip, cloud
SDKs, and thousands of other projects <a
href="https://opencollective.com/urllib3">please consider contributing
financially</a> to ensure HTTP/2 support is developed sustainably and
maintained for the long-haul.</p>
<p>Thank you for your support.</p>
<h2>Changes</h2>
<ul>
<li>Added the <code>Proxy-Authorization</code> header to the list of
headers to strip from requests when redirecting to a different host. As
before, different headers can be set via
<code>Retry.remove_headers_on_redirect</code>.</li>
<li>Allowed passing negative integers as <code>amt</code> to read
methods of <code>http.client.HTTPResponse</code> as an alternative to
<code>None</code>. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/3122">#3122</a>)</li>
<li>Fixed return types representing copying actions to use
<code>typing.Self</code>. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/3363">#3363</a>)</li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/urllib3/urllib3/compare/2.2.1...2.2.2">https://github.com/urllib3/urllib3/compare/2.2.1...2.2.2</a></p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/urllib3/urllib3/blob/main/CHANGES.rst">urllib3's
changelog</a>.</em></p>
<blockquote>
<h1>2.2.2 (2024-06-17)</h1>
<ul>
<li>Added the <code>Proxy-Authorization</code> header to the list of
headers to strip from requests when redirecting to a different host. As
before, different headers can be set via
<code>Retry.remove_headers_on_redirect</code>.</li>
<li>Allowed passing negative integers as <code>amt</code> to read
methods of <code>http.client.HTTPResponse</code> as an alternative to
<code>None</code>.
(<code>[#3122](https://github.com/urllib3/urllib3/issues/3122)
&lt;https://github.com/urllib3/urllib3/issues/3122&gt;</code>__)</li>
<li>Fixed return types representing copying actions to use
<code>typing.Self</code>.
(<code>[#3363](https://github.com/urllib3/urllib3/issues/3363)
&lt;https://github.com/urllib3/urllib3/issues/3363&gt;</code>__)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/urllib3/urllib3/commit/27e2a5c5a7ab6a517252cc8dcef3ffa6ffb8f61a"><code>27e2a5c</code></a>
Release 2.2.2 (<a
href="https://redirect.github.com/urllib3/urllib3/issues/3406">#3406</a>)</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/accff72ecc2f6cf5a76d9570198a93ac7c90270e"><code>accff72</code></a>
Merge pull request from GHSA-34jh-p97f-mpxf</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/34be4a57e59eb7365bcc37d52e9f8271b5b8d0d3"><code>34be4a5</code></a>
Pin CFFI to a new release candidate instead of a Git commit (<a
href="https://redirect.github.com/urllib3/urllib3/issues/3398">#3398</a>)</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/da410581b6b3df73da976b5ce5eb20a4bd030437"><code>da41058</code></a>
Bump browser-actions/setup-chrome from 1.6.0 to 1.7.1 (<a
href="https://redirect.github.com/urllib3/urllib3/issues/3399">#3399</a>)</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/b07a669bd970d69847801148286b726f0570b625"><code>b07a669</code></a>
Bump github/codeql-action from 2.13.4 to 3.25.6 (<a
href="https://redirect.github.com/urllib3/urllib3/issues/3396">#3396</a>)</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/b8589ec9f8c4da91511e601b632ac06af7e7c10e"><code>b8589ec</code></a>
Measure coverage with v4 of artifact actions (<a
href="https://redirect.github.com/urllib3/urllib3/issues/3394">#3394</a>)</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/f3bdc5585111429e22c81b5fb26c3ec164d98b81"><code>f3bdc55</code></a>
Allow triggering CI manually (<a
href="https://redirect.github.com/urllib3/urllib3/issues/3391">#3391</a>)</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/52392654b30183129cf3ec06010306f517d9c146"><code>5239265</code></a>
Fix HTTP version in debug log (<a
href="https://redirect.github.com/urllib3/urllib3/issues/3316">#3316</a>)</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/b34619f94ece0c40e691a5aaf1304953d88089de"><code>b34619f</code></a>
Bump actions/checkout to 4.1.4 (<a
href="https://redirect.github.com/urllib3/urllib3/issues/3387">#3387</a>)</li>
<li><a
href="https://github.com/urllib3/urllib3/commit/9961d14de7c920091d42d42ed76d5d479b80064d"><code>9961d14</code></a>
Bump browser-actions/setup-chrome from 1.5.0 to 1.6.0 (<a
href="https://redirect.github.com/urllib3/urllib3/issues/3386">#3386</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/urllib3/urllib3/compare/2.2.1...2.2.2">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=urllib3&package-manager=pip&previous-version=2.2.1&new-version=2.2.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/astral-sh/python-build-standalone/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
 requirements.win.txt | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/requirements.win.txt b/requirements.win.txt
index 4fc9c31e..6100025a 100644
--- a/requirements.win.txt
+++ b/requirements.win.txt
@@ -382,9 +382,9 @@ tomli==2.0.1 \
     --hash=sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc \
     --hash=sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f
     # via -r requirements.in
-urllib3==2.2.1 \
-    --hash=sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d \
-    --hash=sha256:d0570876c61ab9e520d776c38acbbb5b05a776d3f9ff98a5c8fd5162a444cf19
+urllib3==2.2.2 \
+    --hash=sha256:a448b2f64d686155468037e1ace9f2d2199776e17f0a46610480d311f73e3472 \
+    --hash=sha256:dd505485549a7a552833da5e6063639d0d177c04f23bc3864e41e5dc5f612168
     # via
     #   docker
     #   requests

From 784ea01b8c488765a434cfd76b3a76306901a578 Mon Sep 17 00:00:00 2001
From: Gregory Szorc <gregory.szorc@gmail.com>
Date: Tue, 20 May 2025 19:27:48 -0700
Subject: [PATCH 090/157] Rework host platform naming (#617)

---
 cpython-unix/Makefile              |  2 +-
 cpython-unix/build-cpython-host.sh |  2 +-
 cpython-unix/build-cpython.sh      | 32 ++++++++---------
 cpython-unix/build-main.py         | 22 +++---------
 cpython-unix/build-ncurses.sh      |  6 ++--
 cpython-unix/build-tix.sh          |  2 +-
 cpython-unix/build-tk.sh           |  4 +--
 cpython-unix/build.py              | 25 +++++++------
 cpython-unix/targets.yml           | 58 +++++++++++++++++-------------
 pythonbuild/utils.py               | 50 +++++++++++++++++++++-----
 10 files changed, 117 insertions(+), 86 deletions(-)

diff --git a/cpython-unix/Makefile b/cpython-unix/Makefile
index 196b6bbf..2413d7a1 100644
--- a/cpython-unix/Makefile
+++ b/cpython-unix/Makefile
@@ -86,7 +86,7 @@ $(OUTDIR)/$(CLANG_FILENAME):
 $(OUTDIR)/musl-$(MUSL_VERSION)-$(HOST_PLATFORM).tar: $(BASE_TOOLCHAIN_DEPENDS) $(HERE)/build-musl.sh
 	$(RUN_BUILD) --toolchain musl
 
-ifeq ($(HOST_PLATFORM),linux64)
+ifeq ($(HOST_PLATFORM),linux_x86_64)
     TOOLCHAIN_TARGET := $(OUTDIR)/musl-$(MUSL_VERSION)-$(HOST_PLATFORM).tar
 else
     TOOLCHAIN_TARGET :=
diff --git a/cpython-unix/build-cpython-host.sh b/cpython-unix/build-cpython-host.sh
index 3cfa3ac5..99b021d7 100755
--- a/cpython-unix/build-cpython-host.sh
+++ b/cpython-unix/build-cpython-host.sh
@@ -22,7 +22,7 @@ export trailer_m4=${TOOLS_PATH}/host/share/autoconf/autoconf/trailer.m4
 
 # The share/autoconf/autom4te.cfg file also hard-codes some paths. Rewrite
 # those to the real tools path.
-if [ "${PYBUILD_PLATFORM}" = "macos" ]; then
+if [[ "${PYBUILD_PLATFORM}" = macos* ]]; then
   sed_args="-i '' -e"
 else
   sed_args="-i"
diff --git a/cpython-unix/build-cpython.sh b/cpython-unix/build-cpython.sh
index 39d810e3..b7ba3855 100755
--- a/cpython-unix/build-cpython.sh
+++ b/cpython-unix/build-cpython.sh
@@ -33,7 +33,7 @@ export trailer_m4=${TOOLS_PATH}/host/share/autoconf/autoconf/trailer.m4
 
 # The share/autoconf/autom4te.cfg file also hard-codes some paths. Rewrite
 # those to the real tools path.
-if [ "${PYBUILD_PLATFORM}" = "macos" ]; then
+if [[ "${PYBUILD_PLATFORM}" = macos* ]]; then
     sed_args=(-i '' -e)
 else
     sed_args=(-i)
@@ -59,7 +59,7 @@ cat Makefile.extra
 pushd Python-${PYTHON_VERSION}
 
 # configure doesn't support cross-compiling on Apple. Teach it.
-if [ "${PYBUILD_PLATFORM}" = "macos" ]; then
+if [[ "${PYBUILD_PLATFORM}" = macos* ]]; then
     if [ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_13}" ]; then
         patch -p1 -i ${ROOT}/patch-apple-cross-3.13.patch
     elif [ "${PYTHON_MAJMIN_VERSION}" = "3.12" ]; then
@@ -159,7 +159,7 @@ fi
 # linked modules. But those libraries should only get linked into libpython, not the
 # executable. This behavior is kinda suspect on all platforms, as it could be adding
 # library dependencies that shouldn't need to be there.
-if [ "${PYBUILD_PLATFORM}" = "macos" ]; then
+if [[ "${PYBUILD_PLATFORM}" = macos* ]]; then
     if [ "${PYTHON_MAJMIN_VERSION}" = "3.9" ]; then
         patch -p1 -i ${ROOT}/patch-python-link-modules-3.9.patch
     elif [ "${PYTHON_MAJMIN_VERSION}" = "3.10" ]; then
@@ -214,7 +214,7 @@ fi
 # macOS. On older versions, we need to hack up readline.c to build against
 # libedit. This patch breaks older libedit (as seen on macOS) so don't apply
 # on macOS.
-if [[ -n "${PYTHON_MEETS_MAXIMUM_VERSION_3_9}" && "${PYBUILD_PLATFORM}" != "macos" ]]; then
+if [[ -n "${PYTHON_MEETS_MAXIMUM_VERSION_3_9}" && "${PYBUILD_PLATFORM}" != macos* ]]; then
     # readline.c assumes that a modern readline API version has a free_history_entry().
     # but libedit does not. Change the #ifdef accordingly.
     #
@@ -317,13 +317,13 @@ CFLAGS=${CFLAGS//-fvisibility=hidden/}
 
 # But some symbols from some dependency libraries are still non-hidden for some
 # reason. We force the linker to do our bidding.
-if [ "${PYBUILD_PLATFORM}" != "macos" ]; then
+if [[ "${PYBUILD_PLATFORM}" != macos* ]]; then
     LDFLAGS="${LDFLAGS} -Wl,--exclude-libs,ALL"
 fi
 
 EXTRA_CONFIGURE_FLAGS=
 
-if [ "${PYBUILD_PLATFORM}" = "macos" ]; then
+if [[ "${PYBUILD_PLATFORM}" = macos* ]]; then
     CFLAGS="${CFLAGS} -I${TOOLS_PATH}/deps/include/uuid"
 
     # Prevent using symbols not supported by current macOS SDK target.
@@ -332,7 +332,7 @@ fi
 
 # Always build against libedit instead of the default of readline.
 # macOS always uses the system libedit, so no tweaks are needed.
-if [ "${PYBUILD_PLATFORM}" != "macos" ]; then
+if [[ "${PYBUILD_PLATFORM}" != macos* ]]; then
     # CPython 3.10 introduced proper configure support for libedit, so add configure
     # flag there.
     if [ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_10}" ]; then
@@ -381,7 +381,7 @@ CONFIGURE_FLAGS="
 # this patch mildly conflicts with the macos-only patch-python-link-modules
 # applied above, so you will need to resolve that conflict if you re-enable
 # this for macos.
-if [ "${PYBUILD_PLATFORM}" != "macos" ]; then
+if [[ "${PYBUILD_PLATFORM}" != macos* ]]; then
     if [ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_12}" ]; then
         patch -p1 -i "${ROOT}/patch-python-configure-add-enable-static-libpython-for-interpreter.patch"
     else
@@ -493,7 +493,7 @@ if [ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_11}" ]; then
     CONFIGURE_FLAGS="${CONFIGURE_FLAGS} --with-build-python=${TOOLS_PATH}/host/bin/python${PYTHON_MAJMIN_VERSION}"
 fi
 
-if [ "${PYBUILD_PLATFORM}" = "macos" ]; then
+if [[ "${PYBUILD_PLATFORM}" = macos* ]]; then
     # Configure may detect libintl from non-system sources, such
     # as Homebrew or MacPorts. So nerf the check to prevent this.
     CONFIGURE_FLAGS="${CONFIGURE_FLAGS} ac_cv_lib_intl_textdomain=no"
@@ -563,7 +563,7 @@ if [ "${PYBUILD_PLATFORM}" = "macos" ]; then
 fi
 
 # ptsrname_r is only available in SDK 13.4+, but we target a lower version for compatibility.
-if [ "${PYBUILD_PLATFORM}" = "macos" ]; then
+if [[ "${PYBUILD_PLATFORM}" = macos* ]]; then
     CONFIGURE_FLAGS="${CONFIGURE_FLAGS} ac_cv_func_ptsname_r=no"
 fi
 
@@ -575,12 +575,12 @@ fi
 
 # On 3.14+ `test_strftime_y2k` fails when cross-compiling for `x86_64_v2` and `x86_64_v3` targets on
 # Linux, so we ignore it. See https://github.com/python/cpython/issues/128104
-if [[ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_14}" && -n "${CROSS_COMPILING}" && "${PYBUILD_PLATFORM}" != "macos" ]]; then
+if [[ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_14}" && -n "${CROSS_COMPILING}" && "${PYBUILD_PLATFORM}" != macos* ]]; then
     export PROFILE_TASK='-m test --pgo --ignore test_strftime_y2k'
 fi
 
 # We use ndbm on macOS and BerkeleyDB elsewhere.
-if [ "${PYBUILD_PLATFORM}" = "macos" ]; then
+if [[ "${PYBUILD_PLATFORM}" = macos* ]]; then
     CONFIGURE_FLAGS="${CONFIGURE_FLAGS} --with-dbmliborder=ndbm"
 else
     CONFIGURE_FLAGS="${CONFIGURE_FLAGS} --with-dbmliborder=bdb"
@@ -608,7 +608,7 @@ if [ -n "${CROSS_COMPILING}" ]; then
     # python will end up with the time.tzset function or not. All linux targets,
     # however, should have a working tzset function via libc. So we manually
     # indicate this to the configure script.
-    if [ "${PYBUILD_PLATFORM}" != "macos" ]; then
+    if [[ "${PYBUILD_PLATFORM}" != macos* ]]; then
         CONFIGURE_FLAGS="${CONFIGURE_FLAGS} ac_cv_working_tzset=yes"
     fi
 
@@ -660,7 +660,7 @@ fi
 # This ensures we can run the binary in any location without
 # LD_LIBRARY_PATH pointing to the directory containing libpython.
 if [ "${PYBUILD_SHARED}" = "1" ]; then
-    if [ "${PYBUILD_PLATFORM}" = "macos" ]; then
+    if [[ "${PYBUILD_PLATFORM}" = macos* ]]; then
         # There's only 1 dylib produced on macOS and it has the binary suffix.
         LIBPYTHON_SHARED_LIBRARY_BASENAME=libpython${PYTHON_MAJMIN_VERSION}${PYTHON_BINARY_SUFFIX}.dylib
         LIBPYTHON_SHARED_LIBRARY=${ROOT}/out/python/install/lib/${LIBPYTHON_SHARED_LIBRARY_BASENAME}
@@ -1143,7 +1143,7 @@ cp -av ${TOOLS_PATH}/deps/lib/*.a ${ROOT}/out/python/build/lib/
 #
 # We copy the libclang_rt.<platform>.a library from our clang into the
 # distribution so it is available. See documentation in quirks.rst for more.
-if [ "${PYBUILD_PLATFORM}" = "macos" ]; then
+if [[ "${PYBUILD_PLATFORM}" = macos* ]]; then
   cp -av $(dirname $(which clang))/../lib/clang/*/lib/darwin/libclang_rt.osx.a ${ROOT}/out/python/build/lib/
 fi
 
@@ -1158,7 +1158,7 @@ if [ -d "${TOOLS_PATH}/deps/lib/tcl8" ]; then
         cp -av $source ${ROOT}/out/python/install/lib/
     done
 
-    if [ "${PYBUILD_PLATFORM}" != "macos" ]; then
+    if [[ "${PYBUILD_PLATFORM}" != macos* ]]; then
         cp -av ${TOOLS_PATH}/deps/lib/Tix8.4.3 ${ROOT}/out/python/install/lib/
     fi
 fi
diff --git a/cpython-unix/build-main.py b/cpython-unix/build-main.py
index 6bf91b49..a353daf2 100755
--- a/cpython-unix/build-main.py
+++ b/cpython-unix/build-main.py
@@ -7,7 +7,6 @@
 import multiprocessing
 import os
 import pathlib
-import platform
 import subprocess
 import sys
 
@@ -15,6 +14,8 @@
 from pythonbuild.downloads import DOWNLOADS
 from pythonbuild.utils import (
     compress_python_archive,
+    current_host_platform,
+    default_target_triple,
     get_target_settings,
     release_tag_from_git,
     supported_targets,
@@ -28,29 +29,14 @@
 
 
 def main():
-    if sys.platform == "linux":
-        host_platform = "linux64"
-        default_target_triple = "x86_64-unknown-linux-gnu"
-    elif sys.platform == "darwin":
-        host_platform = "macos"
-        machine = platform.machine()
-
-        if machine == "arm64":
-            default_target_triple = "aarch64-apple-darwin"
-        elif machine == "x86_64":
-            default_target_triple = "x86_64-apple-darwin"
-        else:
-            raise Exception("unhandled macOS machine value: %s" % machine)
-    else:
-        print("Unsupported build platform: %s" % sys.platform)
-        return 1
+    host_platform = current_host_platform()
 
     # Note these arguments must be synced with `build.py`
     parser = argparse.ArgumentParser()
 
     parser.add_argument(
         "--target-triple",
-        default=default_target_triple,
+        default=default_target_triple(),
         choices=supported_targets(TARGETS_CONFIG),
         help="Target host triple to build for",
     )
diff --git a/cpython-unix/build-ncurses.sh b/cpython-unix/build-ncurses.sh
index b1a568bc..25df7e22 100755
--- a/cpython-unix/build-ncurses.sh
+++ b/cpython-unix/build-ncurses.sh
@@ -16,7 +16,7 @@ tar -xf ncurses-${NCURSES_VERSION}.tar.gz
 # ncurses version. Our workaround is to build ncurses for the host when
 # cross-compiling then make its `tic` available to the target ncurses
 # build.
-if [[ -n "${CROSS_COMPILING}" && "${PYBUILD_PLATFORM}" != "macos" ]]; then
+if [[ -n "${CROSS_COMPILING}" && "${PYBUILD_PLATFORM}" != macos* ]]; then
   echo "building host ncurses to provide modern tic for cross-compile"
 
   pushd ncurses-${NCURSES_VERSION}
@@ -65,7 +65,7 @@ CONFIGURE_FLAGS="
 # ncurses wants --with-build-cc when cross-compiling. But it insists on CC
 # and this value not being equal, even though using the same binary with
 # different compiler flags is doable!
-if [[ -n "${CROSS_COMPILING}" && "${PYBUILD_PLATFORM}" != "macos" ]]; then
+if [[ -n "${CROSS_COMPILING}" && "${PYBUILD_PLATFORM}" != macos* ]]; then
   CONFIGURE_FLAGS="${CONFIGURE_FLAGS} --with-build-cc=$(which "${HOST_CC}")"
 fi
 
@@ -91,7 +91,7 @@ fi
 # binary. So we provide a suitable runtime value and then move files at install
 # time.
 
-if [ "${PYBUILD_PLATFORM}" = "macos" ]; then
+if [[ "${PYBUILD_PLATFORM}" = macos* ]]; then
   CONFIGURE_FLAGS="${CONFIGURE_FLAGS}
     --datadir=/usr/share
     --sysconfdir=/etc
diff --git a/cpython-unix/build-tix.sh b/cpython-unix/build-tix.sh
index a894f528..c1d5fae3 100755
--- a/cpython-unix/build-tix.sh
+++ b/cpython-unix/build-tix.sh
@@ -28,7 +28,7 @@ if [ "${CC}" = "clang" ]; then
     CFLAGS="${CFLAGS} -Wno-error=implicit-function-declaration -Wno-error=incompatible-function-pointer-types"
 fi
 
-if [ "${PYBUILD_PLATFORM}" = "macos" ]; then
+if [[ "${PYBUILD_PLATFORM}" = macos* ]]; then
     CFLAGS="${CFLAGS} -I${TOOLS_PATH}/deps/include"
     EXTRA_CONFIGURE_FLAGS="--without-x"
 else
diff --git a/cpython-unix/build-tk.sh b/cpython-unix/build-tk.sh
index 0dca3516..2769a631 100755
--- a/cpython-unix/build-tk.sh
+++ b/cpython-unix/build-tk.sh
@@ -17,7 +17,7 @@ pushd tk*/unix
 CFLAGS="${EXTRA_TARGET_CFLAGS} -fPIC"
 LDFLAGS="${EXTRA_TARGET_LDFLAGS}"
 
-if [ "${PYBUILD_PLATFORM}" = "macos" ]; then
+if [[ "${PYBUILD_PLATFORM}" = macos* ]]; then
     CFLAGS="${CFLAGS} -I${TOOLS_PATH}/deps/include -Wno-availability"
     CFLAGS="${CFLAGS} -Wno-deprecated-declarations -Wno-unknown-attributes -Wno-typedef-redefinition"
     LDFLAGS="-L${TOOLS_PATH}/deps/lib"
@@ -36,7 +36,7 @@ CFLAGS="${CFLAGS}" CPPFLAGS="${CFLAGS}" LDFLAGS="${LDFLAGS}" ./configure \
     ${EXTRA_CONFIGURE_FLAGS}
 
 # Remove wish, since we don't need it.
-if [ "${PYBUILD_PLATFORM}" != "macos" ]; then
+if [[ "${PYBUILD_PLATFORM}" != macos* ]]; then
     sed -i 's/all: binaries libraries doc/all: libraries/' Makefile
     sed -i 's/install-binaries: $(TK_STUB_LIB_FILE) $(TK_LIB_FILE) ${WISH_EXE}/install-binaries: $(TK_STUB_LIB_FILE) $(TK_LIB_FILE)/' Makefile
 fi
diff --git a/cpython-unix/build.py b/cpython-unix/build.py
index f058e93a..05783fe8 100755
--- a/cpython-unix/build.py
+++ b/cpython-unix/build.py
@@ -116,7 +116,7 @@ def add_target_env(env, build_platform, target_triple, build_env):
     extra_host_cflags = []
     extra_host_ldflags = []
 
-    if build_platform == "linux64":
+    if build_platform == "linux_x86_64":
         env["BUILD_TRIPLE"] = "x86_64-unknown-linux-gnu"
 
         env["TARGET_TRIPLE"] = (
@@ -133,7 +133,7 @@ def add_target_env(env, build_platform, target_triple, build_env):
         ):
             env["CROSS_COMPILING"] = "1"
 
-    if build_platform == "macos":
+    if build_platform.startswith("macos_"):
         machine = platform.machine()
 
         if machine == "arm64":
@@ -232,7 +232,7 @@ def toolchain_archive_path(package_name, host_platform):
 
 
 def install_binutils(platform):
-    return platform != "macos"
+    return not platform.startswith("macos_")
 
 
 def simple_build(
@@ -410,7 +410,7 @@ def build_tix(
             )
 
         depends = {"tcl", "tk"}
-        if host_platform != "macos":
+        if not host_platform.startswith("macos_"):
             depends |= {"libX11", "xorgproto"}
 
         for p in sorted(depends):
@@ -516,7 +516,7 @@ def python_build_info(
 
     binary_suffix = ""
 
-    if platform == "linux64":
+    if platform == "linux_x86_64":
         bi["core"]["static_lib"] = (
             "install/lib/python{version}/config-{version}{binary_suffix}-x86_64-linux-gnu/libpython{version}{binary_suffix}.a".format(
                 version=version, binary_suffix=binary_suffix
@@ -539,7 +539,7 @@ def python_build_info(
             object_file_format = f"llvm-bitcode:%{llvm_version}"
         else:
             object_file_format = "elf"
-    elif platform == "macos":
+    elif platform.startswith("macos_"):
         bi["core"]["static_lib"] = (
             "install/lib/python{version}/config-{version}{binary_suffix}-darwin/libpython{version}{binary_suffix}.a".format(
                 version=version, binary_suffix=binary_suffix
@@ -599,9 +599,12 @@ def python_build_info(
         if lib.startswith("-l"):
             lib = lib[2:]
 
-            if platform == "linux64" and lib not in linux_allowed_system_libraries:
+            if platform == "linux_x86_64" and lib not in linux_allowed_system_libraries:
                 raise Exception("unexpected library in LIBS (%s): %s" % (libs, lib))
-            elif platform == "macos" and lib not in MACOS_ALLOW_SYSTEM_LIBRARIES:
+            elif (
+                platform.startswith("macos_")
+                and lib not in MACOS_ALLOW_SYSTEM_LIBRARIES
+            ):
                 raise Exception("unexpected library in LIBS (%s): %s" % (libs, lib))
 
             log("adding core system link library: %s" % lib)
@@ -867,7 +870,7 @@ def build_cpython(
         extension_module_loading = ["builtin"]
         crt_features = []
 
-        if host_platform == "linux64":
+        if host_platform == "linux_x86_64":
             if "static" in parsed_build_options:
                 crt_features.append("static")
             else:
@@ -893,7 +896,7 @@ def build_cpython(
 
             python_symbol_visibility = "global-default"
 
-        elif host_platform == "macos":
+        elif host_platform.startswith("macos_"):
             python_symbol_visibility = "global-default"
             extension_module_loading.append("shared-library")
             crt_features.append("libSystem")
@@ -1238,7 +1241,7 @@ def main():
 
         elif action == "tk":
             extra_archives = {"tcl"}
-            if host_platform != "macos":
+            if not host_platform.startswith("macos_"):
                 extra_archives |= {
                     "libX11",
                     "libXau",
diff --git a/cpython-unix/targets.yml b/cpython-unix/targets.yml
index 1b179768..46a92e31 100644
--- a/cpython-unix/targets.yml
+++ b/cpython-unix/targets.yml
@@ -61,7 +61,8 @@
 # 11.0+.
 aarch64-apple-darwin:
   host_platforms:
-    - macos
+    - macos_arm64
+    - macos_x86_64
   pythons_supported:
     - '3.9'
     - '3.10'
@@ -111,7 +112,8 @@ aarch64-apple-darwin:
 
 aarch64-apple-ios:
   host_platforms:
-    - macos
+    - macos_arm64
+    - macos_x86_64
   pythons_supported:
     - '3.9'
   needs_toolchain: true
@@ -153,7 +155,7 @@ aarch64-apple-ios:
 
 aarch64-unknown-linux-gnu:
   host_platforms:
-    - linux64
+    - linux_x86_64
   pythons_supported:
     - '3.9'
     - '3.10'
@@ -194,7 +196,8 @@ aarch64-unknown-linux-gnu:
 
 arm64-apple-tvos:
   host_platforms:
-    - macos
+    - macos_arm64
+    - macos_x86_64
   pythons_supported:
     - '3.9'
   needs_toolchain: true
@@ -235,7 +238,7 @@ arm64-apple-tvos:
 
 armv7-unknown-linux-gnueabi:
   host_platforms:
-    - linux64
+    - linux_x86_64
   pythons_supported:
     - '3.9'
     - '3.10'
@@ -276,7 +279,7 @@ armv7-unknown-linux-gnueabi:
 
 armv7-unknown-linux-gnueabihf:
   host_platforms:
-    - linux64
+    - linux_x86_64
   pythons_supported:
     - '3.9'
     - '3.10'
@@ -317,7 +320,7 @@ armv7-unknown-linux-gnueabihf:
 
 i686-unknown-linux-gnu:
   host_platforms:
-    - linux64
+    - linux_x86_64
   pythons_supported:
     - '3.9'
     - '3.10'
@@ -363,7 +366,7 @@ i686-unknown-linux-gnu:
 
 mips-unknown-linux-gnu:
   host_platforms:
-    - linux64
+    - linux_x86_64
   pythons_supported:
     - '3.9'
     - '3.10'
@@ -404,7 +407,7 @@ mips-unknown-linux-gnu:
 
 mipsel-unknown-linux-gnu:
   host_platforms:
-    - linux64
+    - linux_x86_64
   pythons_supported:
     - '3.9'
     - '3.10'
@@ -445,7 +448,7 @@ mipsel-unknown-linux-gnu:
 
 ppc64le-unknown-linux-gnu:
   host_platforms:
-    - linux64
+    - linux_x86_64
   pythons_supported:
     - '3.9'
     - '3.10'
@@ -486,7 +489,7 @@ ppc64le-unknown-linux-gnu:
 
 riscv64-unknown-linux-gnu:
   host_platforms:
-    - linux64
+    - linux_x86_64
   pythons_supported:
     - '3.9'
     - '3.10'
@@ -527,7 +530,7 @@ riscv64-unknown-linux-gnu:
 
 s390x-unknown-linux-gnu:
   host_platforms:
-    - linux64
+    - linux_x86_64
   pythons_supported:
     - '3.9'
     - '3.10'
@@ -568,7 +571,8 @@ s390x-unknown-linux-gnu:
 
 thumb7k-apple-watchos:
   host_platforms:
-    - macos
+    - macos_arm64
+    - macos_x86_64
   pythons_supported:
     - '3.9'
   needs_toolchain: true
@@ -613,7 +617,8 @@ thumb7k-apple-watchos:
 # machines.
 x86_64-apple-darwin:
   host_platforms:
-    - macos
+    - macos_arm64
+    - macos_x86_64
   pythons_supported:
     - '3.9'
     - '3.10'
@@ -663,7 +668,8 @@ x86_64-apple-darwin:
 
 x86_64-apple-ios:
   host_platforms:
-    - macos
+    - macos_arm64
+    - macos_x86_64
   pythons_supported:
     - '3.9'
   needs_toolchain: true
@@ -705,7 +711,8 @@ x86_64-apple-ios:
 
 x86_64-apple-tvos:
   host_platforms:
-    - macos
+    - macos_arm64
+    - macos_x86_64
   pythons_supported:
     - '3.9'
   needs_toolchain: true
@@ -746,7 +753,8 @@ x86_64-apple-tvos:
 
 x86_64-apple-watchos:
   host_platforms:
-    - macos
+    - macos_arm64
+    - macos_x86_64
   pythons_supported:
     - '3.9'
   needs_toolchain: true
@@ -787,7 +795,7 @@ x86_64-apple-watchos:
 
 x86_64-unknown-linux-gnu:
   host_platforms:
-    - linux64
+    - linux_x86_64
   pythons_supported:
     - '3.9'
     - '3.10'
@@ -833,7 +841,7 @@ x86_64-unknown-linux-gnu:
 
 x86_64_v2-unknown-linux-gnu:
   host_platforms:
-    - linux64
+    - linux_x86_64
   pythons_supported:
     - '3.9'
     - '3.10'
@@ -880,7 +888,7 @@ x86_64_v2-unknown-linux-gnu:
 
 x86_64_v3-unknown-linux-gnu:
   host_platforms:
-    - linux64
+    - linux_x86_64
   pythons_supported:
     - '3.9'
     - '3.10'
@@ -927,7 +935,7 @@ x86_64_v3-unknown-linux-gnu:
 
 x86_64_v4-unknown-linux-gnu:
   host_platforms:
-    - linux64
+    - linux_x86_64
   pythons_supported:
     - '3.9'
     - '3.10'
@@ -974,7 +982,7 @@ x86_64_v4-unknown-linux-gnu:
 
 x86_64-unknown-linux-musl:
   host_platforms:
-    - linux64
+    - linux_x86_64
   pythons_supported:
     - '3.9'
     - '3.10'
@@ -1018,7 +1026,7 @@ x86_64-unknown-linux-musl:
 
 x86_64_v2-unknown-linux-musl:
   host_platforms:
-    - linux64
+    - linux_x86_64
   pythons_supported:
     - '3.9'
     - '3.10'
@@ -1063,7 +1071,7 @@ x86_64_v2-unknown-linux-musl:
 
 x86_64_v3-unknown-linux-musl:
   host_platforms:
-    - linux64
+    - linux_x86_64
   pythons_supported:
     - '3.9'
     - '3.10'
@@ -1108,7 +1116,7 @@ x86_64_v3-unknown-linux-musl:
 
 x86_64_v4-unknown-linux-musl:
   host_platforms:
-    - linux64
+    - linux_x86_64
   pythons_supported:
     - '3.9'
     - '3.10'
diff --git a/pythonbuild/utils.py b/pythonbuild/utils.py
index 14d9a474..1c4f4ffc 100644
--- a/pythonbuild/utils.py
+++ b/pythonbuild/utils.py
@@ -30,6 +30,41 @@
 from .logging import log
 
 
+def current_host_platform() -> str:
+    """Resolve the name of the current machine's host platform.
+
+    This is conceptually a simplified machine triple.
+    """
+    machine = platform.machine()
+    if sys.platform == "linux":
+        if machine == "x86_64":
+            return "linux_x86_64"
+        else:
+            raise Exception(f"unsupported Linux host platform: {machine}")
+    elif sys.platform == "darwin":
+        if machine == "arm64":
+            return "macos_arm64"
+        elif machine == "x86_64":
+            return "macos_x86_64"
+        else:
+            raise Exception(f"unhanded macOS machine type: {machine}")
+    else:
+        raise Exception(f"unsupported host platform: {sys.platform}")
+
+
+def default_target_triple() -> str:
+    """Resolve the default target triple to build for."""
+    host = current_host_platform()
+    if host == "linux_x86_64":
+        return "x86_64-unknown-linux-gnu"
+    elif host == "macos_arm64":
+        return "aarch64-apple-darwin"
+    elif host == "macos_x86_64":
+        return "x86_64-apple-darwin"
+    else:
+        raise Exception(f"unrecognized host platform: {host}")
+
+
 def get_targets(yaml_path: pathlib.Path):
     """Obtain the parsed targets YAML file."""
     with yaml_path.open("rb") as fh:
@@ -47,9 +82,9 @@ def supported_targets(yaml_path: pathlib.Path):
 
     for target, settings in get_targets(yaml_path).items():
         for host_platform in settings["host_platforms"]:
-            if sys.platform == "linux" and host_platform == "linux64":
+            if sys.platform == "linux" and host_platform == "linux_x86_64":
                 targets.add(target)
-            elif sys.platform == "darwin" and host_platform == "macos":
+            elif sys.platform == "darwin" and host_platform.startswith("macos_"):
                 targets.add(target)
 
     return targets
@@ -430,17 +465,16 @@ def sort_key(v):
 
 
 def clang_toolchain(host_platform: str, target_triple: str) -> str:
-    if host_platform == "linux64":
+    if host_platform == "linux_x86_64":
         # musl currently has issues with LLVM 15+.
         if "musl" in target_triple:
             return "llvm-14-x86_64-linux"
         else:
             return "llvm-20-x86_64-linux"
-    elif host_platform == "macos":
-        if platform.mac_ver()[2] == "arm64":
-            return "llvm-aarch64-macos"
-        else:
-            return "llvm-x86_64-macos"
+    elif host_platform == "macos_arm64":
+        return "llvm-aarch64-macos"
+    elif host_platform == "macos_x86_64":
+        return "llvm-x86_64-macos"
     else:
         raise Exception("unhandled host platform")
 

From 482a9bc818a81a236397a603e5fd169187aaabbe Mon Sep 17 00:00:00 2001
From: Geoffrey Thomas <geofft@ldpreload.com>
Date: Wed, 21 May 2025 21:32:50 -0400
Subject: [PATCH 091/157] Add an rpath to bin/python3 on glibc platforms to fix
 #619 (#621)

Even though the Python interpreter no longer needs libpython3.x.so, it
turns out some extension modules (incorrectly) do, and miraculously,
allowing them to find libpython3.x.so doesn't actually break things, for
reasons detailed in the comment. So set an rpath that allows
libpython3.x.so to be loaded if needed by some other library, even
though we won't use that ourselves. We are already doing this on musl;
do it on glibc too.

Note that this change does not risk users who want to make bin/python3
setuid or setcap (e.g. #576); while the rpath is presumably ignored for
privileged binaries, there is no error message, and the binary launches
fine, and _because_ we do not need the rpath in order for the
interpreter to work, everything (except these misbuilt extension
modules) works.
---
 cpython-unix/build-cpython.sh | 106 ++++++++++++++++++++++++++--------
 1 file changed, 83 insertions(+), 23 deletions(-)

diff --git a/cpython-unix/build-cpython.sh b/cpython-unix/build-cpython.sh
index b7ba3855..73fb8c45 100755
--- a/cpython-unix/build-cpython.sh
+++ b/cpython-unix/build-cpython.sh
@@ -688,45 +688,105 @@ if [ "${PYBUILD_SHARED}" = "1" ]; then
                 -change /install/lib/${LIBPYTHON_SHARED_LIBRARY_BASENAME} @executable_path/../lib/${LIBPYTHON_SHARED_LIBRARY_BASENAME} \
                 ${ROOT}/out/python/install/bin/python${PYTHON_MAJMIN_VERSION}${PYTHON_BINARY_SUFFIX}
         fi
-    else
+    else # (not macos)
         LIBPYTHON_SHARED_LIBRARY_BASENAME=libpython${PYTHON_MAJMIN_VERSION}${PYTHON_BINARY_SUFFIX}.so.1.0
         LIBPYTHON_SHARED_LIBRARY=${ROOT}/out/python/install/lib/${LIBPYTHON_SHARED_LIBRARY_BASENAME}
 
-        if [ "${CC}" == "musl-clang" ]; then
-            # musl does not support $ORIGIN in DT_NEEDED, so we use RPATH instead. This could be
-            # problematic, i.e., we could load the shared library from the wrong location if
-            # `LD_LIBRARY_PATH` is set, but there's not a clear alternative at this time. The
-            # long term solution is probably to statically link to libpython instead.
+        # Although we are statically linking libpython, some extension
+        # modules link against libpython.so even though they are not
+        # supposed to do that. If you try to import them on an
+        # interpreter statically linking libpython, all the symbols they
+        # need are resolved from the main program (because neither glibc
+        # nor musl has two-level namespaces), so there is hopefully no
+        # correctness risk, but they need to be able to successfully
+        # find libpython.so in order to load the module.  To allow such
+        # extensions to load, we set an rpath to point at our lib
+        # directory, so that if anyone ever tries to find a libpython,
+        # they successfully find one. See
+        # https://github.com/astral-sh/python-build-standalone/issues/619
+        # for some reports of extensions that need this workaround.
+        #
+        # Note that this matches the behavior of Debian/Ubuntu/etc.'s
+        # interpreter (if package libpython3.x is installed, which it
+        # usually is thanks to gdb, vim, etc.), because libpython is in
+        # the system lib directory, as well as the behavior in practice
+        # on conda-forge miniconda and probably other Conda-family
+        # Python distributions, which too set an rpath.
+        #
+        # There is a downside of making this libpython locatable: some user
+        # code might do e.g.
+        #     ctypes.CDLL(f"libpython3.{sys.version_info.minor}.so.1.0")
+        # to get at things in the CPython API not exposed to pure
+        # Python. This code may _silently misbehave_ on a
+        # static-libpython interpreter, because you are actually using
+        # the second copy of libpython. For loading static data or using
+        # accessors, you might get lucky and things will work, with the
+        # full set of dangers of C undefined behavior being possible.
+        # However, there are a few reasons we think this risk is
+        # tolerable.  First, we can't actually fix it by not setting the
+        # rpath - user code may well find a system libpython3.x.so or
+        # something which is even more likely to break. Second, this
+        # exact problem happens with Debian, Conda, etc., so it is very
+        # unlikely (compared to the extension modules case above) that
+        # any widely-used code has this problem; the risk is largely
+        # backwards incompatibility of our own builds. Also, it's quite
+        # easy for users to fix: simply do
+        #    ctypes.CDLL(None)
+        # (i.e., dlopen(NULL)), to use symbols already in the process;
+        # this will work reliably on all interpreters regardless of
+        # whether they statically or dynamically link libpython. Finally,
+        # we can (and should, at some point) add a warning, error, or
+        # silent fix to ctypes for user code that does this, which will
+        # also cover the case of other libpython3.x.so files on the
+        # library search path that we cannot suppress.
+        #
+        # In the past, when we dynamically linked libpython, we avoided
+        # using an rpath and instead used a DT_NEEDED entry with
+        # $ORIGIN/../lib/libpython.so, because LD_LIBRARY_PATH takes
+        # precedence over DT_RUNPATH, and it's not uncommon to have an
+        # LD_LIBRARY_PATH that points to some sort of unwanted libpython
+        # (e.g., actions/setup-python does this as of May 2025).
+        # Now, though, because we're not actually using code from the
+        # libpython that's loaded and just need _any_ file of that name
+        # to satisfy the link, that's not a problem. (This also implies
+        # another approach to the problem: ensure that libraries find an
+        # empty dummy libpython.so, which allows the link to succeed but
+        # ensures they do not use any unwanted symbols. That might be
+        # worth doing at some point.)
+        patchelf --set-rpath "\$ORIGIN/../lib" \
+            ${ROOT}/out/python/install/bin/python${PYTHON_MAJMIN_VERSION}
+
+        if [ -n "${PYTHON_BINARY_SUFFIX}" ]; then
             patchelf --set-rpath "\$ORIGIN/../lib" \
-                ${ROOT}/out/python/install/bin/python${PYTHON_MAJMIN_VERSION}
+                ${ROOT}/out/python/install/bin/python${PYTHON_MAJMIN_VERSION}${PYTHON_BINARY_SUFFIX}
+        fi
 
+        # For libpython3.so (the ABI3 library for embedders), we do
+        # still dynamically link libpython3.x.so.1.0 (the
+        # version-specific library), because there is no particular
+        # speedup/benefit in statically linking libpython into
+        # libpython3.so, and we'd just be shipping a third copy of the
+        # libpython code. Therefore we use the old logic for that and
+        # set an $ORIGIN-relative DT_NEEDED, at least for glibc.
+        # Unfortunately, musl does not (as of May 2025) support $ORIGIN
+        # in DT_NEEDED, only in DT_RUNPATH/RPATH, so we did set an rpath
+        # for bin/python3, and still do for libpython3.so. In both
+        # cases, we have no concerns/need no workarounds for code
+        # referencing libpython3.x.so.1.0, because we are actually
+        # dynamically linking it and so all code will get the real
+        # libpython3.x.so.1.0 that they want.
+        if [ "${CC}" == "musl-clang" ]; then
             # libpython3.so isn't present in debug builds.
             if [ -z "${CPYTHON_DEBUG}" ]; then
                 patchelf --set-rpath "\$ORIGIN/../lib" \
                     ${ROOT}/out/python/install/lib/libpython3.so
             fi
-
-            if [ -n "${PYTHON_BINARY_SUFFIX}" ]; then
-                patchelf --set-rpath "\$ORIGIN/../lib" \
-                    ${ROOT}/out/python/install/bin/python${PYTHON_MAJMIN_VERSION}${PYTHON_BINARY_SUFFIX}
-            fi
         else
-            # If we simply set DT_RUNPATH via --set-rpath, LD_LIBRARY_PATH would be used before
-            # DT_RUNPATH, which could result in confusion at run-time. But if DT_NEEDED contains a
-            # slash, the explicit path is used.
-            patchelf --replace-needed ${LIBPYTHON_SHARED_LIBRARY_BASENAME} "\$ORIGIN/../lib/${LIBPYTHON_SHARED_LIBRARY_BASENAME}" \
-                ${ROOT}/out/python/install/bin/python${PYTHON_MAJMIN_VERSION}
-
             # libpython3.so isn't present in debug builds.
             if [ -z "${CPYTHON_DEBUG}" ]; then
                 patchelf --replace-needed ${LIBPYTHON_SHARED_LIBRARY_BASENAME} "\$ORIGIN/../lib/${LIBPYTHON_SHARED_LIBRARY_BASENAME}" \
                     ${ROOT}/out/python/install/lib/libpython3.so
             fi
-
-            if [ -n "${PYTHON_BINARY_SUFFIX}" ]; then
-                patchelf --replace-needed ${LIBPYTHON_SHARED_LIBRARY_BASENAME} "\$ORIGIN/../lib/${LIBPYTHON_SHARED_LIBRARY_BASENAME}" \
-                    ${ROOT}/out/python/install/bin/python${PYTHON_MAJMIN_VERSION}${PYTHON_BINARY_SUFFIX}
-            fi
         fi
     fi
 fi

From c5503752d25b94c51cf6ae74ac2954f0eb7ac1ba Mon Sep 17 00:00:00 2001
From: Gregory Szorc <gregory.szorc@gmail.com>
Date: Mon, 26 May 2025 16:24:01 -0700
Subject: [PATCH 092/157] Remove support for Linux x86 builds (#626)

We stopped shipping the distributions in
6fa8fe9f42aa9187095d60a8dacf19e4eb76baf6 in October 2023. At the time we
preserved build support just in case.

I don't believe anyone has complained about the loss of x86 Linux
distributions.

I don't believe there is compelling value in PBS supporting x86 Linux
distributions.

If someone wants to run Python on x86 Linux, they can always use
CPython's official build systen, which still supports targeting x86
Linux.

This commit rips out our support building for x86 Linux.
---
 cpython-unix/base.Dockerfile       |  4 ---
 cpython-unix/build-cpython.sh      |  6 ++--
 cpython-unix/build-libX11.sh       |  6 ----
 cpython-unix/build.Dockerfile      |  4 ---
 cpython-unix/extension-modules.yml |  3 --
 cpython-unix/targets.yml           | 46 ------------------------------
 6 files changed, 3 insertions(+), 66 deletions(-)

diff --git a/cpython-unix/base.Dockerfile b/cpython-unix/base.Dockerfile
index 58016550..7e666e04 100644
--- a/cpython-unix/base.Dockerfile
+++ b/cpython-unix/base.Dockerfile
@@ -29,10 +29,6 @@ RUN for s in debian_jessie debian_jessie-updates debian-security_jessie/updates;
       echo 'Acquire::Retries "5";'; \
     ) > /etc/apt/apt.conf.d/99cpython-portable
 
-RUN ( echo 'amd64'; \
-      echo 'i386'; \
-    ) > /var/lib/dpkg/arch
-
 # apt iterates all available file descriptors up to rlim_max and calls
 # fcntl(fd, F_SETFD, FD_CLOEXEC). This can result in millions of system calls
 # (we've seen 1B in the wild) and cause operations to take seconds to minutes.
diff --git a/cpython-unix/build-cpython.sh b/cpython-unix/build-cpython.sh
index 73fb8c45..fcf469ec 100755
--- a/cpython-unix/build-cpython.sh
+++ b/cpython-unix/build-cpython.sh
@@ -91,6 +91,9 @@ fi
 
 # Configure nerfs RUNSHARED when cross-compiling, which prevents PGO from running when
 # we can in fact run the target binaries (e.g. x86_64 host and i686 target). Undo that.
+# TODO this may not be needed after removing support for i686 builds. But it
+# may still be useful since CPython's definition of cross-compiling has historically
+# been very liberal and kicks in when it arguably shouldn't.
 if [ -n "${CROSS_COMPILING}" ]; then
     if [ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_14}" ]; then
         patch -p1 -i ${ROOT}/patch-dont-clear-runshared-14.patch
@@ -1058,9 +1061,6 @@ armv7-unknown-linux-gnueabi)
 armv7-unknown-linux-gnueabihf)
     PYTHON_ARCH="arm-linux-gnueabihf"
     ;;
-i686-unknown-linux-gnu)
-    PYTHON_ARCH="i386-linux-gnu"
-    ;;
 mips-unknown-linux-gnu)
     PYTHON_ARCH="mips-linux-gnu"
     ;;
diff --git a/cpython-unix/build-libX11.sh b/cpython-unix/build-libX11.sh
index e8f65ad4..bb45028b 100755
--- a/cpython-unix/build-libX11.sh
+++ b/cpython-unix/build-libX11.sh
@@ -54,9 +54,6 @@ if [ -n "${CROSS_COMPILING}" ]; then
     armv7-unknown-linux-gnueabihf)
       EXTRA_FLAGS="${EXTRA_FLAGS} --enable-malloc0returnsnull"
       ;;
-    i686-unknown-linux-gnu)
-      EXTRA_FLAGS="${EXTRA_FLAGS} --enable-malloc0returnsnull"
-      ;;
     mips-unknown-linux-gnu)
       EXTRA_FLAGS="${EXTRA_FLAGS} --enable-malloc0returnsnull"
       ;;
@@ -81,9 +78,6 @@ if [ -n "${CROSS_COMPILING}" ]; then
     aarch64-unknown-linux-musl)
       EXTRA_FLAGS="${EXTRA_FLAGS} --enable-malloc0returnsnull"
       ;;
-    i686-unknown-linux-musl)
-      EXTRA_FLAGS="${EXTRA_FLAGS} --enable-malloc0returnsnull"
-      ;;
     mips-unknown-linux-musl)
       EXTRA_FLAGS="${EXTRA_FLAGS} --enable-malloc0returnsnull"
       ;;
diff --git a/cpython-unix/build.Dockerfile b/cpython-unix/build.Dockerfile
index 09e37fab..e44d0a2e 100644
--- a/cpython-unix/build.Dockerfile
+++ b/cpython-unix/build.Dockerfile
@@ -1,8 +1,5 @@
 {% include 'base.Dockerfile' %}
 
-# libc6-dev:i386 pulls in 32-bit system libraries to enable cross-compiling
-# to i386.
-#
 # libffi-dev and zlib1g-dev are present so host Python (during cross-builds)
 # can build the ctypes and zlib extensions. So comment in build-cpython.sh
 # for more context.
@@ -14,7 +11,6 @@ RUN ulimit -n 10000 && apt-get install \
     bzip2 \
     file \
     libc6-dev \
-    libc6-dev:i386 \
     libffi-dev \
     make \
     patch \
diff --git a/cpython-unix/extension-modules.yml b/cpython-unix/extension-modules.yml
index c5207857..028eadde 100644
--- a/cpython-unix/extension-modules.yml
+++ b/cpython-unix/extension-modules.yml
@@ -249,7 +249,6 @@ _decimal:
     - define: CONFIG_32=1
       targets:
         - armv7-.*
-        - i686-.*
         - mips-.*
         - mipsel-.*
     - define: CONFIG_64=1
@@ -299,7 +298,6 @@ _hashlib:
     # a static library so there isn't a runtime dependency.
     - name: ':libatomic.a'
       targets:
-        - i686-unknown-linux-gnu
         - mips-unknown-linux-gnu
         - mipsel-unknown-linux-gnu
         - x86_64.*-unknown-linux-gnu
@@ -570,7 +568,6 @@ _ssl:
     # a static library so there isn't a runtime dependency.
     - name: ':libatomic.a'
       targets:
-        - i686-unknown-linux-gnu
         - mips-unknown-linux-gnu
         - mipsel-unknown-linux-gnu
         - x86_64.*-unknown-linux-gnu
diff --git a/cpython-unix/targets.yml b/cpython-unix/targets.yml
index 46a92e31..1b47dba4 100644
--- a/cpython-unix/targets.yml
+++ b/cpython-unix/targets.yml
@@ -318,52 +318,6 @@ armv7-unknown-linux-gnueabihf:
     - zlib
   openssl_target: linux-armv4
 
-i686-unknown-linux-gnu:
-  host_platforms:
-    - linux_x86_64
-  pythons_supported:
-    - '3.9'
-    - '3.10'
-    - '3.11'
-    - '3.12'
-    - '3.13'
-    - '3.14'
-  needs_toolchain: true
-  host_cc: clang
-  host_cxx: clang++
-  target_cc: clang
-  target_cxx: clang++
-  target_cflags:
-    - '-m32'
-    - '-fvisibility=hidden'
-  target_ldflags:
-    - '-m32'
-  needs:
-    - autoconf
-    - bdb
-    - binutils
-    - bzip2
-    - expat
-    - libedit
-    - libffi
-    - libX11
-    - libXau
-    - libxcb
-    - m4
-    - mpdecimal
-    - ncurses
-    - openssl-3.0
-    - patchelf
-    - sqlite
-    - tcl
-    - tk
-    - tix
-    - uuid
-    - xorgproto
-    - xz
-    - zlib
-  openssl_target: linux-x86-clang
-
 mips-unknown-linux-gnu:
   host_platforms:
     - linux_x86_64

From 35eec28788d95cf5c4cd46689f1b837ad3e35a5c Mon Sep 17 00:00:00 2001
From: Gregory Szorc <gregory.szorc@gmail.com>
Date: Mon, 26 May 2025 16:24:37 -0700
Subject: [PATCH 093/157] Use host CPython as Python dependency; remove xcb
 image; upgrade xcb (#627)

The `xcb` Dockerfile / image existed to provide a host build of CPython,
which was required to build libxcb, xcb-proto, and tk. The existence of
this image predated our building a host CPython in order to build
CPython itself.

With PBS now unconditionally building a host CPython, we can use our
host CPython during the builds of these packages, eliminating the need
for the xcb image.

This commit makes that transition.

We also upgrade libxcb and xcb-proto to the latest version as part of
this migration. Older versions of libxcb aren't compatible with Python
3.12+ due to removal of the `imp` module.
---
 .github/workflows/linux.yml               |  3 ---
 cpython-unix/Makefile                     | 13 ++++++++-----
 cpython-unix/build-xcb-proto.sh           |  2 +-
 cpython-unix/build.py                     | 21 +++++++++++++++++++++
 cpython-unix/xcb.Dockerfile               |  3 ---
 cpython-unix/xcb.cross-riscv64.Dockerfile |  3 ---
 cpython-unix/xcb.cross.Dockerfile         |  3 ---
 pythonbuild/downloads.py                  | 18 ++++++++----------
 pythonbuild/utils.py                      |  1 -
 9 files changed, 38 insertions(+), 29 deletions(-)
 delete mode 100644 cpython-unix/xcb.Dockerfile
 delete mode 100644 cpython-unix/xcb.cross-riscv64.Dockerfile
 delete mode 100644 cpython-unix/xcb.cross.Dockerfile

diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml
index c0c21bd0..3b70b5f8 100644
--- a/.github/workflows/linux.yml
+++ b/.github/workflows/linux.yml
@@ -60,9 +60,6 @@ jobs:
           - build.cross
           - build.cross-riscv64
           - gcc
-          - xcb
-          - xcb.cross
-          - xcb.cross-riscv64
     name: ${{ matrix.image }}
     runs-on: depot-ubuntu-22.04
     permissions:
diff --git a/cpython-unix/Makefile b/cpython-unix/Makefile
index 2413d7a1..4cacaff3 100644
--- a/cpython-unix/Makefile
+++ b/cpython-unix/Makefile
@@ -70,6 +70,8 @@ PYTHON_DEP_DEPENDS := \
     $(TOOLCHAIN_DEPENDS) \
     $(NULL)
 
+HOST_PYTHON_DEPENDS := $(OUTDIR)/cpython-$(PYTHON_MAJOR_VERSION)-$(CPYTHON_$(PYTHON_MAJOR_VERSION)_VERSION)-$(HOST_PLATFORM).tar
+
 default: $(OUTDIR)/cpython-$(CPYTHON_$(PYTHON_MAJOR_VERSION)_VERSION)-$(PACKAGE_SUFFIX).tar
 
 ifndef PYBUILD_NO_DOCKER
@@ -149,8 +151,8 @@ $(OUTDIR)/libXau-$(LIBXAU_VERSION)-$(PACKAGE_SUFFIX).tar: $(LIBXAU_DEPENDS)
 
 LIBXCB_DEPENDS = \
     $(PYTHON_DEP_DEPENDS) \
+    $(HOST_PYTHON_DEPENDS) \
     $(HERE)/build-libxcb.sh \
-    $(OUTDIR)/image-$(DOCKER_IMAGE_XCB).tar \
     $(OUTDIR)/xcb-proto-$(XCB_PROTO_VERSION)-$(PACKAGE_SUFFIX).tar \
     $(OUTDIR)/libXau-$(LIBXAU_VERSION)-$(PACKAGE_SUFFIX).tar \
     $(OUTDIR)/xorgproto-$(XORGPROTO_VERSION)-$(PACKAGE_SUFFIX).tar \
@@ -158,7 +160,7 @@ LIBXCB_DEPENDS = \
     $(NULL)
 
 $(OUTDIR)/libxcb-$(LIBXCB_VERSION)-$(PACKAGE_SUFFIX).tar: $(LIBXCB_DEPENDS)
-	$(RUN_BUILD) --docker-image $(DOCKER_IMAGE_XCB) libxcb
+	$(RUN_BUILD) --docker-image $(DOCKER_IMAGE_BUILD) --python-host-version $(PYBUILD_PYTHON_VERSION) libxcb
 
 $(OUTDIR)/m4-$(M4_VERSION)-$(PACKAGE_SUFFIX).tar: $(PYTHON_DEP_DEPENDS) $(HERE)/build-m4.sh
 	$(RUN_BUILD) --docker-image $(DOCKER_IMAGE_BUILD) m4
@@ -204,13 +206,14 @@ $(OUTDIR)/tix-$(TIX_VERSION)-$(PACKAGE_SUFFIX).tar: $(TIX_DEPENDS)
 	$(RUN_BUILD) --docker-image $(DOCKER_IMAGE_BUILD) tix
 
 TK_DEPENDS = \
+    $(HOST_PYTHON_DEPENDS) \
     $(HERE)/build-tk.sh \
     $(OUTDIR)/tcl-$(TCL_VERSION)-$(PACKAGE_SUFFIX).tar \
     $(if $(NEED_LIBX11),$(OUTDIR)/libX11-$(LIBX11_VERSION)-$(PACKAGE_SUFFIX).tar) \
     $(NULL)
 
 $(OUTDIR)/tk-$(TK_VERSION)-$(PACKAGE_SUFFIX).tar: $(TK_DEPENDS)
-	$(RUN_BUILD) --docker-image $(DOCKER_IMAGE_XCB) tk
+	$(RUN_BUILD) --docker-image $(DOCKER_IMAGE_BUILD) --python-host-version $(PYBUILD_PYTHON_VERSION) tk
 
 $(OUTDIR)/uuid-$(UUID_VERSION)-$(PACKAGE_SUFFIX).tar: $(PYTHON_DEP_DEPENDS) $(HERE)/build-uuid.sh
 	$(RUN_BUILD) --docker-image $(DOCKER_IMAGE_BUILD) uuid
@@ -218,8 +221,8 @@ $(OUTDIR)/uuid-$(UUID_VERSION)-$(PACKAGE_SUFFIX).tar: $(PYTHON_DEP_DEPENDS) $(HE
 $(OUTDIR)/x11-util-macros-$(X11_UTIL_MACROS_VERSION)-$(PACKAGE_SUFFIX).tar: $(PYTHON_DEP_DEPENDS) $(HERE)/build-x11-util-macros.sh
 	$(RUN_BUILD) --docker-image $(DOCKER_IMAGE_BUILD) x11-util-macros
 
-$(OUTDIR)/xcb-proto-$(XCB_PROTO_VERSION)-$(PACKAGE_SUFFIX).tar: $(PYTHON_DEP_DEPENDS) $(HERE)/build-xcb-proto.sh
-	$(RUN_BUILD) --docker-image $(DOCKER_IMAGE_XCB) xcb-proto
+$(OUTDIR)/xcb-proto-$(XCB_PROTO_VERSION)-$(PACKAGE_SUFFIX).tar: $(PYTHON_DEP_DEPENDS) $(HOST_PYTHON_DEPENDS) $(HERE)/build-xcb-proto.sh
+	$(RUN_BUILD) --docker-image $(DOCKER_IMAGE_BUILD) --python-host-version $(PYBUILD_PYTHON_VERSION) xcb-proto
 
 $(OUTDIR)/xorgproto-$(XORGPROTO_VERSION)-$(PACKAGE_SUFFIX).tar: $(PYTHON_DEP_DEPENDS) $(HERE)/build-xorgproto.sh
 	$(RUN_BUILD) --docker-image $(DOCKER_IMAGE_BUILD) xorgproto
diff --git a/cpython-unix/build-xcb-proto.sh b/cpython-unix/build-xcb-proto.sh
index 21e8c2e4..5ac092a2 100755
--- a/cpython-unix/build-xcb-proto.sh
+++ b/cpython-unix/build-xcb-proto.sh
@@ -12,7 +12,7 @@ pkg-config --version
 export PATH=/tools/${TOOLCHAIN}/bin:/tools/host/bin:$PATH
 export PKG_CONFIG_PATH=/tools/deps/share/pkgconfig
 
-tar -xf xcb-proto-${XCB_PROTO_VERSION}.tar.gz
+tar -xf xcb-proto-${XCB_PROTO_VERSION}.tar.xz
 pushd xcb-proto-${XCB_PROTO_VERSION}
 
 CFLAGS="${EXTRA_TARGET_CFLAGS} -fPIC" CPPFLAGS="${EXTRA_TARGET_CFLAGS} -fPIC" LDFLAGS="${EXTRA_TARGET_LDFLAGS}" ./configure \
diff --git a/cpython-unix/build.py b/cpython-unix/build.py
index 05783fe8..6829e910 100755
--- a/cpython-unix/build.py
+++ b/cpython-unix/build.py
@@ -246,6 +246,7 @@ def simple_build(
     dest_archive,
     extra_archives=None,
     tools_path="deps",
+    python_host_version=None,
 ):
     archive = download_entry(entry, DOWNLOADS_PATH)
 
@@ -264,6 +265,15 @@ def simple_build(
         for a in extra_archives or []:
             build_env.install_artifact_archive(BUILD, a, target_triple, build_options)
 
+        if python_host_version:
+            majmin = ".".join(python_host_version.split(".")[0:2])
+            build_env.install_toolchain_archive(
+                BUILD,
+                f"cpython-{majmin}",
+                host_platform,
+                version=python_host_version,
+            )
+
         build_env.copy_file(archive)
         build_env.copy_file(SUPPORT / ("build-%s.sh" % entry))
 
@@ -796,6 +806,7 @@ def build_cpython(
         for p in sorted(packages):
             build_env.install_artifact_archive(BUILD, p, target_triple, build_options)
 
+        # Install the host CPython.
         build_env.install_toolchain_archive(
             BUILD, entry_name, host_platform, version=python_version
         )
@@ -1032,6 +1043,11 @@ def main():
         default=None,
         help="A custom path to CPython source files to use",
     )
+    parser.add_argument(
+        "--python-host-version",
+        default=None,
+        help="Python X.Y version for host Python installation",
+    )
     parser.add_argument("action")
 
     args = parser.parse_args()
@@ -1047,6 +1063,8 @@ def main():
     dest_archive = pathlib.Path(args.dest_archive)
     docker_image = args.docker_image
 
+    python_host_version = args.python_host_version
+
     settings = get_target_settings(TARGETS_CONFIG, target_triple)
 
     if args.action == "dockerfiles":
@@ -1213,6 +1231,7 @@ def main():
                 target_triple=target_triple,
                 build_options=build_options,
                 dest_archive=dest_archive,
+                python_host_version=python_host_version,
             )
 
         elif action == "libxcb":
@@ -1226,6 +1245,7 @@ def main():
                 build_options=build_options,
                 dest_archive=dest_archive,
                 extra_archives={"libpthread-stubs", "libXau", "xcb-proto", "xorgproto"},
+                python_host_version=python_host_version,
             )
 
         elif action == "tix":
@@ -1260,6 +1280,7 @@ def main():
                 build_options=build_options,
                 dest_archive=dest_archive,
                 extra_archives=extra_archives,
+                python_host_version=python_host_version,
             )
 
         elif action.startswith("cpython-") and action.endswith("-host"):
diff --git a/cpython-unix/xcb.Dockerfile b/cpython-unix/xcb.Dockerfile
deleted file mode 100644
index 33d350e2..00000000
--- a/cpython-unix/xcb.Dockerfile
+++ /dev/null
@@ -1,3 +0,0 @@
-{% include 'build.Dockerfile' %}
-RUN ulimit -n 10000 && apt-get install \
-    python
diff --git a/cpython-unix/xcb.cross-riscv64.Dockerfile b/cpython-unix/xcb.cross-riscv64.Dockerfile
deleted file mode 100644
index 260aa7d7..00000000
--- a/cpython-unix/xcb.cross-riscv64.Dockerfile
+++ /dev/null
@@ -1,3 +0,0 @@
-{% include 'build.cross-riscv64.Dockerfile' %}
-RUN apt-get install \
-    python
diff --git a/cpython-unix/xcb.cross.Dockerfile b/cpython-unix/xcb.cross.Dockerfile
deleted file mode 100644
index cc003ff2..00000000
--- a/cpython-unix/xcb.cross.Dockerfile
+++ /dev/null
@@ -1,3 +0,0 @@
-{% include 'build.cross.Dockerfile' %}
-RUN apt-get install \
-    python
diff --git a/pythonbuild/downloads.py b/pythonbuild/downloads.py
index c6fd2214..12abd7ae 100644
--- a/pythonbuild/downloads.py
+++ b/pythonbuild/downloads.py
@@ -156,13 +156,11 @@
         "licenses": ["MIT"],
         "license_file": "LICENSE.libXau.txt",
     },
-    # Newer versions of libxcb require a modern Python to build. We can take this
-    # dependency once we feel like doing the work.
     "libxcb": {
-        "url": "https://xcb.freedesktop.org/dist/libxcb-1.14.tar.gz",
-        "size": 640322,
-        "sha256": "2c7fcddd1da34d9b238c9caeda20d3bd7486456fc50b3cc6567185dbd5b0ad02",
-        "version": "1.14",
+        "url": "https://xcb.freedesktop.org/dist/libxcb-1.17.0.tar.gz",
+        "size": 661593,
+        "sha256": "2c69287424c9e2128cb47ffe92171e10417041ec2963bceafb65cb3fcf8f0b85",
+        "version": "1.17.0",
         "library_names": ["xcb"],
         "licenses": ["MIT"],
         "license_file": "LICENSE.libxcb.txt",
@@ -380,10 +378,10 @@
         "version": "1.20.1",
     },
     "xcb-proto": {
-        "url": "https://www.x.org/archive/individual/proto/xcb-proto-1.14.1.tar.gz",
-        "size": 194674,
-        "sha256": "85cd21e9d9fbc341d0dbf11eace98d55d7db89fda724b0e598855fcddf0944fd",
-        "version": "1.14.1",
+        "url": "https://xcb.freedesktop.org/dist/xcb-proto-1.17.0.tar.xz",
+        "size": 151748,
+        "sha256": "2c1bacd2110f4799f74de6ebb714b94cf6f80fb112316b1219480fd22562148c",
+        "version": "1.17.0",
     },
     # Newer versions from at least 2023 have build failures for reasons we haven't
     # fully investigated.
diff --git a/pythonbuild/utils.py b/pythonbuild/utils.py
index 1c4f4ffc..3df0f783 100644
--- a/pythonbuild/utils.py
+++ b/pythonbuild/utils.py
@@ -195,7 +195,6 @@ def write_triples_makefiles(
             image_suffix = settings.get("docker_image_suffix", "")
 
             lines.append("DOCKER_IMAGE_BUILD := build%s\n" % image_suffix)
-            lines.append("DOCKER_IMAGE_XCB := xcb%s\n" % image_suffix)
 
             entry = clang_toolchain(host_platform, triple)
             lines.append(

From 6d9b8ac42269ea31e3bf93d3dba0c144591c386a Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Tue, 27 May 2025 08:38:43 -0500
Subject: [PATCH 094/157] Add Dependabot config to group dependency updates
 (#630)

Closes https://github.com/astral-sh/python-build-standalone/issues/620
---
 .github/dependabot.yml | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)
 create mode 100644 .github/dependabot.yml

diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 00000000..7adec609
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,18 @@
+version: 2
+updates:
+- package-ecosystem: "pip
+  directory: "/"
+  schedule:
+    interval: "weekly"
+  groups:
+    python:
+      patterns:
+        - "*"
+- package-ecosystem: "cargo"
+  directory: "/"
+  schedule:
+    interval: "weekly"
+  groups:
+    rust:
+      patterns:
+        - "*"

From c77b2314bf7abf3ee89bb48c81aaa825fd50111a Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Tue, 27 May 2025 09:31:07 -0500
Subject: [PATCH 095/157] Fix dependabot configuration typo (#631)

I am not sure why this change is not validated on pull request :(

Follows #630
---
 .github/dependabot.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index 7adec609..7a977433 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -1,6 +1,6 @@
 version: 2
 updates:
-- package-ecosystem: "pip
+- package-ecosystem: "pip"
   directory: "/"
   schedule:
     interval: "weekly"

From 0af2c72102f7ad260d75b1e2997875c40d9cf44f Mon Sep 17 00:00:00 2001
From: Gregory Szorc <gregory.szorc@gmail.com>
Date: Tue, 27 May 2025 13:17:35 -0700
Subject: [PATCH 096/157] Remove remnants of sccache (#629)

Before commit 71882f2eef78c6eea85c1a7e8fdca5f25ff72022 (May 2022), we
built LLVM from source. This employed sccache to make builds faster.

After that commit, sccache hasn't effectively been used. But there were
remnants of sccache in the code base.

This commit removes all references to sccache in the repo.
---
 cpython-unix/build-binutils.sh  | 11 -----------
 cpython-unix/build.py           | 30 ----------------------------
 cpython-unix/sccache-wrapper.sh | 31 -----------------------------
 docs/building.rst               | 35 ---------------------------------
 pythonbuild/utils.py            | 11 -----------
 src/github.rs                   |  2 +-
 6 files changed, 1 insertion(+), 119 deletions(-)
 delete mode 100755 cpython-unix/sccache-wrapper.sh

diff --git a/cpython-unix/build-binutils.sh b/cpython-unix/build-binutils.sh
index b287e2e1..c52e8238 100755
--- a/cpython-unix/build-binutils.sh
+++ b/cpython-unix/build-binutils.sh
@@ -5,23 +5,12 @@
 
 set -ex
 
-ROOT=$(pwd)
-SCCACHE="${ROOT}/sccache"
-
 cd /build
 
 tar -xf binutils-${BINUTILS_VERSION}.tar.xz
 mkdir binutils-objdir
 pushd binutils-objdir
 
-EXTRA_VARS=
-
-if [ -x "${SCCACHE}" ]; then
-  "${SCCACHE}" --start-server
-  export CC="${SCCACHE} /usr/bin/gcc"
-  export STAGE_CC_WRAPPER="${SCCACHE}"
-fi
-
 # gprofng requires a bison newer than what we have. So just disable it.
 ../binutils-${BINUTILS_VERSION}/configure \
     --build=x86_64-unknown-linux-gnu \
diff --git a/cpython-unix/build.py b/cpython-unix/build.py
index 6829e910..6f98e990 100755
--- a/cpython-unix/build.py
+++ b/cpython-unix/build.py
@@ -64,34 +64,6 @@
 MACOS_ALLOW_FRAMEWORKS = {"CoreFoundation"}
 
 
-def install_sccache(build_env):
-    """Attempt to install sccache into the build environment.
-
-    This will attempt to locate a sccache executable and copy it
-    into the root directory of the build environment.
-    """
-    candidates = [
-        # Prefer a binary in the project itself.
-        ROOT / "sccache",
-    ]
-
-    # Look for sccache in $PATH, but only if the build environment
-    # isn't isolated, as copying binaries into an isolated environment
-    # may not run. And running sccache in an isolated environment won't
-    # do anything meaningful unless an external cache is being used.
-    if not build_env.is_isolated:
-        for path in os.environ.get("PATH", "").split(":"):
-            if not path:
-                continue
-
-            candidates.append(pathlib.Path(path) / "sccache")
-
-    for candidate in candidates:
-        if candidate.exists():
-            build_env.copy_file(candidate)
-            return
-
-
 def add_target_env(env, build_platform, target_triple, build_env):
     add_env_common(env)
 
@@ -302,8 +274,6 @@ def build_binutils(client, image, host_platform):
     archive = download_entry("binutils", DOWNLOADS_PATH)
 
     with build_environment(client, image) as build_env:
-        install_sccache(build_env)
-
         build_env.copy_file(archive)
         build_env.copy_file(SUPPORT / "build-binutils.sh")
 
diff --git a/cpython-unix/sccache-wrapper.sh b/cpython-unix/sccache-wrapper.sh
deleted file mode 100755
index 6eb63fb2..00000000
--- a/cpython-unix/sccache-wrapper.sh
+++ /dev/null
@@ -1,31 +0,0 @@
-#!/usr/bin/env bash
-# This script is needed to handle a race in GCC's build system and a bug in
-# sccache.
-#
-# GCC's build system could materialize `xgcc` and invoke commands like
-# `xgcc -dumpspecs` before make materializes `cc1`. This is relevant because
-# sccache invokes `<compiler> -E` on the first invocation of a compiler to
-# determine which flavor of compiler to treat it as. And `gcc -E` requires
-# support binaries like `cc1` in order to work. Our wrapper script sniffs
-# for existence of `cc1` to mitigate this race condiion.
-#
-# Furthermore, sccache doesn't honor `-B` arguments when running
-# `<compiler> -E`. So even if a support binary like `cc1` may exist, GCC may
-# not know where to find it. Our wrapper script works around this by ensuring
-# the compiler's directory is always on PATH.
-#
-# This script/approach is arguably not sound for use outside of the value of
-# STAGE_CC_WRAPPER in GCC's build system. You have been warned.
-
-set -o errexit
-set -o pipefail
-
-dir=$(dirname $1)
-cc1=${dir}/cc1
-
-if [ -e "${cc1}"  ]; then
-  export PATH=${dir}:${PATH}
-  exec sccache "$@"
-else
-  exec "$@"
-fi
diff --git a/docs/building.rst b/docs/building.rst
index dc91dea2..c6a07e25 100644
--- a/docs/building.rst
+++ b/docs/building.rst
@@ -104,38 +104,3 @@ You will need to specify the path to a ``sh.exe`` installed from cygwin. e.g.
 
 To build a 32-bit x86 binary, simply use an ``x86 Native Tools
 Command Prompt`` instead of ``x64``.
-
-Using sccache to Speed up Builds
-================================
-
-Builds can take a long time.
-
-python-build-standalone can automatically detect and use the
-`sccache <https://github.com/mozilla/sccache>`_ compiler cache to speed
-up subsequent builds on UNIX-like platforms. ``sccache`` can shave dozens
-of minutes from fresh builds, even on a 16 core CPU!
-
-If there is an executable ``sccache`` in the source directory, it will
-automatically be copied into the build environment and used. For non-container
-builds, an ``sccache`` executable is also searched for on ``PATH``.
-
-The ``~/.python-build-standalone-env`` file is read if it exists (the format is
-``key=value`` pairs) and variables are added to the build environment.
-
-In addition, environment variables ``AWS_ACCESS_KEY_ID``,
-``AWS_SECRET_ACCESS_KEY``, and any variable beginning with ``SCCACHE_`` are
-automatically added to the build environment.
-
-The environment variable support enables you to define remote build caches
-(such as S3 buckets) to provide a persistent, shared cache across builds and
-machines.
-
-Keep in mind that when performing builds in containers in Linux (the default
-behavior), the local filesystem is local to the container and does not survive
-the build of a single package. So sccache is practically meaningless unless
-configured to use an external store (such as S3).
-
-When using remote stores (such as S3), ``sccache`` can be constrained on
-network I/O. We recommend having at least a 100mbps network connection to
-a remote store and employing a network store with as little latency as possible
-for best results.
diff --git a/pythonbuild/utils.py b/pythonbuild/utils.py
index 3df0f783..a8132ca8 100644
--- a/pythonbuild/utils.py
+++ b/pythonbuild/utils.py
@@ -570,17 +570,6 @@ def add_env_common(env):
     except FileNotFoundError:
         pass
 
-    # Proxy sccache settings.
-    for k, v in os.environ.items():
-        if k.startswith("SCCACHE_"):
-            env[k] = v
-
-    # Proxy cloud provider credentials variables to enable sccache to
-    # use stores in those providers.
-    for k in ("AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY"):
-        if k in os.environ:
-            env[k] = os.environ[k]
-
 
 def exec_and_log(args, cwd, env):
     p = subprocess.Popen(
diff --git a/src/github.rs b/src/github.rs
index 8a432841..0d3bc971 100644
--- a/src/github.rs
+++ b/src/github.rs
@@ -209,7 +209,7 @@ pub async fn command_fetch_release_distributions(args: &ArgMatches) -> Result<()
         for artifact in artifacts {
             if matches!(
                 artifact.name.as_str(),
-                "pythonbuild" | "sccache" | "toolchain"
+                "pythonbuild" | "toolchain"
             ) || artifact.name.contains("install-only")
             {
                 continue;

From d786b162934d10f8ed1e05e9501fd22801aaad51 Mon Sep 17 00:00:00 2001
From: Geoffrey Thomas <geofft@ldpreload.com>
Date: Thu, 29 May 2025 11:51:17 -0400
Subject: [PATCH 097/157] Update quirks doc to match current reality (#625)

We configure ncurses with defaults for TERMINFO_DIRS that work on I can
find (it works on Debian family, Red Hat family, NixOS, and Alpine), so
we shouldn't phrase either the title or the body as if this is a problem
that affects most people or setting the environment variable is a
necessary thing in general. (Also I think even in cases where we don't
have terminfo for your terminal, backspace usually still works, as
evidenced by `TERM=potato python`).

musl distributions are now dynamic binaries by default and dynamic
loading works.

The libcrypt transition is behind us.

The python3-config file (since its first version, I think) knows how to
correct the prefix in output. While it does contain hard-coded paths
internally, it uses that for the purpose of fixing its output, so I
don't think that fact is helpful to call out.

python-build-standalone users who get it through uv are (hopefully) not
affected by absolute paths in sysconfig; call this out explicitly for
the benefit of people evaluting whether uv will work for them. Also
mention sysconfigpatcher for everyone else.

In general, tighten up the content.
---
 docs/quirks.rst | 219 ++++++++++++++++++------------------------------
 1 file changed, 83 insertions(+), 136 deletions(-)

diff --git a/docs/quirks.rst b/docs/quirks.rst
index aeb8ec57..8900cd6a 100644
--- a/docs/quirks.rst
+++ b/docs/quirks.rst
@@ -4,17 +4,21 @@
 Behavior Quirks
 ===============
 
+While these Python distributions are intended to be broadly compatible
+with the Python ecosystem, there are a few known behavior quirks that
+affect specific environments, packages, or use cases.
+
 .. _quirk_backspace_key:
 
-Backspace Key Doesn't work in Python REPL
-=========================================
+If special keys do not work in the Python REPL
+==============================================
 
 If you attempt to run ``python`` and the backspace key doesn't
 erase characters or the arrow keys don't work as expected, this
 is because the executable can't find the *terminfo database*.
 
-A telltale sign of this is the Python REPL printing the following
-on startup::
+If this happens, the Python REPL will print the following warning
+message on startup::
 
    Cannot read termcap database;
    using dumb terminal settings.
@@ -35,42 +39,27 @@ you build a program (like Python) locally, you link against
 ``readline`` or ``libedit`` and get these default locations
 *for free*.
 
-Because python-build-standalone Python distributions compile
-and use their own version of ``libedit`` and because the build
-environment is different from your machine, the default search
-locations for the *terminfo database* built into binaries
-distributed with this project may point to a path that doesn't
-exist. The *terminfo database* cannot be located and ``libedit``
-does not know how to convert special key presses to special behavior.
-
-The solution to this is to set an environment variable
-with the location of the *terminfo database*.
-
-If running a Debian based Linux distribution (including Ubuntu)::
-
-   $ TERMINFO_DIRS=/etc/terminfo:/lib/terminfo:/usr/share/terminfo
-
-If running a RedHat based Linux distribution::
-
-   $ TERMINFO_DIRS=/etc/terminfo:/usr/share/terminfo
-
-If running macOS::
-
-   $ TERMINFO_DIRS=/usr/share/terminfo
-
-e.g.::
+These Python distributions compile and use their own version of
+``libedit`` to avoid a dependency on what is (or isn't) installed on
+your system. This means that they do not use your system-provided
+libraries for reading the *terminfo database*.  This version of
+``libedit`` is configured to look for in locations that should work for
+most OSes (specifically, ``/usr/share/terminfo`` on macOS, and
+``/etc/terminfo``, ``/lib/terminfo``, and ``/usr/share/terminfo`` on
+Linux, which should cover all major Linux distributions), but it is
+possible that your environment has it somewhere else. If your OS stores
+the *terminfo database* in an uncommon location, you can set the
+``TERMINFO_DIRS`` environment variable so that ``libedit`` can find it.
 
-   $ TERMINFO_DIRS=/etc/terminfo:/lib/terminfo:/usr/share/terminfo install/bin/python3.9
+For instance, you may need to do something like:
 
-The macOS distributions built with this project should automatically
-use the terminfo database in ``/usr/share/terminfo``. Please file
-a bug report if the macOS distributions do not behave as expected.
+   $ TERMINFO_DIRS=/uncommon/place/terminfo install/bin/python3.9
 
-Starting in the first release after 20240107, the Linux distributions are
-configured to automatically use the terminfo database in ``/etc/terminfo``,
-``/lib/terminfo``, and ``/usr/share/terminfo``.
+If you are running on a relatively standard OS and this does not work
+out of the box, please file a bug report so we can add the location of
+the *terminfo database* to the build.
 
-Also starting in the first release after 20240107, the terminfo database
+For convenience, a relatively recent copy of the terminfo database
 is distributed in the ``share/terminfo`` directory (``../../share/terminfo``
 relative to the ``bin/python3`` executable) in Linux distributions. Note
 that ncurses and derived libraries don't know how to find this directory
@@ -150,29 +139,6 @@ Some functionality may behave subtly differently as a result of our choice
 to link ``libedit`` by default. (We choose ``libedit`` by default to
 avoid GPL licensing requirements of ``readline``.)
 
-Static Linking of musl libc Prevents Extension Module Library Loading
-=====================================================================
-
-Our musl libc linked Linux builds link musl libc statically and the resulting
-binaries are completely static and don't have any external dependencies.
-
-Due to how Linux/ELF works, a static/non-dynamic binary cannot call
-``dlopen()`` and therefore it cannot load shared library based Python
-extension modules (``.so`` based extension modules). This significantly
-limits the utility of these Python distributions. (If you want to use
-additional extension modules you can use the build artifacts in the
-distributions to construct a new ``libpython`` with the additional
-extension modules configured as builtin extension modules.)
-
-Another consequence of statically linking musl libc is that our musl
-distributions aren't compatible with
-`PEP 656 <https://www.python.org/dev/peps/pep-0656/>`_. PEP 656
-stipulates that Python and extension modules are linked against a
-dynamic musl. This is what you'll find in Alpine Linux, for example.
-
-See https://github.com/astral-sh/python-build-standalone/issues/86 for
-a tracking issue to improve the state of musl distributions.
-
 .. _quirk_linux_libx11:
 
 Static Linking of ``libX11`` / Incompatibility with PyQt on Linux
@@ -232,40 +198,6 @@ And you can't easily remove ``_tkinter`` and its symbols from the pre-built
 and ready-to-use Python install included in this project's distribution
 artifacts.
 
-.. _quirk_missing_libcrypt:
-
-Missing ``libcrypt.so.1``
-=========================
-
-Linux distributions in the 20230507 release and earlier had a hard dependency
-on ``libcrypt.so.1`` due to static linking of the ``_crypt`` extension module,
-which imports it.
-
-Presence of ``libcrypt.so.1`` is mandated as part of the Linux Standard Base
-Core Specification and therefore should be present in Linux environments
-conforming to this specification. Most Linux distributions historically
-attempted to conform to this specification.
-
-In 2022, various Linux distributions stopped shipping ``libcrypt.so.1``
-(it appears glibc is ceasing to provide this functionality and Linux
-distributions aren't backfilling ``libcrypt.so.1`` in the base install
-to remain compatible with the Linux Standard Base Core Specification).
-
-In reaction to Linux distributions no longer providing ``libcrypt.so.1`` by
-default, we changed the configuration of the ``_crypt`` extension module so
-it is compiled/distributed as a standalone shared library and not compiled
-into libpython. This means a missing ``libcrypt.so.1`` is only relevant if
-the Python interpreter imports the ``crypt`` / ``_crypt`` modules.
-
-If you are using an older release of this project with a hard dependency
-on ``libcrypt.so.1`` and don't want to upgrade, you can instruct end-users
-to install a ``libxcrypt-compat`` (or comparable) package to provide the
-missing ``libcrypt.so.1``.
-
-See https://github.com/astral-sh/python-build-standalone/issues/113 and
-https://github.com/astral-sh/python-build-standalone/issues/173 for additional
-context on this matter.
-
 .. _quirk_references_to_build_paths:
 
 References to Build-Time Paths
@@ -278,8 +210,8 @@ build-time configuration in a handful of files:
   ``lib/python3.10/_sysconfigdata__linux_x86_64-linux-gnu.py``.
 * In a ``Makefile`` under a ``config-*`` directory in the standard library.
   e.g. ``lib/python3.10/config-3.10-x86_64-linux-gnu/Makefile``.
-* In ``python*-config`` files. e.g. ``bin/python3.10-config``.
-* In ``PYTHON.json`` (mostly reflected values from ``_sysconfigdata_*.py``.
+* In python-build-standalone's metadata file ``PYTHON.json`` (mostly
+  reflected values from ``_sysconfigdata_*.py``).
 
 Each of these serves a different use case. But the general theme is various
 aspects of the Python distribution attempt to capture how Python was built.
@@ -290,47 +222,62 @@ module. ``sysconfig`` in turn is used by packaging tools like ``setuptools``
 and ``pip`` to figure out how to invoke a compiler for e.g. compiling C
 extensions from source.
 
-On Linux, our distributions are built in containers. The container has a
-custom build of Clang in a custom filesystem location. And Python is
-installed to the prefix ``/install``. So you may see references to
-``/install`` in Linux distributions.
-
-On macOS, most distributions are built from GitHub Actions runners. They
-use a specific macOS SDK. So you may see references to SDK paths that don't
-exist on your machine. e.g.
-``/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.3.sdk``.
-
-On Windows, builds are performed from a temporary directory. So you may
-see references to temporary directories in Windows distributions.
-
-**The existence of hard-coded paths in our produced distributions can confuse
-consumers of these values and break common workflows, like compiling C
-extensions.**
-
-We don't currently have a great idea for how to solve this problem. We
-can't hardcode values that will work on every machine because every machine
-has different filesystem layouts. For example, if we hardcode ``gcc`` as
-the compiler, someone with only ``clang`` installed will complain. And
-we certainly don't know where end-users will extract their Python
-distribution to!
-
-To solve this problem requires executing dynamic code after extracting
-our custom distributions in order to patch these hardcoded values into
-conformance with the new machine. We're unsure how to actually do this
-because figuring out what values to set is essentially equivalent to
-reinventing autoconf / configure! Perhaps we could implement something
-that works in common system layouts (e.g. hardcoded defaults for common
-distros like Debian/Ubuntu and RedHat).
-
-Until we have a better solution here, just understand that anything looking
-at ``sysconfig`` could resolve non-existent paths or names of binaries that
-don't exist on the current machine.
-
-Starting with the Linux and macOS distributions released in 2024, we do
-normalize some values in these files at build time. Normalizations include:
-
-* Removing compiler flags that are non-portable.
-* Removing references to build paths (e.g. ``/tools`` on Linux).
+When installed by `uv <https://docs.astral.sh/uv/>`_, these absolute
+paths are fixed up to point to the actual location on your system where
+the distribution was installed, so **this quirk generally does not
+affect uv users**.  The third-party tool `sysconfigpatcher
+<https://github.com/bluss/sysconfigpatcher>`_ also does this and might
+be helpful to use or reference if you are installing these distributions
+on your own.
+
+In particular, you may see references to our install-time paths on the
+build infrastructure, e.g., ``/build`` and ``/install`` on Linux, a
+particular SDK in ``/Applications/Xcode.app`` on macOS, and temporary
+directories on Windows.
+
+Also, Python reports the compiler and flags in use, just in case it is
+needed to make binary-compatible extensions. On Linux, for instance, we
+use our own builds of Clang and potentially some flags (warnings,
+optimizations, locations of the build environment) that do not work or
+apply in other environments.  We try to configure Python to remove
+unneeded flags and absolute paths to files in the build environment.
+references to build-time paths.  Python's ``sysconfig`` system requires
+listing a compiler, so we leave it set to ``clang`` without the absolute
+path, but you should be able to use another compiler like ``gcc`` to
+compile extensions, too.
 
 If there is a build time normalization that you think should be performed to
 make distributions more portable, please file a GitHub issue.
+
+.. _quirk_former:
+.. _quirk_missing_libcrypt:
+
+Former quirks
+=============
+
+The following quirks were previously listed on this page but have since
+been resolved.
+
+* "Static Linking of musl libc Prevents Extension Module Library
+  Loading": Starting with the 20250311 release, the default musl
+  distributions are dynamically linked by default, so extension modules
+  should work properly. Note that these now require a system-wide
+  installation of the musl C library. (This is present by default on
+  musl-based OSes like Alpine, and many glibc-based distros have a
+  ``musl`` package you can safely co-install with glibc, too.) If you
+  specifically need a statically-linked binary, variants with the
+  ``+static`` build option are available, but these retain the quirk
+  that compiled extension modules (e.g., ``musllinux`` wheels) cannot be
+  loaded.
+
+* "Missing ``libcrypt.so.1``": The 20230507 release and earlier required
+  the system library ``libcrypt.so.1``, which stopped being shipped by
+  default in several Linux distributions around 2022. Starting with the
+  20230726 release, this dependency is now only needed by the deprecated
+  ``crypt`` module, which only exists on Python 3.12 and lower. If you
+  still need this module, your OS may offer a ``libxcrypt`` package to
+  provide this library. Alternatively, there are suggestions in `What's
+  New in Python 3.13`_ about third-party replacements for the ``crypt``
+  module.
+
+.. _What's New in Python 3.13: https://docs.python.org/3/whatsnew/3.13.html#whatsnew313-pep594

From 10218de12a3c61c5e959f24b83b9844626dc1237 Mon Sep 17 00:00:00 2001
From: Geoffrey Thomas <geofft@ldpreload.com>
Date: Fri, 30 May 2025 01:07:07 -0400
Subject: [PATCH 098/157] Specifically use DT_RPATH instead of DT_RUNPATH for
 the libpython hack (#623)

We need this to get inherited to dependent libraries, i.e., to extension
modules.
---
 cpython-unix/build-cpython.sh | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/cpython-unix/build-cpython.sh b/cpython-unix/build-cpython.sh
index fcf469ec..2463a02e 100755
--- a/cpython-unix/build-cpython.sh
+++ b/cpython-unix/build-cpython.sh
@@ -756,11 +756,11 @@ if [ "${PYBUILD_SHARED}" = "1" ]; then
         # empty dummy libpython.so, which allows the link to succeed but
         # ensures they do not use any unwanted symbols. That might be
         # worth doing at some point.)
-        patchelf --set-rpath "\$ORIGIN/../lib" \
+        patchelf --force-rpath --set-rpath "\$ORIGIN/../lib" \
             ${ROOT}/out/python/install/bin/python${PYTHON_MAJMIN_VERSION}
 
         if [ -n "${PYTHON_BINARY_SUFFIX}" ]; then
-            patchelf --set-rpath "\$ORIGIN/../lib" \
+            patchelf --force-rpath --set-rpath "\$ORIGIN/../lib" \
                 ${ROOT}/out/python/install/bin/python${PYTHON_MAJMIN_VERSION}${PYTHON_BINARY_SUFFIX}
         fi
 
@@ -777,7 +777,8 @@ if [ "${PYBUILD_SHARED}" = "1" ]; then
         # cases, we have no concerns/need no workarounds for code
         # referencing libpython3.x.so.1.0, because we are actually
         # dynamically linking it and so all code will get the real
-        # libpython3.x.so.1.0 that they want.
+	# libpython3.x.so.1.0 that they want (and it's fine to use
+	# DT_RUNPATH instead of DT_RPATH).
         if [ "${CC}" == "musl-clang" ]; then
             # libpython3.so isn't present in debug builds.
             if [ -z "${CPYTHON_DEBUG}" ]; then

From bb8404c33b0d15a61c18b0c4369e97fa46a64023 Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Fri, 30 May 2025 00:08:04 -0500
Subject: [PATCH 099/157] Use larger runner for releases (#615)

We were killed in
https://github.com/astral-sh/python-build-standalone/actions/runs/15085967950/job/42408534018
---
 .github/workflows/release.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index ce803392..aa2d3a70 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -29,7 +29,7 @@ jobs:
   release:
     env:
       GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-    runs-on: ubuntu-latest-large
+    runs-on: github-ubuntu-24.04-x86_64-16
     steps:
       - uses: actions/checkout@v4
         with:

From cddb9c19fcbb656b5cda420dcd6c3bf196e53beb Mon Sep 17 00:00:00 2001
From: Geoffrey Thomas <geofft@ldpreload.com>
Date: Fri, 30 May 2025 01:11:57 -0400
Subject: [PATCH 100/157] Disable unsafe identical code folding in BOLT (#622)

astral-sh/uv#13610 reported a misbehavior that is the result of a
subclass of str incorrectly having its ->tp_as_number->nb_add slot
filled in with the value of PyUnicode_Type->tp_as_sequence->sq_concat.
There are some times when this is an appropriate thing to do iwhen
subclassing, but this is not one of them. The logic to prevent it in
this case relies on two helper functions in the file, wrap_binaryfunc
and wrap_binaryfunc_l, having different addresses, even though they
contain identical code.

For some reason BOLT does not do this optimization in the shared library
(even though those are static functions and not exported), so we only
started seeing this in the static build.

BOLT in LLVM 20+ supports "safe" code folding, which uses heuristics about
relocations to determine whether a function's address is used in any way other
than a call. This seems to be enough to fix the issue. Add a patch to switch
to -icf=safe, submitted upstream as python/cpython#134642
---
 cpython-unix/build-cpython.sh                 |  6 ++
 .../patch-configure-bolt-icf-safe.patch       | 84 +++++++++++++++++++
 2 files changed, 90 insertions(+)
 create mode 100644 cpython-unix/patch-configure-bolt-icf-safe.patch

diff --git a/cpython-unix/build-cpython.sh b/cpython-unix/build-cpython.sh
index 2463a02e..b44bb971 100755
--- a/cpython-unix/build-cpython.sh
+++ b/cpython-unix/build-cpython.sh
@@ -274,6 +274,12 @@ if [ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_12}" ]; then
     # https://github.com/python/cpython/issues/128514
     patch -p1 -i ${ROOT}/patch-configure-bolt-apply-flags-128514.patch
 
+    # Disable unsafe identical code folding. Objects/typeobject.c
+    # update_one_slot requires that wrap_binaryfunc != wrap_binaryfunc_l,
+    # despite the functions being identical.
+    # https://github.com/python/cpython/pull/134642
+    patch -p1 -i ${ROOT}/patch-configure-bolt-icf-safe.patch
+
     # Tweak --skip-funcs to work with our toolchain.
     patch -p1 -i ${ROOT}/patch-configure-bolt-skip-funcs.patch
 fi
diff --git a/cpython-unix/patch-configure-bolt-icf-safe.patch b/cpython-unix/patch-configure-bolt-icf-safe.patch
new file mode 100644
index 00000000..1cc41adc
--- /dev/null
+++ b/cpython-unix/patch-configure-bolt-icf-safe.patch
@@ -0,0 +1,84 @@
+From 91fc5ae4a5a66a03931f8cd383abd2aa062bb0e9 Mon Sep 17 00:00:00 2001
+From: Geoffrey Thomas <geofft@ldpreload.com>
+Date: Sat, 24 May 2025 19:04:09 -0400
+Subject: [PATCH 1/1] Use only safe identical code folding with BOLT
+
+"Identical code folding" (ICF) is the feature of an optimizer to find that two
+functions have the same code and that they can therefore be deduplicated
+in the binary. While this is usually safe, it can cause observable
+behavior differences if the program relies on the fact that the two
+functions have different addresses.
+
+CPython relies on this in (at least) Objects/typeobject.c, which defines
+two functions wrap_binaryfunc() and wrap_binaryfunc_l() with the same
+implementation, and stores their addresses in the slotdefs array. If
+these two functions have the same address, update_one_slot() in that
+file will fill in slots it shouldn't, causing, for instances,
+classes defined in Python that inherit from some built-in types to
+misbehave.
+
+As of LLVM 20 (llvm/llvm-project#116275), BOLT has a "safe ICF" mode,
+where it looks to see if there are any uses of a function symbol outside
+function calls (e.g., relocations in data sections) and skips ICF on
+such functions. The intent is that this avoids observable behavior
+differences but still saves storage as much as possible.
+
+This version is about two months old at the time of writing. To support
+older LLVM versions, we have to turn off ICF entirely.
+
+This problem was previously noticed for Windows/MSVC in #53093 (and
+again in #24098), where the default behavior of PGO is to enable ICF
+(which they expand to "identical COMDAT folding") and we had to turn it
+off.
+---
+ configure    | 50 +++++++++++++++++++++++++++++++++++++++++++++++++-
+ configure.ac | 25 ++++++++++++++++++++++++-
+ 2 files changed, 73 insertions(+), 2 deletions(-)
+
+diff --git a/configure.ac b/configure.ac
+index 8d939f07505..25737e3f9d6 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -2129,6 +2129,29 @@ if test "$Py_BOLT" = 'true' ; then
+   else
+     AC_MSG_ERROR([merge-fdata is required for a --enable-bolt build but could not be found.])
+   fi
++
++  py_bolt_icf_flag="-icf=safe"
++  AC_CACHE_CHECK(
++    [whether ${LLVM_BOLT} supports safe identical code folding],
++    [py_cv_bolt_icf_safe],
++    [
++      saved_cflags="$CFLAGS"
++      saved_ldflags="$LDFLAGS"
++      CFLAGS="$CFLAGS_NODIST"
++      LDFLAGS="$LDFLAGS_NODIST"
++      AC_LINK_IFELSE(
++        [AC_LANG_PROGRAM([[]], [[]])],
++        [py_cv_bolt_icf_safe=no
++         ${LLVM_BOLT} -icf=safe -o conftest.bolt conftest$EXEEXT >&AS_MESSAGE_LOG_FD 2>&1 dnl
++         && py_cv_bolt_icf_safe=yes],
++        [AC_MSG_FAILURE([could not compile empty test program])])
++      CFLAGS="$saved_cflags"
++      LDFLAGS="$saved_ldflags"
++    ]
++  )
++  if test "$py_cv_bolt_icf_safe" = no; then
++    py_bolt_icf_flag=""
++  fi
+ fi
+ 
+ dnl Enable BOLT of libpython if built.
+@@ -2184,7 +2207,7 @@ then
+      -reorder-blocks=ext-tsp
+      -reorder-functions=cdsort
+      -split-functions
+      -split-strategy=cdsplit
+-     -icf=1
++     ${py_bolt_icf_flag}
+      -inline-all
+      -split-eh
+      -reorder-functions-use-hot-size
+-- 
+2.39.5 (Apple Git-154)
+

From c7bc21c1d4b1fc687378c0ab341c9d234cb90436 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Fri, 30 May 2025 07:44:17 -0500
Subject: [PATCH 101/157] Bump the python group with 21 updates (#632)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Bumps the python group with 21 updates:

| Package | From | To |
| --- | --- | --- |
| [attrs](https://github.com/sponsors/hynek) | `23.2.0` | `25.3.0` |
| [certifi](https://github.com/certifi/python-certifi) | `2024.7.4` |
`2025.4.26` |
| [charset-normalizer](https://github.com/jawah/charset_normalizer) |
`3.3.2` | `3.4.2` |
| [docker](https://github.com/docker/docker-py) | `7.0.0` | `7.1.0` |
| [idna](https://github.com/kjd/idna) | `3.6` | `3.10` |
| [jsonschema](https://github.com/python-jsonschema/jsonschema) |
`4.21.1` | `4.24.0` |
|
[jsonschema-specifications](https://github.com/python-jsonschema/jsonschema-specifications)
| `2023.12.1` | `2025.4.1` |
| [markupsafe](https://github.com/pallets/markupsafe) | `2.1.5` |
`3.0.2` |
| [packaging](https://github.com/pypa/packaging) | `23.2` | `25.0` |
| [pywin32](https://github.com/mhammond/pywin32) | `308` | `310` |
| [referencing](https://github.com/python-jsonschema/referencing) |
`0.33.0` | `0.36.2` |
| [requests](https://github.com/psf/requests) | `2.32.2` | `2.32.3` |
| [rpds-py](https://github.com/crate-py/rpds) | `0.18.0` | `0.25.1` |
| [six](https://github.com/benjaminp/six) | `1.16.0` | `1.17.0` |
| [tomli](https://github.com/hukkin/tomli) | `2.0.1` | `2.2.1` |
| [urllib3](https://github.com/urllib3/urllib3) | `2.2.2` | `2.4.0` |
| [zstandard](https://github.com/indygreg/python-zstandard) | `0.22.0` |
`0.23.0` |
| [mypy](https://github.com/python/mypy) | `1.8.0` | `1.15.0` |
| [ruff](https://github.com/astral-sh/ruff) | `0.3.4` | `0.11.11` |
| [types-jsonschema](https://github.com/typeshed-internal/stub_uploader)
| `4.21.0.20240118` | `4.23.0.20250516` |
| [types-pyyaml](https://github.com/typeshed-internal/stub_uploader) |
`6.0.12.12` | `6.0.12.20250516` |

Updates `attrs` from 23.2.0 to 25.3.0
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a
href="https://github.com/sponsors/hynek/commits">compare view</a></li>
</ul>
</details>
<br />

Updates `certifi` from 2024.7.4 to 2025.4.26
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/certifi/python-certifi/commit/275c9eb55733a464589c15fb4566fddd4598e5b2"><code>275c9eb</code></a>
2025.04.26 (<a
href="https://redirect.github.com/certifi/python-certifi/issues/347">#347</a>)</li>
<li><a
href="https://github.com/certifi/python-certifi/commit/37883310b51e56570919cdc2d44becc1c6940559"><code>3788331</code></a>
Bump actions/setup-python from 5.4.0 to 5.5.0 (<a
href="https://redirect.github.com/certifi/python-certifi/issues/346">#346</a>)</li>
<li><a
href="https://github.com/certifi/python-certifi/commit/9d1f1b782000baedf57026de5b79e193bcb7ef7b"><code>9d1f1b7</code></a>
Bump actions/download-artifact from 4.1.9 to 4.2.1 (<a
href="https://redirect.github.com/certifi/python-certifi/issues/344">#344</a>)</li>
<li><a
href="https://github.com/certifi/python-certifi/commit/96b97a5afe26bc1adef98cb0bfe68e34948a73b6"><code>96b97a5</code></a>
Bump actions/upload-artifact from 4.6.1 to 4.6.2 (<a
href="https://redirect.github.com/certifi/python-certifi/issues/343">#343</a>)</li>
<li><a
href="https://github.com/certifi/python-certifi/commit/c054ed3ac3d3505efc929b71cfd87a257bbdb6b3"><code>c054ed3</code></a>
Bump peter-evans/create-pull-request from 7.0.7 to 7.0.8 (<a
href="https://redirect.github.com/certifi/python-certifi/issues/342">#342</a>)</li>
<li><a
href="https://github.com/certifi/python-certifi/commit/44547fc77121b12bb276b44b3b2b49cfcbeac06f"><code>44547fc</code></a>
Bump actions/download-artifact from 4.1.8 to 4.1.9 (<a
href="https://redirect.github.com/certifi/python-certifi/issues/341">#341</a>)</li>
<li><a
href="https://github.com/certifi/python-certifi/commit/5ea51247afecf1bf4ebfa8f2db3082e89a8bfaed"><code>5ea5124</code></a>
Bump actions/upload-artifact from 4.6.0 to 4.6.1 (<a
href="https://redirect.github.com/certifi/python-certifi/issues/340">#340</a>)</li>
<li><a
href="https://github.com/certifi/python-certifi/commit/2f142b7ae0b2d13fee4ba4b9fbd73a9cd5069060"><code>2f142b7</code></a>
Bump peter-evans/create-pull-request from 7.0.6 to 7.0.7 (<a
href="https://redirect.github.com/certifi/python-certifi/issues/339">#339</a>)</li>
<li><a
href="https://github.com/certifi/python-certifi/commit/80d2ebdc77d2d005f408f789fe2fb1fe5f4e0265"><code>80d2ebd</code></a>
Bump actions/setup-python from 5.3.0 to 5.4.0 (<a
href="https://redirect.github.com/certifi/python-certifi/issues/337">#337</a>)</li>
<li><a
href="https://github.com/certifi/python-certifi/commit/088f93122ea7c91cfdaeea7fa76ab2f850b8064d"><code>088f931</code></a>
2025.01.31 (<a
href="https://redirect.github.com/certifi/python-certifi/issues/336">#336</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/certifi/python-certifi/compare/2024.07.04...2025.04.26">compare
view</a></li>
</ul>
</details>
<br />

Updates `charset-normalizer` from 3.3.2 to 3.4.2
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/jawah/charset_normalizer/releases">charset-normalizer's
releases</a>.</em></p>
<blockquote>
<h2>Version 3.4.2</h2>
<h2><a
href="https://github.com/Ousret/charset_normalizer/compare/3.4.1...3.4.2">3.4.2</a>
(2025-05-02)</h2>
<h3>Fixed</h3>
<ul>
<li>Addressed the DeprecationWarning in our CLI regarding
<code>argparse.FileType</code> by backporting the target class into the
package. (<a
href="https://redirect.github.com/jawah/charset_normalizer/issues/591">#591</a>)</li>
<li>Improved the overall reliability of the detector with CJK
Ideographs. (<a
href="https://redirect.github.com/jawah/charset_normalizer/issues/605">#605</a>)
(<a
href="https://redirect.github.com/jawah/charset_normalizer/issues/587">#587</a>)</li>
</ul>
<h3>Changed</h3>
<ul>
<li>Optional mypyc compilation upgraded to version 1.15 for Python &gt;=
3.9</li>
</ul>
<h2>Version 3.4.1</h2>
<h2>🚀 We're still raising awareness around HTTP/2, and HTTP/3!</h2>
<p>Did you know that Internet Explorer 11 shipped with an optional
HTTP/2 support back in 2013? also libcurl did ship it in 2014[...]
Using Requests today is the rough equivalent of using EOL Windows 8! We
promptly invite Python developers to look at the first drop-in
replacement for Requests, <a
href="https://github.com/jawah/niquests">namely Niquests</a>. Ship with
native WebSocket, SSE, Happy Eyeballs, DNS over HTTPS, and so on[...]
All of this while remaining compatible with all Requests prior plug-ins
/ add-ons.</p>
<p>It leverages charset-normalizer in a better way! Check it out, you
will gain up to being 3X faster and get a real/respectable support with
it.</p>
<h2><a
href="https://github.com/Ousret/charset_normalizer/compare/3.4.0...3.4.1">3.4.1</a>
(2024-12-24)</h2>
<h3>Changed</h3>
<ul>
<li>Project metadata are now stored using <code>pyproject.toml</code>
instead of <code>setup.cfg</code> using setuptools as the build
backend.</li>
<li>Enforce annotation delayed loading for a simpler and consistent
types in the project.</li>
<li>Optional mypyc compilation upgraded to version 1.14 for Python &gt;=
3.8</li>
</ul>
<h3>Added</h3>
<ul>
<li>pre-commit configuration.</li>
<li>noxfile.</li>
</ul>
<h3>Removed</h3>
<ul>
<li><code>build-requirements.txt</code> as per using
<code>pyproject.toml</code> native build configuration.</li>
<li><code>bin/integration.py</code> and <code>bin/serve.py</code> in
favor of downstream integration test (see noxfile).</li>
<li><code>setup.cfg</code> in favor of <code>pyproject.toml</code>
metadata configuration.</li>
<li>Unused <code>utils.range_scan</code> function.</li>
</ul>
<h3>Fixed</h3>
<ul>
<li>Converting content to Unicode bytes may insert <code>utf_8</code>
instead of preferred <code>utf-8</code>. (<a
href="https://redirect.github.com/jawah/charset_normalizer/issues/572">#572</a>)</li>
<li>Deprecation warning &quot;'count' is passed as positional
argument&quot; when converting to Unicode bytes on Python 3.13+</li>
</ul>
<h2>Version 3.4.0</h2>
<h2>🚀 charset-normalizer is raising awareness around HTTP/2, and
HTTP/3!</h2>
<p>Did you know that Internet Explorer 11 shipped with an optional
HTTP/2 support back in 2013? also libcurl did ship it in 2014[...]
All of this while our community is still struggling to make a firm
advancement in HTTP clients. Now, many of you use Requests
as the defacto http client, now, and for many years now, Requests has
been frozen. Being left in a vegetative state and not evolving,
this blocked millions of developers from using more advanced
features.</p>
<p>We promptly invite Python developers to look at the drop-in
replacement for Requests, <a
href="https://github.com/jawah/niquests">namely Niquests</a>.
It leverage charset-normalizer in a better way! Check it out, you will
be positively surprised! Don't wait another decade.</p>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/jawah/charset_normalizer/blob/master/CHANGELOG.md">charset-normalizer's
changelog</a>.</em></p>
<blockquote>
<h2><a
href="https://github.com/Ousret/charset_normalizer/compare/3.4.1...3.4.2">3.4.2</a>
(2025-05-02)</h2>
<h3>Fixed</h3>
<ul>
<li>Addressed the DeprecationWarning in our CLI regarding
<code>argparse.FileType</code> by backporting the target class into the
package. (<a
href="https://redirect.github.com/jawah/charset_normalizer/issues/591">#591</a>)</li>
<li>Improved the overall reliability of the detector with CJK
Ideographs. (<a
href="https://redirect.github.com/jawah/charset_normalizer/issues/605">#605</a>)
(<a
href="https://redirect.github.com/jawah/charset_normalizer/issues/587">#587</a>)</li>
</ul>
<h3>Changed</h3>
<ul>
<li>Optional mypyc compilation upgraded to version 1.15 for Python &gt;=
3.8</li>
</ul>
<h2><a
href="https://github.com/Ousret/charset_normalizer/compare/3.4.0...3.4.1">3.4.1</a>
(2024-12-24)</h2>
<h3>Changed</h3>
<ul>
<li>Project metadata are now stored using <code>pyproject.toml</code>
instead of <code>setup.cfg</code> using setuptools as the build
backend.</li>
<li>Enforce annotation delayed loading for a simpler and consistent
types in the project.</li>
<li>Optional mypyc compilation upgraded to version 1.14 for Python &gt;=
3.8</li>
</ul>
<h3>Added</h3>
<ul>
<li>pre-commit configuration.</li>
<li>noxfile.</li>
</ul>
<h3>Removed</h3>
<ul>
<li><code>build-requirements.txt</code> as per using
<code>pyproject.toml</code> native build configuration.</li>
<li><code>bin/integration.py</code> and <code>bin/serve.py</code> in
favor of downstream integration test (see noxfile).</li>
<li><code>setup.cfg</code> in favor of <code>pyproject.toml</code>
metadata configuration.</li>
<li>Unused <code>utils.range_scan</code> function.</li>
</ul>
<h3>Fixed</h3>
<ul>
<li>Converting content to Unicode bytes may insert <code>utf_8</code>
instead of preferred <code>utf-8</code>. (<a
href="https://redirect.github.com/jawah/charset_normalizer/issues/572">#572</a>)</li>
<li>Deprecation warning &quot;'count' is passed as positional
argument&quot; when converting to Unicode bytes on Python 3.13+</li>
</ul>
<h2><a
href="https://github.com/Ousret/charset_normalizer/compare/3.3.2...3.4.0">3.4.0</a>
(2024-10-08)</h2>
<h3>Added</h3>
<ul>
<li>Argument <code>--no-preemptive</code> in the CLI to prevent the
detector to search for hints.</li>
<li>Support for Python 3.13 (<a
href="https://redirect.github.com/jawah/charset_normalizer/issues/512">#512</a>)</li>
</ul>
<h3>Fixed</h3>
<ul>
<li>Relax the TypeError exception thrown when trying to compare a
CharsetMatch with anything else than a CharsetMatch.</li>
<li>Improved the general reliability of the detector based on user
feedbacks. (<a
href="https://redirect.github.com/jawah/charset_normalizer/issues/520">#520</a>)
(<a
href="https://redirect.github.com/jawah/charset_normalizer/issues/509">#509</a>)
(<a
href="https://redirect.github.com/jawah/charset_normalizer/issues/498">#498</a>)
(<a
href="https://redirect.github.com/jawah/charset_normalizer/issues/407">#407</a>)
(<a
href="https://redirect.github.com/jawah/charset_normalizer/issues/537">#537</a>)</li>
<li>Declared charset in content (preemptive detection) not changed when
converting to utf-8 bytes. (<a
href="https://redirect.github.com/jawah/charset_normalizer/issues/381">#381</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/jawah/charset_normalizer/commit/6422af1d50f1f46624deab585424e1ac4d08ba94"><code>6422af1</code></a>
:pencil: update release date</li>
<li><a
href="https://github.com/jawah/charset_normalizer/commit/0e60ec18eb00bfe312dde86739929165839b633c"><code>0e60ec1</code></a>
:bookmark: Release 3.4.2 (<a
href="https://redirect.github.com/jawah/charset_normalizer/issues/614">#614</a>)</li>
<li><a
href="https://github.com/jawah/charset_normalizer/commit/f6630ce3b7fd34f234759a0c7a5ca413640e8ffb"><code>f6630ce</code></a>
:arrow_up: Bump pypa/cibuildwheel from 2.23.2 to 2.23.3 (<a
href="https://redirect.github.com/jawah/charset_normalizer/issues/617">#617</a>)</li>
<li><a
href="https://github.com/jawah/charset_normalizer/commit/677c99953f1a728de9f88d8659abff1246a80ade"><code>677c999</code></a>
:arrow_up: Bump actions/download-artifact from 4.2.1 to 4.3.0 (<a
href="https://redirect.github.com/jawah/charset_normalizer/issues/618">#618</a>)</li>
<li><a
href="https://github.com/jawah/charset_normalizer/commit/960ab1e676b7ef73c8c4f36c387b5a0da21e01c0"><code>960ab1e</code></a>
:arrow_up: Bump actions/setup-python from 5.5.0 to 5.6.0 (<a
href="https://redirect.github.com/jawah/charset_normalizer/issues/619">#619</a>)</li>
<li><a
href="https://github.com/jawah/charset_normalizer/commit/6eb632521c9b3f92df2cd944c7c524c205abfffc"><code>6eb6325</code></a>
:arrow_up: Bump github/codeql-action from 3.28.10 to 3.28.16 (<a
href="https://redirect.github.com/jawah/charset_normalizer/issues/620">#620</a>)</li>
<li><a
href="https://github.com/jawah/charset_normalizer/commit/c99c0f2c33ce54e41fefcae1c4fb96fa901d5cd4"><code>c99c0f2</code></a>
:arrow_up: Update coverage requirement from &lt;7.7,&gt;=7.2.7 to
&gt;=7.2.7,&lt;7.9 (<a
href="https://redirect.github.com/jawah/charset_normalizer/issues/606">#606</a>)</li>
<li><a
href="https://github.com/jawah/charset_normalizer/commit/270f28e474db75f2a5085d6da732a90c2ac338f4"><code>270f28e</code></a>
:arrow_up: Bump actions/setup-python from 5.4.0 to 5.5.0 (<a
href="https://redirect.github.com/jawah/charset_normalizer/issues/607">#607</a>)</li>
<li><a
href="https://github.com/jawah/charset_normalizer/commit/d4d89a092d262a37ce427ee39ba5091ffd188f0b"><code>d4d89a0</code></a>
:arrow_up: Bump pypa/cibuildwheel from 2.22.0 to 2.23.2 (<a
href="https://redirect.github.com/jawah/charset_normalizer/issues/608">#608</a>)</li>
<li><a
href="https://github.com/jawah/charset_normalizer/commit/905fcf5cbe93e8b59c12103217434bdbc703d105"><code>905fcf5</code></a>
:arrow_up: Bump slsa-framework/slsa-github-generator from 2.0.0 to 2.1.0
(<a
href="https://redirect.github.com/jawah/charset_normalizer/issues/609">#609</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/jawah/charset_normalizer/compare/3.3.2...3.4.2">compare
view</a></li>
</ul>
</details>
<br />

Updates `docker` from 7.0.0 to 7.1.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/docker/docker-py/releases">docker's
releases</a>.</em></p>
<blockquote>
<h2>7.1.0</h2>
<h2>Upgrade Notes</h2>
<ul>
<li>Bumped minimum engine API version to 1.24</li>
<li>Bumped default engine API version to 1.44 (Moby 25.0)</li>
</ul>
<h2>Bugfixes</h2>
<ul>
<li>Fixed issue with tag parsing when the registry address includes
ports that resulted in <code>invalid tag format</code> errors</li>
<li>Fixed issue preventing creating new configs
(<code>ConfigCollection</code>), which failed with a
<code>KeyError</code> due to the <code>name</code> field</li>
<li>Fixed an issue due to an update in the <a
href="https://github.com/psf/requests">requests</a> package breaking
<code>docker-py</code> by applying the <a
href="https://redirect.github.com/psf/requests/pull/6710">suggested
fix</a></li>
</ul>
<h2>Miscellaneous</h2>
<ul>
<li>Documentation improvements</li>
<li>Updated Ruff (linter) and fixed minor linting issues</li>
<li>Packaging/CI updates
<ul>
<li>Started using hatch for packaging (<a
href="https://github.com/pypa/hatch">https://github.com/pypa/hatch</a>)</li>
<li>Updated <code>setup-python</code> github action</li>
</ul>
</li>
<li>Updated tests
<ul>
<li>Stopped checking for deprecated container and image related fields
(<code>Container</code> and <code>ContainerConfig</code>)</li>
<li>Updated tests that check
<code>NetworkSettings.Networks.&lt;network&gt;.Aliases</code> due to
engine changes</li>
</ul>
</li>
</ul>
<h2>What's Changed</h2>
<ul>
<li>Bump default API version to 1.43 (Moby 24.0) by <a
href="https://github.com/vvoland"><code>@​vvoland</code></a> in <a
href="https://redirect.github.com/docker/docker-py/pull/3199">docker/docker-py#3199</a></li>
<li>integration/commit: Don't check for deprecated fields by <a
href="https://github.com/vvoland"><code>@​vvoland</code></a> in <a
href="https://redirect.github.com/docker/docker-py/pull/3203">docker/docker-py#3203</a></li>
<li>fix: tag regex should allow ports by <a
href="https://github.com/artificial-intelligence"><code>@​artificial-intelligence</code></a>
in <a
href="https://redirect.github.com/docker/docker-py/pull/3196">docker/docker-py#3196</a></li>
<li>utils: Fix datetime_to_timestamp by <a
href="https://github.com/vvoland"><code>@​vvoland</code></a> in <a
href="https://redirect.github.com/docker/docker-py/pull/3208">docker/docker-py#3208</a></li>
<li>fix: keyerror when creating new config(<a
href="https://redirect.github.com/docker/docker-py/issues/3110">#3110</a>)
by <a href="https://github.com/Khushiyant"><code>@​Khushiyant</code></a>
in <a
href="https://redirect.github.com/docker/docker-py/pull/3200">docker/docker-py#3200</a></li>
<li>Update Ruff, fix some minor issues by <a
href="https://github.com/akx"><code>@​akx</code></a> in <a
href="https://redirect.github.com/docker/docker-py/pull/3206">docker/docker-py#3206</a></li>
<li>docs: change image.history() return type to list (<a
href="https://redirect.github.com/docker/docker-py/issues/3076">#3076</a>)
by <a href="https://github.com/Khushiyant"><code>@​Khushiyant</code></a>
in <a
href="https://redirect.github.com/docker/docker-py/pull/3202">docker/docker-py#3202</a></li>
<li>lint: fix string formatting by <a
href="https://github.com/milas"><code>@​milas</code></a> in <a
href="https://redirect.github.com/docker/docker-py/pull/3211">docker/docker-py#3211</a></li>
<li>Drop <code>packaging</code> dependency by <a
href="https://github.com/akx"><code>@​akx</code></a> in <a
href="https://redirect.github.com/docker/docker-py/pull/3205">docker/docker-py#3205</a></li>
<li>Bump default API version to 1.44 (Moby 25.0) by <a
href="https://github.com/vvoland"><code>@​vvoland</code></a> in <a
href="https://redirect.github.com/docker/docker-py/pull/3231">docker/docker-py#3231</a></li>
<li>Modernize build to use <code>hatchling</code> and
<code>hatch-vcs</code> by <a
href="https://github.com/akx"><code>@​akx</code></a> in <a
href="https://redirect.github.com/docker/docker-py/pull/3207">docker/docker-py#3207</a></li>
<li>Enable Ruff I (import sort), autofix by <a
href="https://github.com/akx"><code>@​akx</code></a> in <a
href="https://redirect.github.com/docker/docker-py/pull/3212">docker/docker-py#3212</a></li>
<li>chore(ci): fix-ups across Make / Docker / GitHub Actions by <a
href="https://github.com/milas"><code>@​milas</code></a> in <a
href="https://redirect.github.com/docker/docker-py/pull/3241">docker/docker-py#3241</a></li>
<li>chore: fix return type docs for <code>container.logs()</code> by <a
href="https://github.com/BobDu"><code>@​BobDu</code></a> in <a
href="https://redirect.github.com/docker/docker-py/pull/2240">docker/docker-py#2240</a></li>
<li>CI fix by <a
href="https://github.com/krissetto"><code>@​krissetto</code></a> in <a
href="https://redirect.github.com/docker/docker-py/pull/3260">docker/docker-py#3260</a></li>
<li>Fix for requests 2.32 by <a
href="https://github.com/felixfontein"><code>@​felixfontein</code></a>
in <a
href="https://redirect.github.com/docker/docker-py/pull/3257">docker/docker-py#3257</a></li>
<li>Added 7.1.0 changelog by <a
href="https://github.com/krissetto"><code>@​krissetto</code></a> in <a
href="https://redirect.github.com/docker/docker-py/pull/3262">docker/docker-py#3262</a></li>
<li>Fix env var name in release pipeline by <a
href="https://github.com/krissetto"><code>@​krissetto</code></a> in <a
href="https://redirect.github.com/docker/docker-py/pull/3263">docker/docker-py#3263</a></li>
<li>Change env var name in release pipeline to match hatch expectations
by <a href="https://github.com/krissetto"><code>@​krissetto</code></a>
in <a
href="https://redirect.github.com/docker/docker-py/pull/3264">docker/docker-py#3264</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/vvoland"><code>@​vvoland</code></a> made
their first contribution in <a
href="https://redirect.github.com/docker/docker-py/pull/3199">docker/docker-py#3199</a></li>
<li><a
href="https://github.com/artificial-intelligence"><code>@​artificial-intelligence</code></a>
made their first contribution in <a
href="https://redirect.github.com/docker/docker-py/pull/3196">docker/docker-py#3196</a></li>
<li><a
href="https://github.com/Khushiyant"><code>@​Khushiyant</code></a> made
their first contribution in <a
href="https://redirect.github.com/docker/docker-py/pull/3200">docker/docker-py#3200</a></li>
<li><a href="https://github.com/BobDu"><code>@​BobDu</code></a> made
their first contribution in <a
href="https://redirect.github.com/docker/docker-py/pull/2240">docker/docker-py#2240</a></li>
<li><a href="https://github.com/krissetto"><code>@​krissetto</code></a>
made their first contribution in <a
href="https://redirect.github.com/docker/docker-py/pull/3260">docker/docker-py#3260</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/docker/docker-py/compare/7.0.0...7.1.0">https://github.com/docker/docker-py/compare/7.0.0...7.1.0</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/docker/docker-py/commit/a3652028b1ead708bd9191efb286f909ba6c2a49"><code>a365202</code></a>
Merge pull request <a
href="https://redirect.github.com/docker/docker-py/issues/3264">#3264</a>
from krissetto/rename-env-var-in-release-pipeline</li>
<li><a
href="https://github.com/docker/docker-py/commit/1ab40c8e926c0b892b3ef47ae8acc274fc13f250"><code>1ab40c8</code></a>
Fix env var name in release pipeline to match hatch expectations</li>
<li><a
href="https://github.com/docker/docker-py/commit/b33088e0ca1bd40e45ad759a61cf084e9628043e"><code>b33088e</code></a>
Merge pull request <a
href="https://redirect.github.com/docker/docker-py/issues/3263">#3263</a>
from krissetto/fix-release-pipeline</li>
<li><a
href="https://github.com/docker/docker-py/commit/45488acfc1851c5b5358ec7d8030a754c5f23783"><code>45488ac</code></a>
Fix env var name in release pipeline</li>
<li><a
href="https://github.com/docker/docker-py/commit/20879eca6ae19ef406e918baa1e220aa37ba29a2"><code>20879ec</code></a>
Merge pull request <a
href="https://redirect.github.com/docker/docker-py/issues/3262">#3262</a>
from krissetto/changelog-7.1.0</li>
<li><a
href="https://github.com/docker/docker-py/commit/4f2a26d21e81774cbb8e025b01de001a3ac3a545"><code>4f2a26d</code></a>
Added 7.1.0 changelog</li>
<li><a
href="https://github.com/docker/docker-py/commit/7785ad913ddf2d86478f08278bb2c488d05a29ff"><code>7785ad9</code></a>
Merge pull request <a
href="https://redirect.github.com/docker/docker-py/issues/3257">#3257</a>
from felixfontein/requests-hotfix</li>
<li><a
href="https://github.com/docker/docker-py/commit/d8e9bcb2780607faf388f8832bff3865eb24dce0"><code>d8e9bcb</code></a>
requests 2.32.0 and 2.32.1 have been yanked.</li>
<li><a
href="https://github.com/docker/docker-py/commit/2a059a9f19c7b37c6c71c233754c6845e325d1ec"><code>2a059a9</code></a>
Extend fix to requests 2.32.2+.</li>
<li><a
href="https://github.com/docker/docker-py/commit/e33e0a437ecd895158c8cb4322a0cdad79312636"><code>e33e0a4</code></a>
Hotfix for requests 2.32.0.</li>
<li>Additional commits viewable in <a
href="https://github.com/docker/docker-py/compare/7.0.0...7.1.0">compare
view</a></li>
</ul>
</details>
<br />

Updates `idna` from 3.6 to 3.10
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/kjd/idna/releases">idna's
releases</a>.</em></p>
<blockquote>
<h2>v3.10</h2>
<p>No release notes provided.</p>
<h2>v3.9</h2>
<p>No release notes provided.</p>
<h2>v3.8</h2>
<h2>What's Changed</h2>
<ul>
<li>Fix regression where IDNAError exception was not being produced for
certain inputs.</li>
<li>Add support for Python 3.13, drop support for Python 3.5 as it is no
longer testable.</li>
<li>Documentation improvements</li>
<li>Updates to package testing using Github actions</li>
</ul>
<p>Thanks to Hugo van Kemenade for contributions to this release.</p>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/kjd/idna/compare/v3.7...v3.8">https://github.com/kjd/idna/compare/v3.7...v3.8</a></p>
<h2>v3.7</h2>
<h2>What's Changed</h2>
<ul>
<li>Fix issue where specially crafted inputs to encode() could take
exceptionally long amount of time to process. [CVE-2024-3651]</li>
</ul>
<p>Thanks to Guido Vranken for reporting the issue.</p>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/kjd/idna/compare/v3.6...v3.7">https://github.com/kjd/idna/compare/v3.6...v3.7</a></p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/kjd/idna/blob/master/HISTORY.rst">idna's
changelog</a>.</em></p>
<blockquote>
<p>3.10 (2024-09-15)
+++++++++++++++++</p>
<ul>
<li>Reverted to Unicode 15.1.0 data. Unicode 16 has some significant
changes
to UTS46 processing that will require more work to properly
implement.</li>
</ul>
<p>3.9 (2024-09-13)
++++++++++++++++</p>
<ul>
<li>Update to Unicode 16.0.0</li>
<li>Deprecate setup.cfg in favour of pyproject.toml</li>
<li>Use ruff for code formatting</li>
</ul>
<p>Thanks to Waket Zheng for contributions to this release.</p>
<p>3.8 (2024-08-23)
++++++++++++++++</p>
<ul>
<li>Fix regression where IDNAError exception was not being produced for
certain inputs.</li>
<li>Add support for Python 3.13, drop support for Python 3.5 as it is no
longer testable.</li>
<li>Documentation improvements</li>
<li>Updates to package testing using Github actions</li>
</ul>
<p>Thanks to Hugo van Kemenade for contributions to this release.</p>
<p>3.7 (2024-04-11)
++++++++++++++++</p>
<ul>
<li>Fix issue where specially crafted inputs to encode() could
take exceptionally long amount of time to process. [CVE-2024-3651]</li>
</ul>
<p>Thanks to Guido Vranken for reporting the issue.</p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/kjd/idna/commit/729225d8b0c58bc66bb38d1d0faf281a757ece59"><code>729225d</code></a>
Release v3.10</li>
<li><a
href="https://github.com/kjd/idna/commit/3eef1680132907e90afb0feb29136f6895001f3c"><code>3eef168</code></a>
Merge pull request <a
href="https://redirect.github.com/kjd/idna/issues/194">#194</a> from
kjd/revert-unicode-16</li>
<li><a
href="https://github.com/kjd/idna/commit/ceca619a214c816e04c7c233565280bf3998c938"><code>ceca619</code></a>
Revert Unicode 16.0.0 data updates</li>
<li><a
href="https://github.com/kjd/idna/commit/c43ac75cf649511c3d593164a32a3ff9cd0cdcd1"><code>c43ac75</code></a>
Merge pull request <a
href="https://redirect.github.com/kjd/idna/issues/191">#191</a> from
kjd/release-3.9</li>
<li><a
href="https://github.com/kjd/idna/commit/1b8800a4d0c76126ab2d3e28c7e62f567cbe69f8"><code>1b8800a</code></a>
Release v3.9</li>
<li><a
href="https://github.com/kjd/idna/commit/a1fd16821734235fb6ce4e0283a49a71d61535d2"><code>a1fd168</code></a>
Merge pull request <a
href="https://redirect.github.com/kjd/idna/issues/190">#190</a> from
kjd/unicode-16</li>
<li><a
href="https://github.com/kjd/idna/commit/7732c6153e07946f1bf5cdea96817264d305b7cc"><code>7732c61</code></a>
Merge branch 'master' into unicode-16</li>
<li><a
href="https://github.com/kjd/idna/commit/4ed183d95cf5cdfc98bb867b9e4b33a3fd13ca9b"><code>4ed183d</code></a>
Refactor membership test</li>
<li><a
href="https://github.com/kjd/idna/commit/762216bd7b1d0c45937703ea0c7632360e32c85b"><code>762216b</code></a>
Format with ruff</li>
<li><a
href="https://github.com/kjd/idna/commit/580ece955f7e127094b21b40761be6b70ab62aef"><code>580ece9</code></a>
Implement changes to UTS46 algorithm</li>
<li>Additional commits viewable in <a
href="https://github.com/kjd/idna/compare/v3.6...v3.10">compare
view</a></li>
</ul>
</details>
<br />

Updates `jsonschema` from 4.21.1 to 4.24.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/python-jsonschema/jsonschema/releases">jsonschema's
releases</a>.</em></p>
<blockquote>
<h2>v4.24.0</h2>
<!-- raw HTML omitted -->
<h2>What's Changed</h2>
<ul>
<li>Fix calculation of evaluated properties by <a
href="https://github.com/V02460"><code>@​V02460</code></a> in <a
href="https://redirect.github.com/python-jsonschema/jsonschema/pull/1351">python-jsonschema/jsonschema#1351</a></li>
<li>Support for Python 3.8 has been dropped, as it is end-of-life.</li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/bkueng"><code>@​bkueng</code></a> made
their first contribution in <a
href="https://redirect.github.com/python-jsonschema/jsonschema/pull/1326">python-jsonschema/jsonschema#1326</a></li>
<li><a href="https://github.com/V02460"><code>@​V02460</code></a> made
their first contribution in <a
href="https://redirect.github.com/python-jsonschema/jsonschema/pull/1351">python-jsonschema/jsonschema#1351</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/python-jsonschema/jsonschema/compare/v4.23.0...v4.24.0">https://github.com/python-jsonschema/jsonschema/compare/v4.23.0...v4.24.0</a></p>
<h2>v4.23.0</h2>
<!-- raw HTML omitted -->
<h2>What's Changed</h2>
<ul>
<li>Add some typing to the <code>exceptions.py</code> module by <a
href="https://github.com/DanielNoord"><code>@​DanielNoord</code></a> in
<a
href="https://redirect.github.com/python-jsonschema/jsonschema/pull/1019">python-jsonschema/jsonschema#1019</a></li>
<li>Declare support for 3.13 by <a
href="https://github.com/rominf"><code>@​rominf</code></a> in <a
href="https://redirect.github.com/python-jsonschema/jsonschema/pull/1282">python-jsonschema/jsonschema#1282</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/rominf"><code>@​rominf</code></a> made
their first contribution in <a
href="https://redirect.github.com/python-jsonschema/jsonschema/pull/1282">python-jsonschema/jsonschema#1282</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/python-jsonschema/jsonschema/compare/v4.22.0...v4.23.0">https://github.com/python-jsonschema/jsonschema/compare/v4.22.0...v4.23.0</a></p>
<h2>v4.22.0</h2>
<!-- raw HTML omitted -->
<h2>What's Changed</h2>
<ul>
<li>Improve <code>best_match</code> (and thereby error messages from
<code>jsonschema.validate</code>) in cases where there are multiple
<em>sibling</em> errors from applying <code>anyOf</code> /
<code>allOf</code> -- i.e. when multiple elements of a JSON array have
errors, we now do prefer showing errors from earlier elements rather
than simply showing an error for the full array (<a
href="https://redirect.github.com/python-jsonschema/jsonschema/issues/1250">#1250</a>).</li>
<li>(Micro-)optimize equality checks when comparing for JSON Schema
equality by first checking for object identity, as <code>==</code>
would.</li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/shinnar"><code>@​shinnar</code></a> made
their first contribution in <a
href="https://redirect.github.com/python-jsonschema/jsonschema/pull/1224">python-jsonschema/jsonschema#1224</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/python-jsonschema/jsonschema/compare/v4.21.1...v4.22.0">https://github.com/python-jsonschema/jsonschema/compare/v4.21.1...v4.22.0</a></p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/python-jsonschema/jsonschema/blob/main/CHANGELOG.rst">jsonschema's
changelog</a>.</em></p>
<blockquote>
<h1>v4.24.0</h1>
<ul>
<li>Fix improper handling of <code>unevaluatedProperties</code> in the
presence of <code>additionalProperties</code> (<a
href="https://redirect.github.com/python-jsonschema/jsonschema/issues/1351">#1351</a>).</li>
<li>Support for Python 3.8 has been dropped, as it is end-of-life.</li>
</ul>
<h1>v4.23.0</h1>
<ul>
<li>Do not reorder dictionaries (schemas, instances) that are printed as
part of validation errors.</li>
<li>Declare support for Py3.13</li>
</ul>
<h1>v4.22.0</h1>
<ul>
<li>Improve <code>best_match</code> (and thereby error messages from
<code>jsonschema.validate</code>) in cases where there are multiple
<em>sibling</em> errors from applying <code>anyOf</code> /
<code>allOf</code> -- i.e. when multiple elements of a JSON array have
errors, we now do prefer showing errors from earlier elements rather
than simply showing an error for the full array (<a
href="https://redirect.github.com/python-jsonschema/jsonschema/issues/1250">#1250</a>).</li>
<li>(Micro-)optimize equality checks when comparing for JSON Schema
equality by first checking for object identity, as <code>==</code>
would.</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/python-jsonschema/jsonschema/commit/3e23ee5e695f84565f4175fb972073d787e1ab24"><code>3e23ee5</code></a>
Add the bugfix to the changelog.</li>
<li><a
href="https://github.com/python-jsonschema/jsonschema/commit/8917e85c6549b2b2a0dfcae48fd512aaaebae836"><code>8917e85</code></a>
Stop running CIFuzz.</li>
<li><a
href="https://github.com/python-jsonschema/jsonschema/commit/737e5ed536db806d97879ef3681f695ddc75a32d"><code>737e5ed</code></a>
Rely on ruff in pre-commit.</li>
<li><a
href="https://github.com/python-jsonschema/jsonschema/commit/57e5e034cb0c8662995494ed4a833febf9b581a4"><code>57e5e03</code></a>
Test via PyPy 3.11.</li>
<li><a
href="https://github.com/python-jsonschema/jsonschema/commit/d6c2ad7bbbdea0b2c3e627c304ad4dd325aaa254"><code>d6c2ad7</code></a>
Add the zizmor setup here as well.</li>
<li><a
href="https://github.com/python-jsonschema/jsonschema/commit/af9a8578767ca70380ca2a2f7f6c2311b702d663"><code>af9a857</code></a>
Drop a dead pyproject section.</li>
<li><a
href="https://github.com/python-jsonschema/jsonschema/commit/c64ef846095b9d790749152367c8b12bea69a116"><code>c64ef84</code></a>
This is less true than it once was...</li>
<li><a
href="https://github.com/python-jsonschema/jsonschema/commit/9ff926f4588f0e4a8f5726cb69529c05c7921cc6"><code>9ff926f</code></a>
Merge branch 'additional-evaluated'</li>
<li><a
href="https://github.com/python-jsonschema/jsonschema/commit/8290667beb239282529430b59e2d4ea51777b33e"><code>8290667</code></a>
We still need to ditch pip-licenses...</li>
<li><a
href="https://github.com/python-jsonschema/jsonschema/commit/6d973b543030be9b53a67739d08c6f8b19f45119"><code>6d973b5</code></a>
Update pre-commit hooks.</li>
<li>Additional commits viewable in <a
href="https://github.com/python-jsonschema/jsonschema/compare/v4.21.1...v4.24.0">compare
view</a></li>
</ul>
</details>
<br />

Updates `jsonschema-specifications` from 2023.12.1 to 2025.4.1
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/python-jsonschema/jsonschema-specifications/releases">jsonschema-specifications's
releases</a>.</em></p>
<blockquote>
<h2>v2025.4.1</h2>
<!-- raw HTML omitted -->
<h2>What's Changed</h2>
<ul>
<li>Add SPDX license identifier by <a
href="https://github.com/cdce8p"><code>@​cdce8p</code></a> in <a
href="https://redirect.github.com/python-jsonschema/jsonschema-specifications/pull/93">python-jsonschema/jsonschema-specifications#93</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/cdce8p"><code>@​cdce8p</code></a> made
their first contribution in <a
href="https://redirect.github.com/python-jsonschema/jsonschema-specifications/pull/93">python-jsonschema/jsonschema-specifications#93</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/python-jsonschema/jsonschema-specifications/compare/v2024.10.1...v2025.4.1">https://github.com/python-jsonschema/jsonschema-specifications/compare/v2024.10.1...v2025.4.1</a></p>
<h2>v2024.10.1</h2>
<!-- raw HTML omitted -->
<h2>What's Changed</h2>
<ul>
<li>Declare support for Python 3.13 by <a
href="https://github.com/edgarrmondragon"><code>@​edgarrmondragon</code></a>
in <a
href="https://redirect.github.com/python-jsonschema/jsonschema-specifications/pull/72">python-jsonschema/jsonschema-specifications#72</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a
href="https://github.com/edgarrmondragon"><code>@​edgarrmondragon</code></a>
made their first contribution in <a
href="https://redirect.github.com/python-jsonschema/jsonschema-specifications/pull/72">python-jsonschema/jsonschema-specifications#72</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/python-jsonschema/jsonschema-specifications/compare/v2023.12.1...v2024.10.1">https://github.com/python-jsonschema/jsonschema-specifications/compare/v2023.12.1...v2024.10.1</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/python-jsonschema/jsonschema-specifications/commit/e3b0c79cd8797087a847768f5e0b21590c8040a5"><code>e3b0c79</code></a>
Merge pull request <a
href="https://redirect.github.com/python-jsonschema/jsonschema-specifications/issues/92">#92</a>
from python-jsonschema/pre-commit-ci-update-config</li>
<li><a
href="https://github.com/python-jsonschema/jsonschema-specifications/commit/7baf0695aa114719294d9af5dcd4a33ec3ff7af9"><code>7baf069</code></a>
Merge pull request <a
href="https://redirect.github.com/python-jsonschema/jsonschema-specifications/issues/93">#93</a>
from cdce8p/main</li>
<li><a
href="https://github.com/python-jsonschema/jsonschema-specifications/commit/de300146b7d253bbddadb60de1af319dcb074576"><code>de30014</code></a>
Add SPDX license identifier</li>
<li><a
href="https://github.com/python-jsonschema/jsonschema-specifications/commit/26b96870d8bb2f5661a5881d1ed72202c0b48ed6"><code>26b9687</code></a>
[pre-commit.ci] pre-commit autoupdate</li>
<li><a
href="https://github.com/python-jsonschema/jsonschema-specifications/commit/a8d179ae69a73558c26fa3218102176edb535acf"><code>a8d179a</code></a>
Merge pull request <a
href="https://redirect.github.com/python-jsonschema/jsonschema-specifications/issues/91">#91</a>
from python-jsonschema/pre-commit-ci-update-config</li>
<li><a
href="https://github.com/python-jsonschema/jsonschema-specifications/commit/9d19c4673df96efe588c6345b73fb04ea029b873"><code>9d19c46</code></a>
[pre-commit.ci] pre-commit autoupdate</li>
<li><a
href="https://github.com/python-jsonschema/jsonschema-specifications/commit/865ee26013f432bb7c2ffd4a0dc7bc27785f1020"><code>865ee26</code></a>
Merge pull request <a
href="https://redirect.github.com/python-jsonschema/jsonschema-specifications/issues/90">#90</a>
from python-jsonschema/pre-commit-ci-update-config</li>
<li><a
href="https://github.com/python-jsonschema/jsonschema-specifications/commit/89e5dbea141ac664a3cbf03d3f45c05af10ec7c5"><code>89e5dbe</code></a>
[pre-commit.ci] pre-commit autoupdate</li>
<li><a
href="https://github.com/python-jsonschema/jsonschema-specifications/commit/4f5a55001659592e86497d4083b979ce0210399e"><code>4f5a550</code></a>
Merge pull request <a
href="https://redirect.github.com/python-jsonschema/jsonschema-specifications/issues/89">#89</a>
from python-jsonschema/pre-commit-ci-update-config</li>
<li><a
href="https://github.com/python-jsonschema/jsonschema-specifications/commit/9289b54d5294bf5dea8df26cc8ed9b534386f77c"><code>9289b54</code></a>
[pre-commit.ci] pre-commit autoupdate</li>
<li>Additional commits viewable in <a
href="https://github.com/python-jsonschema/jsonschema-specifications/compare/v2023.12.1...v2025.4.1">compare
view</a></li>
</ul>
</details>
<br />

Updates `markupsafe` from 2.1.5 to 3.0.2
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/pallets/markupsafe/releases">markupsafe's
releases</a>.</em></p>
<blockquote>
<h2>3.0.2</h2>
<p>This is the MarkupSafe 3.0.2 fix release, which fixes bugs but does
not otherwise change behavior and should not result in breaking
changes.</p>
<p>PyPI: <a
href="https://pypi.org/project/MarkupSafe/3.0.2/">https://pypi.org/project/MarkupSafe/3.0.2/</a>
Changes: <a
href="https://markupsafe.palletsprojects.com/en/stable/changes/#version-3-0-2">https://markupsafe.palletsprojects.com/en/stable/changes/#version-3-0-2</a>
Milestone: <a
href="https://github.com/pallets/markupsafe/milestone/14?closed=1">https://github.com/pallets/markupsafe/milestone/14?closed=1</a></p>
<ul>
<li>Fix compatibility when <code>__str__</code> returns a
<code>str</code> subclass. <a
href="https://redirect.github.com/pallets/markupsafe/issues/472">#472</a></li>
<li>Build requires setuptools &gt;= 70.1. <a
href="https://redirect.github.com/pallets/markupsafe/issues/475">#475</a></li>
</ul>
<h2>3.0.1</h2>
<p>This is the MarkupSafe 3.0.1 fix release, which fixes bugs but does
not otherwise change behavior and should not result in breaking
changes.</p>
<p>PyPI: <a
href="https://pypi.org/project/MarkupSafe/3.0.1/">https://pypi.org/project/MarkupSafe/3.0.1/</a>
Changes: <a
href="https://markupsafe.palletsprojects.com/en/stable/changes/#version-3-0-1">https://markupsafe.palletsprojects.com/en/stable/changes/#version-3-0-1</a>
Milestone: <a
href="https://github.com/pallets/markupsafe/milestone/13?closed=1">https://github.com/pallets/markupsafe/milestone/13?closed=1</a></p>
<ul>
<li>Address compiler warnings that became errors in GCC 14. <a
href="https://redirect.github.com/pallets/markupsafe/issues/466">#466</a></li>
<li>Fix compatibility with proxy objects. <a
href="https://redirect.github.com/pallets/markupsafe/issues/467">#467</a></li>
</ul>
<h2>3.0.0</h2>
<p>This is the MarkupSafe 3.0.0 feature release. A feature release may
include new features, remove previously deprecated code, add new
deprecations, or introduce potentially breaking changes. The 3.0.x
branch is now the supported fix branch, the 2.1.x branch will become a
tag marking the end of support for that branch. We encourage everyone to
upgrade, and to use a tool such as <a
href="https://pypi.org/project/pip-tools/">pip-tools</a> to pin all
dependencies and control upgrades. Test with warnings treated as errors
to be able to adapt to deprecation warnings early.</p>
<p>PyPI: <a
href="https://pypi.org/project/MarkupSafe/3.0.0/">https://pypi.org/project/MarkupSafe/3.0.0/</a>
Changes: <a
href="https://markupsafe.palletsprojects.com/en/stable/changes/#version-3-0-0">https://markupsafe.palletsprojects.com/en/stable/changes/#version-3-0-0</a>
Milestone: <a
href="https://github.com/pallets/markupsafe/milestone/10?closed=1">https://github.com/pallets/markupsafe/milestone/10?closed=1</a></p>
<ul>
<li>Support Python 3.13 and its experimental free-threaded build. <a
href="https://redirect.github.com/pallets/markupsafe/issues/461">#461</a></li>
<li>Drop support for Python 3.7 and 3.8.</li>
<li>Use modern packaging metadata with <code>pyproject.toml</code>
instead of <code>setup.cfg</code>. <a
href="https://redirect.github.com/pallets/markupsafe/issues/348">#348</a></li>
<li>Change <code>distutils</code> imports to <code>setuptools</code>. <a
href="https://redirect.github.com/pallets/markupsafe/issues/399">#399</a></li>
<li>Use deferred evaluation of annotations. <a
href="https://redirect.github.com/pallets/markupsafe/issues/400">#400</a></li>
<li>Update signatures for <code>Markup</code> methods to match
<code>str</code> signatures. Use positional-only arguments. <a
href="https://redirect.github.com/pallets/markupsafe/issues/400">#400</a></li>
<li>Some <code>str</code> methods on <code>Markup</code> no longer
escape their argument: <code>strip</code>, <code>lstrip</code>,
<code>rstrip</code>, <code>removeprefix</code>,
<code>removesuffix</code>, <code>partition</code>, and
<code>rpartition</code>; <code>replace</code> only escapes its
<code>new</code> argument. These methods are conceptually linked to
search methods such as <code>in</code>, <code>find</code>, and
<code>index</code>, which already do not escape their argument. <a
href="https://redirect.github.com/pallets/markupsafe/issues/401">#401</a></li>
<li>The <code>__version__</code> attribute is deprecated. Use feature
detection, or
<code>importlib.metadata.version(&quot;markupsafe&quot;)</code>,
instead. <a
href="https://redirect.github.com/pallets/markupsafe/issues/402">#402</a></li>
<li>Speed up escaping plain strings by 40%. <a
href="https://redirect.github.com/pallets/markupsafe/issues/434">#434</a></li>
<li>Simplify speedups implementation. <a
href="https://redirect.github.com/pallets/markupsafe/issues/437">#437</a></li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/pallets/markupsafe/blob/main/CHANGES.rst">markupsafe's
changelog</a>.</em></p>
<blockquote>
<h2>Version 3.0.2</h2>
<p>Released 2024-10-18</p>
<ul>
<li>Fix compatibility when <code>__str__</code> returns a
<code>str</code> subclass. :issue:<code>472</code></li>
<li>Build requires setuptools &gt;= 70.1. :issue:<code>475</code></li>
</ul>
<h2>Version 3.0.1</h2>
<p>Released 2024-10-08</p>
<ul>
<li>Address compiler warnings that became errors in GCC 14.
:issue:<code>466</code></li>
<li>Fix compatibility with proxy objects. :issue:<code>467</code></li>
</ul>
<h2>Version 3.0.0</h2>
<p>Released 2024-10-07</p>
<ul>
<li>Support Python 3.13 and its experimental free-threaded build.
:pr:<code>461</code></li>
<li>Drop support for Python 3.7 and 3.8.</li>
<li>Use modern packaging metadata with <code>pyproject.toml</code>
instead of <code>setup.cfg</code>.
:pr:<code>348</code></li>
<li>Change <code>distutils</code> imports to <code>setuptools</code>.
:pr:<code>399</code></li>
<li>Use deferred evaluation of annotations. :pr:<code>400</code></li>
<li>Update signatures for <code>Markup</code> methods to match
<code>str</code> signatures. Use
positional-only arguments. :pr:<code>400</code></li>
<li>Some <code>str</code> methods on <code>Markup</code> no longer
escape their argument:
<code>strip</code>, <code>lstrip</code>, <code>rstrip</code>,
<code>removeprefix</code>, <code>removesuffix</code>,
<code>partition</code>, and <code>rpartition</code>;
<code>replace</code> only escapes its <code>new</code>
argument. These methods are conceptually linked to search methods such
as
<code>in</code>, <code>find</code>, and <code>index</code>, which
already do not escape their argument.
:issue:<code>401</code></li>
<li>The <code>__version__</code> attribute is deprecated. Use feature
detection, or
<code>importlib.metadata.version(&quot;markupsafe&quot;)</code>,
instead. :pr:<code>402</code></li>
<li>Speed up escaping plain strings by 40%. :pr:<code>434</code></li>
<li>Simplify speedups implementation. :pr:<code>437</code></li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/pallets/markupsafe/commit/28ace20b140d15c083e1cbc163ee6b7778ba098c"><code>28ace20</code></a>
release version 3.0.2</li>
<li><a
href="https://github.com/pallets/markupsafe/commit/6b51fd8f7386983b7038ad973557367cbd48579a"><code>6b51fd8</code></a>
build requires at least setuptools 70.1 (<a
href="https://redirect.github.com/pallets/markupsafe/issues/478">#478</a>)</li>
<li><a
href="https://github.com/pallets/markupsafe/commit/99dda9fd708432bd07d02327b2668661aa3cdaa0"><code>99dda9f</code></a>
build requires at least setuptools 70.1</li>
<li><a
href="https://github.com/pallets/markupsafe/commit/3d8fd8cc006124a49ce2f4268b4d1739e301583e"><code>3d8fd8c</code></a>
fix version</li>
<li><a
href="https://github.com/pallets/markupsafe/commit/1933c4be9c2c88613f7660840cde27a1bb7567e0"><code>1933c4b</code></a>
fix version</li>
<li><a
href="https://github.com/pallets/markupsafe/commit/e85aff4d878aa458d5c1e879bf475d8483647f71"><code>e85aff4</code></a>
relax speedups str check (<a
href="https://redirect.github.com/pallets/markupsafe/issues/477">#477</a>)</li>
<li><a
href="https://github.com/pallets/markupsafe/commit/8cb1691ca038ca39942e088b956f5b94d8f636bf"><code>8cb1691</code></a>
relax speedups str check</li>
<li><a
href="https://github.com/pallets/markupsafe/commit/4dafb7c36f1f654f1edd85228d346252b0065d45"><code>4dafb7c</code></a>
start version 3.1.0</li>
<li><a
href="https://github.com/pallets/markupsafe/commit/9c44ecf45141f691d373a66ce664c43b5a6cc761"><code>9c44ecf</code></a>
update docs build</li>
<li><a
href="https://github.com/pallets/markupsafe/commit/275c76905617c3f0e34de14e8794fcf4dfb0f937"><code>275c769</code></a>
Merge branch '2.1.x' into 3.0.x</li>
<li>Additional commits viewable in <a
href="https://github.com/pallets/markupsafe/compare/2.1.5...3.0.2">compare
view</a></li>
</ul>
</details>
<br />

Updates `packaging` from 23.2 to 25.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/pypa/packaging/releases">packaging's
releases</a>.</em></p>
<blockquote>
<h2>25.0</h2>
<h2>What's Changed</h2>
<ul>
<li>Re-add a test for Unicode file name parsing by <a
href="https://github.com/Siddhesh-Agarwal"><code>@​Siddhesh-Agarwal</code></a>
in <a
href="https://redirect.github.com/pypa/packaging/pull/863">pypa/packaging#863</a></li>
<li>Upgrade to ruff 0.9.1 by <a
href="https://github.com/DimitriPapadopoulos"><code>@​DimitriPapadopoulos</code></a>
in <a
href="https://redirect.github.com/pypa/packaging/pull/865">pypa/packaging#865</a></li>
<li>Add support for PEP 738 Android tags by <a
href="https://github.com/mhsmith"><code>@​mhsmith</code></a> in <a
href="https://redirect.github.com/pypa/packaging/pull/880">pypa/packaging#880</a></li>
<li>feat(markers): support 'extras' and 'dependency_groups' markers by
<a href="https://github.com/frostming"><code>@​frostming</code></a> in
<a
href="https://redirect.github.com/pypa/packaging/pull/888">pypa/packaging#888</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a
href="https://github.com/Siddhesh-Agarwal"><code>@​Siddhesh-Agarwal</code></a>
made their first contribution in <a
href="https://redirect.github.com/pypa/packaging/pull/863">pypa/packaging#863</a></li>
<li><a href="https://github.com/mhsmith"><code>@​mhsmith</code></a> made
their first contribution in <a
href="https://redirect.github.com/pypa/packaging/pull/880">pypa/packaging#880</a></li>
<li><a href="https://github.com/frostming"><code>@​frostming</code></a>
made their first contribution in <a
href="https://redirect.github.com/pypa/packaging/pull/888">pypa/packaging#888</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/pypa/packaging/compare/24.2...25.0">https://github.com/pypa/packaging/compare/24.2...25.0</a></p>
<h2>24.2</h2>
<h2>What's Changed</h2>
<ul>
<li>The source is auto-formatted with ruff, not black by <a
href="https://github.com/DimitriPapadopoulos"><code>@​DimitriPapadopoulos</code></a>
in <a
href="https://redirect.github.com/pypa/packaging/pull/798">pypa/packaging#798</a></li>
<li>Bump the github-actions group across 1 directory with 3 updates by
<a href="https://github.com/dependabot"><code>@​dependabot</code></a> in
<a
href="https://redirect.github.com/pypa/packaging/pull/813">pypa/packaging#813</a></li>
<li>Apply ruff rules (RUF) by <a
href="https://github.com/DimitriPapadopoulos"><code>@​DimitriPapadopoulos</code></a>
in <a
href="https://redirect.github.com/pypa/packaging/pull/800">pypa/packaging#800</a></li>
<li>Fix typo in Version <code>__str__</code> by <a
href="https://github.com/aryanpingle"><code>@​aryanpingle</code></a> in
<a
href="https://redirect.github.com/pypa/packaging/pull/817">pypa/packaging#817</a></li>
<li>Bump the github-actions group with 3 updates by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/pypa/packaging/pull/819">pypa/packaging#819</a></li>
<li>Get rid of duplicate test cases by <a
href="https://github.com/DimitriPapadopoulos"><code>@​DimitriPapadopoulos</code></a>
in <a
href="https://redirect.github.com/pypa/packaging/pull/821">pypa/packaging#821</a></li>
<li>Fix doc for canonicalize_version and a typo in a docstring by <a
href="https://github.com/Laurent-Dx"><code>@​Laurent-Dx</code></a> in <a
href="https://redirect.github.com/pypa/packaging/pull/801">pypa/packaging#801</a></li>
<li>docs: public/base_version comparison by <a
href="https://github.com/henryiii"><code>@​henryiii</code></a> in <a
href="https://redirect.github.com/pypa/packaging/pull/818">pypa/packaging#818</a></li>
<li>Apply ruff/bugbear rules (B) by <a
href="https://github.com/DimitriPapadopoulos"><code>@​DimitriPapadopoulos</code></a>
in <a
href="https://redirect.github.com/pypa/packaging/pull/787">pypa/packaging#787</a></li>
<li>Apply ruff/pyupgrade rules (UP) by <a
href="https://github.com/DimitriPapadopoulos"><code>@​DimitriPapadopoulos</code></a>
in <a
href="https://redirect.github.com/pypa/packaging/pull/786">pypa/packaging#786</a></li>
<li>Add a changelog entry for dropping Python 3.7 support by <a
href="https://github.com/alexwlchan"><code>@​alexwlchan</code></a> in <a
href="https://redirect.github.com/pypa/packaging/pull/824">pypa/packaging#824</a></li>
<li>Patch python_full_version unconditionally by <a
href="https://github.com/jaraco"><code>@​jaraco</code></a> in <a
href="https://redirect.github.com/pypa/packaging/pull/825">pypa/packaging#825</a></li>
<li>Refactor canonicalize_version by <a
href="https://github.com/jaraco"><code>@​jaraco</code></a> in <a
href="https://redirect.github.com/pypa/packaging/pull/793">pypa/packaging#793</a></li>
<li>Allow creating a SpecifierSet from a list of specifiers by <a
href="https://github.com/pfmoore"><code>@​pfmoore</code></a> in <a
href="https://redirect.github.com/pypa/packaging/pull/777">pypa/packaging#777</a></li>
<li>Fix uninformative error message by <a
href="https://github.com/abravalheri"><code>@​abravalheri</code></a> in
<a
href="https://redirect.github.com/pypa/packaging/pull/830">pypa/packaging#830</a></li>
<li>Fix prerelease detection for <code>&gt;</code> and <code>&lt;</code>
by <a
href="https://github.com/notatallshaw"><code>@​notatallshaw</code></a>
in <a
href="https://redirect.github.com/pypa/packaging/pull/794">pypa/packaging#794</a></li>
<li>Bump the github-actions group across 1 directory with 4 updates by
<a href="https://github.com/dependabot"><code>@​dependabot</code></a> in
<a
href="https://redirect.github.com/pypa/packaging/pull/839">pypa/packaging#839</a></li>
<li>Add support for PEP 730 iOS tags. by <a
href="https://github.com/freakboy3742"><code>@​freakboy3742</code></a>
in <a
href="https://redirect.github.com/pypa/packaging/pull/832">pypa/packaging#832</a></li>
<li>Update the changelog to reflect 24.1 changes by <a
href="https://github.com/pradyunsg"><code>@​pradyunsg</code></a> in <a
href="https://redirect.github.com/pypa/packaging/pull/840">pypa/packaging#840</a></li>
<li>Mention updating changelog in release process by <a
href="https://github.com/pradyunsg"><code>@​pradyunsg</code></a> in <a
href="https://redirect.github.com/pypa/packaging/pull/841">pypa/packaging#841</a></li>
<li>Add a comment as to why <code>Metadata.name</code> isn't normalized
by <a
href="https://github.com/brettcannon"><code>@​brettcannon</code></a> in
<a
href="https://redirect.github.com/pypa/packaging/pull/842">pypa/packaging#842</a></li>
<li>Use !r formatter for error messages with filenames. by <a
href="https://github.com/Carreau"><code>@​Carreau</code></a> in <a
href="https://redirect.github.com/pypa/packaging/pull/844">pypa/packaging#844</a></li>
<li>PEP 639: Implement License-Expression and License-File by <a
href="https://github.com/ewdurbin"><code>@​ewdurbin</code></a> in <a
href="https://redirect.github.com/pypa/packaging/pull/828">pypa/packaging#828</a></li>
<li>Bump the github-actions group with 4 updates by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/pypa/packaging/pull/852">pypa/packaging#852</a></li>
<li>Upgrade to latest mypy by <a
href="https://github.com/hauntsaninja"><code>@​hauntsaninja</code></a>
in <a
href="https://redirect.github.com/pypa/packaging/pull/853">pypa/packaging#853</a></li>
<li>Extraneous quotes by <a
href="https://github.com/ewdurbin"><code>@​ewdurbin</code></a> in <a
href="https://redirect.github.com/pypa/packaging/pull/848">pypa/packaging#848</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a
href="https://github.com/aryanpingle"><code>@​aryanpingle</code></a>
made their first contribution in <a
href="https://redirect.github.com/pypa/packaging/pull/817">pypa/packaging#817</a></li>
<li><a
href="https://github.com/Laurent-Dx"><code>@​Laurent-Dx</code></a> made
their first contribution in <a
href="https://redirect.github.com/pypa/packaging/pull/801">pypa/packaging#801</a></li>
<li><a
href="https://github.com/alexwlchan"><code>@​alexwlchan</code></a> made
their first contribution in <a
href="https://redirect.github.com/pypa/packaging/pull/824">pypa/packaging#824</a></li>
<li><a href="https://github.com/jaraco"><code>@​jaraco</code></a> made
their first contribution in <a
href="https://redirect.github.com/pypa/packaging/pull/825">pypa/packaging#825</a></li>
<li><a
href="https://github.com/notatallshaw"><code>@​notatallshaw</code></a>
made their first contribution in <a
href="https://redirect.github.com/pypa/packaging/pull/794">pypa/packaging#794</a></li>
<li><a
href="https://github.com/freakboy3742"><code>@​freakboy3742</code></a>
made their first contribution in <a
href="https://redirect.github.com/pypa/packaging/pull/832">pypa/packaging#832</a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/pypa/packaging/blob/main/CHANGELOG.rst">packaging's
changelog</a>.</em></p>
<blockquote>
<p>25.0 - 2025-04-19</p>
<pre><code>
* PEP 751: Add support for ``extras`` and ``dependency_groups`` markers.
(:issue:`885`)
* PEP 738: Add support for Android platform tags. (:issue:`880`)
<p>24.2 - 2024-11-08<br />
</code></pre></p>
<ul>
<li>PEP 639: Implement License-Expression and License-File
(:issue:<code>828</code>)</li>
<li>Use <code>!r</code> formatter for error messages with filenames
(:issue:<code>844</code>)</li>
<li>Add support for PEP 730 iOS tags (:issue:<code>832</code>)</li>
<li>Fix prerelease detection for <code>&gt;</code> and <code>&lt;</code>
(:issue:<code>794</code>)</li>
<li>Fix uninformative error message (:issue:<code>830</code>)</li>
<li>Refactor <code>canonicalize_version</code>
(:issue:<code>793</code>)</li>
<li>Patch python_full_version unconditionally
(:issue:<code>825</code>)</li>
<li>Fix doc for <code>canonicalize_version</code> to mention
<code>strip_trailing_zero</code> and a typo in a docstring
(:issue:<code>801</code>)</li>
<li>Fix typo in Version <code>__str__</code>
(:issue:<code>817</code>)</li>
<li>Support creating a <code>SpecifierSet</code> from an iterable of
<code>Specifier</code> objects (:issue:<code>775</code>)</li>
</ul>
<p>24.1 - 2024-06-10</p>
<pre><code>
* Document ``markers.default_environment()`` (:issue:`753`).
* Add support for Python 3.13 (:issue:`783`).
* Modernise type annotations (:issue:`785`).
* Work around ``platform.python_version()`` returning non PEP 440
compliant version
  for non-tagged CPython builds (:issue:`802`).
<p>24.0 - 2024-03-10<br />
</code></pre></p>
<ul>
<li>Do specifier matching correctly when the specifier contains an epoch
number
and has more components than the version (:issue:<code>683</code>)</li>
<li>Support the experimental <code>--disable-gil</code> builds in
packaging.tags
(:issue:<code>727</code>)</li>
<li>BREAKING: Make optional <code>metadata.Metadata</code> attributes
default to <code>None</code> (:issue:<code>733</code>)</li>
<li>Fix errors when trying to access the
<code>description_content_type</code>, <code>keywords</code>,
and <code>requires_python</code> attributes on
<code>metadata.Metadata</code> when those values
have not been provided (:issue:<code>733</code>)</li>
<li>Fix a bug preventing the use of the built in
<code>ExceptionGroup</code> on versions of
Python that support it (:issue:<code>725</code>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/pypa/packaging/commit/f58537628042c7f29780b9d33f31597e7fc9d664"><code>f585376</code></a>
Bump for release</li>
<li><a
href="https://github.com/pypa/packaging/commit/600ecea15b2388037b8dc94883504ca612947576"><code>600ecea</code></a>
Add changelog entries</li>
<li><a
href="https://github.com/pypa/packaging/commit/3910129009b25dd1aa1fe32e644bc891188c56fe"><code>3910129</code></a>
support 'extras' and 'dependency_groups' markers (<a
href="https://redirect.github.com/pypa/packaging/issues/888">#888</a>)</li>
<li><a
href="https://github.com/pypa/packaging/commit/8e49b4373731bffb110c9583e64ad802cb67c7ea"><code>8e49b43</code></a>
Add support for PEP 738 Android tags (<a
href="https://redirect.github.com/pypa/packaging/issues/880">#880</a>)</li>
<li><a
href="https://github.com/pypa/packaging/commit/e624d8edfaa28865de7b5a7da8bd59fd410e5331"><code>e624d8e</code></a>
Bump the github-actions group with 3 updates (<a
href="https://redirect.github.com/pypa/packaging/issues/886">#886</a>)</li>
<li><a
href="https://github.com/pypa/packaging/commit/71f38d872a6e88b28da9d1b270f8512475bc90d4"><code>71f38d8</code></a>
Bump the github-actions group with 2 updates (<a
href="https://redirect.github.com/pypa/packaging/issues/878">#878</a>)</li>
<li><a
href="https://github.com/pypa/packaging/commit/9b4922dd3c26c8522d716bec79d7e0ed408631c1"><code>9b4922d</code></a>
Bump the github-actions group with 3 updates (<a
href="https://redirect.github.com/pypa/packaging/issues/870">#870</a>)</li>
<li><a
href="https://github.com/pypa/packaging/commit/8510bd9d3bab5571974202ec85f6ef7b0359bfaf"><code>8510bd9</code></a>
Upgrade to ruff 0.9.1 (<a
href="https://redirect.github.com/pypa/packaging/issues/865">#865</a>)</li>
<li><a
href="https://github.com/pypa/packaging/commit/9375ec2eff48257967c97d331b9a76019e95bdb0"><code>9375ec2</code></a>
Re-add tests for Unicode file name parsing (<a
href="https://redirect.github.com/pypa/packaging/issues/863">#863</a>)</li>
<li><a
href="https://github.com/pypa/packaging/commit/2256ed4ac261309a09daa04cc801abd7cff2e6f0"><code>2256ed4</code></a>
Bump the github-actions group across 1 directory with 2 updates (<a
href="https://redirect.github.com/pypa/packaging/issues/864">#864</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/pypa/packaging/compare/23.2...25.0">compare
view</a></li>
</ul>
</details>
<br />

Updates `pywin32` from 308 to 310
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/mhammond/pywin32/releases">pywin32's
releases</a>.</em></p>
<blockquote>
<h2>Release 310</h2>
<p>A release fixing <a
href="https://github.com/mhammond/pywin32/blob/b310/CHANGES.txt#L17">a
few regressions</a></p>
<p>Install via pip:</p>
<pre><code>pip install pywin32 --upgrade
</code></pre>
<p>More <a
href="https://github.com/mhammond/pywin32#installing-via-pip">details in
the README</a></p>
<h2>Release 309</h2>
<p>A release with <a
href="https://github.com/mhammond/pywin32/blob/515c815fff7d46431c3614fb6b86e27c7bbdad7e/CHANGES.txt#L14">a
number of changes and fixes</a></p>
<p>Install via pip:</p>
<blockquote>
<p>pip install pywin32 --upgrade</p>
</blockquote>
<p>More <a
href="https://github.com/mhammond/pywin32#installing-via-pip">details in
the README</a></p>
<p>There are no .exe installers for this release - you must use pip.</p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/mhammond/pywin32/blob/main/CHANGES.txt">pywin32's
changelog</a>.</em></p>
<blockquote>
<h2>Build 310, released 2025/03/16</h2>
<ul>
<li>Fixed a regression where
<code>win32com.client.DispatchWithEvents</code> and
win32com.client.WithEvents<code>would throw a</code>TypeError` on the
second call (<a
href="https://redirect.github.com/mhammond/pywin32/issues/2491">#2491</a>,
<a href="https://github.com/Avasam"><code>@​Avasam</code></a>)</li>
<li>Fixed regresion causing <code>win32com.shell.shell</code> to be
missing a number of <code>IID</code>s. (<a
href="https://redirect.github.com/mhammond/pywin32/issues/2487">#2487</a>,
<a href="https://github.com/Avasam"><code>@​Avasam</code></a>)</li>
<li>As part of the above, Windows 7 is now minimum supported.</li>
</ul>
<h2>Build 309, released 2025/03/09</h2>
<h2>pywin32</h2>
<ul>
<li>Fixed Access Violation crashes in 3.12 by moving
<code>PyWInObject_Free*</code> methods so GIL is acquired (<a
href="https://redirect.github.com/mhammond/pywin32/issues/2467">#2467</a>,
<a href="https://github.com/Mscht"><code>@​Mscht</code></a>)</li>
<li>Added support for relative path ...

_Description has been truncated_

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Zanie Blue <contact@zanie.dev>
---
 requirements.dev.txt | 114 +++---
 requirements.in      |   1 +
 requirements.win.txt | 810 ++++++++++++++++++++++++-------------------
 3 files changed, 517 insertions(+), 408 deletions(-)

diff --git a/requirements.dev.txt b/requirements.dev.txt
index dfeb2887..9cb9cd6b 100644
--- a/requirements.dev.txt
+++ b/requirements.dev.txt
@@ -198,34 +198,39 @@ markupsafe==3.0.2 \
     # via
     #   -r requirements.txt
     #   jinja2
-mypy==1.8.0 \
-    --hash=sha256:028cf9f2cae89e202d7b6593cd98db6759379f17a319b5faf4f9978d7084cdc6 \
-    --hash=sha256:2afecd6354bbfb6e0160f4e4ad9ba6e4e003b767dd80d85516e71f2e955ab50d \
-    --hash=sha256:2b5b6c721bd4aabaadead3a5e6fa85c11c6c795e0c81a7215776ef8afc66de02 \
-    --hash=sha256:42419861b43e6962a649068a61f4a4839205a3ef525b858377a960b9e2de6e0d \
-    --hash=sha256:42c6680d256ab35637ef88891c6bd02514ccb7e1122133ac96055ff458f93fc3 \
-    --hash=sha256:485a8942f671120f76afffff70f259e1cd0f0cfe08f81c05d8816d958d4577d3 \
-    --hash=sha256:4c886c6cce2d070bd7df4ec4a05a13ee20c0aa60cb587e8d1265b6c03cf91da3 \
-    --hash=sha256:4e6d97288757e1ddba10dd9549ac27982e3e74a49d8d0179fc14d4365c7add66 \
-    --hash=sha256:4ef4be7baf08a203170f29e89d79064463b7fc7a0908b9d0d5114e8009c3a259 \
-    --hash=sha256:51720c776d148bad2372ca21ca29256ed483aa9a4cdefefcef49006dff2a6835 \
-    --hash=sha256:52825b01f5c4c1c4eb0db253ec09c7aa17e1a7304d247c48b6f3599ef40db8bd \
-    --hash=sha256:538fd81bb5e430cc1381a443971c0475582ff9f434c16cd46d2c66763ce85d9d \
-    --hash=sha256:5c1538c38584029352878a0466f03a8ee7547d7bd9f641f57a0f3017a7c905b8 \
-    --hash=sha256:6ff8b244d7085a0b425b56d327b480c3b29cafbd2eff27316a004f9a7391ae07 \
-    --hash=sha256:7178def594014aa6c35a8ff411cf37d682f428b3b5617ca79029d8ae72f5402b \
-    --hash=sha256:720a5ca70e136b675af3af63db533c1c8c9181314d207568bbe79051f122669e \
-    --hash=sha256:7f1478736fcebb90f97e40aff11a5f253af890c845ee0c850fe80aa060a267c6 \
-    --hash=sha256:855fe27b80375e5c5878492f0729540db47b186509c98dae341254c8f45f42ae \
-    --hash=sha256:8963b83d53ee733a6e4196954502b33567ad07dfd74851f32be18eb932fb1cb9 \
-    --hash=sha256:9261ed810972061388918c83c3f5cd46079d875026ba97380f3e3978a72f503d \
-    --hash=sha256:99b00bc72855812a60d253420d8a2eae839b0afa4938f09f4d2aa9bb4654263a \
-    --hash=sha256:ab3c84fa13c04aeeeabb2a7f67a25ef5d77ac9d6486ff33ded762ef353aa5592 \
-    --hash=sha256:afe3fe972c645b4632c563d3f3eff1cdca2fa058f730df2b93a35e3b0c538218 \
-    --hash=sha256:d19c413b3c07cbecf1f991e2221746b0d2a9410b59cb3f4fb9557f0365a1a817 \
-    --hash=sha256:df9824ac11deaf007443e7ed2a4a26bebff98d2bc43c6da21b2b64185da011c4 \
-    --hash=sha256:e46f44b54ebddbeedbd3d5b289a893219065ef805d95094d16a0af6630f5d410 \
-    --hash=sha256:f5ac9a4eeb1ec0f1ccdc6f326bcdb464de5f80eb07fb38b5ddd7b0de6bc61e55
+mypy==1.15.0 \
+    --hash=sha256:1124a18bc11a6a62887e3e137f37f53fbae476dc36c185d549d4f837a2a6a14e \
+    --hash=sha256:171a9ca9a40cd1843abeca0e405bc1940cd9b305eaeea2dda769ba096932bb22 \
+    --hash=sha256:1905f494bfd7d85a23a88c5d97840888a7bd516545fc5aaedff0267e0bb54e2f \
+    --hash=sha256:1fbb8da62dc352133d7d7ca90ed2fb0e9d42bb1a32724c287d3c76c58cbaa9c2 \
+    --hash=sha256:2922d42e16d6de288022e5ca321cd0618b238cfc5570e0263e5ba0a77dbef56f \
+    --hash=sha256:2e2c2e6d3593f6451b18588848e66260ff62ccca522dd231cd4dd59b0160668b \
+    --hash=sha256:2ee2d57e01a7c35de00f4634ba1bbf015185b219e4dc5909e281016df43f5ee5 \
+    --hash=sha256:2f2147ab812b75e5b5499b01ade1f4a81489a147c01585cda36019102538615f \
+    --hash=sha256:404534629d51d3efea5c800ee7c42b72a6554d6c400e6a79eafe15d11341fd43 \
+    --hash=sha256:5469affef548bd1895d86d3bf10ce2b44e33d86923c29e4d675b3e323437ea3e \
+    --hash=sha256:5a95fb17c13e29d2d5195869262f8125dfdb5c134dc8d9a9d0aecf7525b10c2c \
+    --hash=sha256:6983aae8b2f653e098edb77f893f7b6aca69f6cffb19b2cc7443f23cce5f4828 \
+    --hash=sha256:712e962a6357634fef20412699a3655c610110e01cdaa6180acec7fc9f8513ba \
+    --hash=sha256:8023ff13985661b50a5928fc7a5ca15f3d1affb41e5f0a9952cb68ef090b31ee \
+    --hash=sha256:811aeccadfb730024c5d3e326b2fbe9249bb7413553f15499a4050f7c30e801d \
+    --hash=sha256:8f8722560a14cde92fdb1e31597760dc35f9f5524cce17836c0d22841830fd5b \
+    --hash=sha256:93faf3fdb04768d44bf28693293f3904bbb555d076b781ad2530214ee53e3445 \
+    --hash=sha256:973500e0774b85d9689715feeffcc980193086551110fd678ebe1f4342fb7c5e \
+    --hash=sha256:979e4e1a006511dacf628e36fadfecbcc0160a8af6ca7dad2f5025529e082c13 \
+    --hash=sha256:98b7b9b9aedb65fe628c62a6dc57f6d5088ef2dfca37903a7d9ee374d03acca5 \
+    --hash=sha256:aea39e0583d05124836ea645f412e88a5c7d0fd77a6d694b60d9b6b2d9f184fd \
+    --hash=sha256:b9378e2c00146c44793c98b8d5a61039a048e31f429fb0eb546d93f4b000bedf \
+    --hash=sha256:baefc32840a9f00babd83251560e0ae1573e2f9d1b067719479bfb0e987c6357 \
+    --hash=sha256:be68172e9fd9ad8fb876c6389f16d1c1b5f100ffa779f77b1fb2176fcc9ab95b \
+    --hash=sha256:c43a7682e24b4f576d93072216bf56eeff70d9140241f9edec0c104d0c515036 \
+    --hash=sha256:c4bb0e1bd29f7d34efcccd71cf733580191e9a264a2202b0239da95984c5b559 \
+    --hash=sha256:c7be1e46525adfa0d97681432ee9fcd61a3964c2446795714699a998d193f1a3 \
+    --hash=sha256:c9817fa23833ff189db061e6d2eff49b2f3b6ed9856b4a0a73046e41932d744f \
+    --hash=sha256:ce436f4c6d218a070048ed6a44c0bbb10cd2cc5e272b29e7845f6a2f57ee4464 \
+    --hash=sha256:d10d994b41fb3497719bbf866f227b3489048ea4bbbb5015357db306249f7980 \
+    --hash=sha256:e601a7fa172c2131bff456bb3ee08a88360760d0d2f8cbd7a75a65497e2df078 \
+    --hash=sha256:f95579473af29ab73a10bada2f9722856792a36ec5af5399b653aa28360290a5
     # via -r requirements.dev.in
 mypy-extensions==1.0.0 \
     --hash=sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d \
@@ -408,24 +413,25 @@ rpds-py==0.22.3 \
     #   -r requirements.txt
     #   jsonschema
     #   referencing
-ruff==0.3.4 \
-    --hash=sha256:3f3860057590e810c7ffea75669bdc6927bfd91e29b4baa9258fd48b540a4365 \
-    --hash=sha256:519cf6a0ebed244dce1dc8aecd3dc99add7a2ee15bb68cf19588bb5bf58e0488 \
-    --hash=sha256:60c870a7d46efcbc8385d27ec07fe534ac32f3b251e4fc44b3cbfd9e09609ef4 \
-    --hash=sha256:64abeed785dad51801b423fa51840b1764b35d6c461ea8caef9cf9e5e5ab34d9 \
-    --hash=sha256:6810563cc08ad0096b57c717bd78aeac888a1bfd38654d9113cb3dc4d3f74232 \
-    --hash=sha256:6fc14fa742e1d8f24910e1fff0bd5e26d395b0e0e04cc1b15c7c5e5fe5b4af91 \
-    --hash=sha256:986f2377f7cf12efac1f515fc1a5b753c000ed1e0a6de96747cdf2da20a1b369 \
-    --hash=sha256:98e98300056445ba2cc27d0b325fd044dc17fcc38e4e4d2c7711585bd0a958ed \
-    --hash=sha256:af27ac187c0a331e8ef91d84bf1c3c6a5dea97e912a7560ac0cef25c526a4102 \
-    --hash=sha256:bb0acfb921030d00070539c038cd24bb1df73a2981e9f55942514af8b17be94e \
-    --hash=sha256:c4fd98e85869603e65f554fdc5cddf0712e352fe6e61d29d5a6fe087ec82b76c \
-    --hash=sha256:cf133dd744f2470b347f602452a88e70dadfbe0fcfb5fd46e093d55da65f82f7 \
-    --hash=sha256:cf187a7e7098233d0d0c71175375c5162f880126c4c716fa28a8ac418dcf3378 \
-    --hash=sha256:d3ee7880f653cc03749a3bfea720cf2a192e4f884925b0cf7eecce82f0ce5854 \
-    --hash=sha256:de0d5069b165e5a32b3c6ffbb81c350b1e3d3483347196ffdf86dc0ef9e37dd6 \
-    --hash=sha256:df52972138318bc7546d92348a1ee58449bc3f9eaf0db278906eb511889c4b50 \
-    --hash=sha256:f0f4484c6541a99862b693e13a151435a279b271cff20e37101116a21e2a1ad1
+ruff==0.11.11 \
+    --hash=sha256:1adcb9a18802268aaa891ffb67b1c94cd70578f126637118e8099b8e4adcf112 \
+    --hash=sha256:1b5ab797fcc09121ed82e9b12b6f27e34859e4227080a42d090881be888755d4 \
+    --hash=sha256:6224076c344a7694c6fbbb70d4f2a7b730f6d47d2a9dc1e7f9d9bb583faf390b \
+    --hash=sha256:64ac6f885e3ecb2fdbb71de2701d4e34526651f1e8503af8fb30d4915a3fe345 \
+    --hash=sha256:6c51f136c0364ab1b774767aa8b86331bd8e9d414e2d107db7a2189f35ea1f7b \
+    --hash=sha256:748b4bb245f11e91a04a4ff0f96e386711df0a30412b9fe0c74d5bdc0e4a531f \
+    --hash=sha256:7774173cc7c1980e6bf67569ebb7085989a78a103922fb83ef3dfe230cd0687d \
+    --hash=sha256:7885d9a5e4c77b24e8c88aba8c80be9255fa22ab326019dac2356cff42089fc6 \
+    --hash=sha256:882821fcdf7ae8db7a951df1903d9cb032bbe838852e5fc3c2b6c3ab54e39875 \
+    --hash=sha256:9263f9e5aa4ff1dec765e99810f1cc53f0c868c5329b69f13845f699fe74f639 \
+    --hash=sha256:9924e5ae54125ed8958a4f7de320dab7380f6e9fa3195e3dc3b137c6842a0092 \
+    --hash=sha256:99c28505ecbaeb6594701a74e395b187ee083ee26478c1a795d35084d53ebd81 \
+    --hash=sha256:a97c9babe1d4081037a90289986925726b802d180cca784ac8da2bbbc335f709 \
+    --hash=sha256:c8a93276393d91e952f790148eb226658dd275cddfde96c6ca304873f11d2ae4 \
+    --hash=sha256:d6e333dbe2e6ae84cdedefa943dfd6434753ad321764fd937eef9d6b62022bcd \
+    --hash=sha256:d8c4ddcbe8a19f59f57fd814b8b117d4fcea9bee7c0492e6cf5fdc22cfa563c8 \
+    --hash=sha256:dcec2d50756463d9df075a26a85a6affbc1b0148873da3997286caf1ce03cae1 \
+    --hash=sha256:e231ff3132c1119ece836487a02785f099a43992b95c2f62847d29bace3c75ac
     # via -r requirements.dev.in
 six==1.17.0 \
     --hash=sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274 \
@@ -464,22 +470,24 @@ tomli==2.2.1 \
     --hash=sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272 \
     --hash=sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a \
     --hash=sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7
-    # via -r requirements.txt
+    # via
+    #   -r requirements.txt
+    #   mypy
 types-jinja2==2.11.9 \
     --hash=sha256:60a1e21e8296979db32f9374d8a239af4cb541ff66447bb915d8ad398f9c63b2 \
     --hash=sha256:dbdc74a40aba7aed520b7e4d89e8f0fe4286518494208b35123bcf084d4b8c81
     # via -r requirements.dev.in
-types-jsonschema==4.21.0.20240118 \
-    --hash=sha256:31aae1b5adc0176c1155c2d4f58348b22d92ae64315e9cc83bd6902168839232 \
-    --hash=sha256:77a4ac36b0be4f24274d5b9bf0b66208ee771c05f80e34c4641de7d63e8a872d
+types-jsonschema==4.23.0.20250516 \
+    --hash=sha256:9ace09d9d35c4390a7251ccd7d833b92ccc189d24d1b347f26212afce361117e \
+    --hash=sha256:e7d0dd7db7e59e63c26e3230e26ffc64c4704cc5170dc21270b366a35ead1618
     # via -r requirements.dev.in
 types-markupsafe==1.1.10 \
     --hash=sha256:85b3a872683d02aea3a5ac2a8ef590193c344092032f58457287fbf8e06711b1 \
     --hash=sha256:ca2bee0f4faafc45250602567ef38d533e877d2ddca13003b319c551ff5b3cc5
     # via types-jinja2
-types-pyyaml==6.0.12.12 \
-    --hash=sha256:334373d392fde0fdf95af5c3f1661885fa10c52167b14593eb856289e1855062 \
-    --hash=sha256:c05bc6c158facb0676674b7f11fe3960db4f389718e19e62bd2b84d6205cfd24
+types-pyyaml==6.0.12.20250516 \
+    --hash=sha256:8478208feaeb53a34cb5d970c56a7cd76b72659442e733e268a94dc72b2d0530 \
+    --hash=sha256:9f21a70216fc0fa1b216a8176db5f9e0af6eb35d2f2932acb87689d03a5bf6ba
     # via -r requirements.dev.in
 typing-extensions==4.9.0 \
     --hash=sha256:23478f88c37f27d76ac8aee6c905017a143b0b1b886c3c9f66bc2fd94f9f5783 \
diff --git a/requirements.in b/requirements.in
index a6753f74..0e9ae39a 100644
--- a/requirements.in
+++ b/requirements.in
@@ -7,4 +7,5 @@ six
 # This is a transitive dependency that doesn't get picked up when running on
 # modern Python. So include to force it in requirements.txt.
 tomli
+typing-extensions
 zstandard
diff --git a/requirements.win.txt b/requirements.win.txt
index 6100025a..222620eb 100644
--- a/requirements.win.txt
+++ b/requirements.win.txt
@@ -1,212 +1,209 @@
 # This file was autogenerated by uv via the following command:
 #    uv pip compile --python-platform windows --generate-hashes requirements.in -o requirements.win.txt
-attrs==23.2.0 \
-    --hash=sha256:935dc3b529c262f6cf76e50877d35a4bd3c1de194fd41f47a2b7ae8f19971f30 \
-    --hash=sha256:99b87a485a5820b23b879f04c2305b44b951b502fd64be915879d77a7e8fc6f1
+attrs==25.3.0 \
+    --hash=sha256:427318ce031701fea540783410126f03899a97ffc6f61596ad581ac2e40e3bc3 \
+    --hash=sha256:75d7cefc7fb576747b2c81b4442d4d4a1ce0900973527c011d1030fd3bf4af1b
     # via
     #   jsonschema
     #   referencing
-certifi==2024.7.4 \
-    --hash=sha256:5a1e7645bc0ec61a09e26c36f6106dd4cf40c6db3a1fb6352b0244e7fb057c7b \
-    --hash=sha256:c198e21b1289c2ab85ee4e67bb4b4ef3ead0892059901a8d5b622f24a1101e90
+certifi==2025.4.26 \
+    --hash=sha256:0a816057ea3cdefcef70270d2c515e4506bbc954f417fa5ade2021213bb8f0c6 \
+    --hash=sha256:30350364dfe371162649852c63336a15c70c6510c2ad5015b21c2345311805f3
     # via requests
-charset-normalizer==3.3.2 \
-    --hash=sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027 \
-    --hash=sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087 \
-    --hash=sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786 \
-    --hash=sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8 \
-    --hash=sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09 \
-    --hash=sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185 \
-    --hash=sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574 \
-    --hash=sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e \
-    --hash=sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519 \
-    --hash=sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898 \
-    --hash=sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269 \
-    --hash=sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3 \
-    --hash=sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f \
-    --hash=sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6 \
-    --hash=sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8 \
-    --hash=sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a \
-    --hash=sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73 \
-    --hash=sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc \
-    --hash=sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714 \
-    --hash=sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2 \
-    --hash=sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc \
-    --hash=sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce \
-    --hash=sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d \
-    --hash=sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e \
-    --hash=sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6 \
-    --hash=sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269 \
-    --hash=sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96 \
-    --hash=sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d \
-    --hash=sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a \
-    --hash=sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4 \
-    --hash=sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77 \
-    --hash=sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d \
-    --hash=sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0 \
-    --hash=sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed \
-    --hash=sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068 \
-    --hash=sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac \
-    --hash=sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25 \
-    --hash=sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8 \
-    --hash=sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab \
-    --hash=sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26 \
-    --hash=sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2 \
-    --hash=sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db \
-    --hash=sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f \
-    --hash=sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5 \
-    --hash=sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99 \
-    --hash=sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c \
-    --hash=sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d \
-    --hash=sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811 \
-    --hash=sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa \
-    --hash=sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a \
-    --hash=sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03 \
-    --hash=sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b \
-    --hash=sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04 \
-    --hash=sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c \
-    --hash=sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001 \
-    --hash=sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458 \
-    --hash=sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389 \
-    --hash=sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99 \
-    --hash=sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985 \
-    --hash=sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537 \
-    --hash=sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238 \
-    --hash=sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f \
-    --hash=sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d \
-    --hash=sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796 \
-    --hash=sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a \
-    --hash=sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143 \
-    --hash=sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8 \
-    --hash=sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c \
-    --hash=sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5 \
-    --hash=sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5 \
-    --hash=sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711 \
-    --hash=sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4 \
-    --hash=sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6 \
-    --hash=sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c \
-    --hash=sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7 \
-    --hash=sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4 \
-    --hash=sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b \
-    --hash=sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae \
-    --hash=sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12 \
-    --hash=sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c \
-    --hash=sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae \
-    --hash=sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8 \
-    --hash=sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887 \
-    --hash=sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b \
-    --hash=sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4 \
-    --hash=sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f \
-    --hash=sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5 \
-    --hash=sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33 \
-    --hash=sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519 \
-    --hash=sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561
+charset-normalizer==3.4.2 \
+    --hash=sha256:005fa3432484527f9732ebd315da8da8001593e2cf46a3d817669f062c3d9ed4 \
+    --hash=sha256:046595208aae0120559a67693ecc65dd75d46f7bf687f159127046628178dc45 \
+    --hash=sha256:0c29de6a1a95f24b9a1aa7aefd27d2487263f00dfd55a77719b530788f75cff7 \
+    --hash=sha256:0c8c57f84ccfc871a48a47321cfa49ae1df56cd1d965a09abe84066f6853b9c0 \
+    --hash=sha256:0f5d9ed7f254402c9e7d35d2f5972c9bbea9040e99cd2861bd77dc68263277c7 \
+    --hash=sha256:18dd2e350387c87dabe711b86f83c9c78af772c748904d372ade190b5c7c9d4d \
+    --hash=sha256:1b1bde144d98e446b056ef98e59c256e9294f6b74d7af6846bf5ffdafd687a7d \
+    --hash=sha256:1c95a1e2902a8b722868587c0e1184ad5c55631de5afc0eb96bc4b0d738092c0 \
+    --hash=sha256:1cad5f45b3146325bb38d6855642f6fd609c3f7cad4dbaf75549bf3b904d3184 \
+    --hash=sha256:21b2899062867b0e1fde9b724f8aecb1af14f2778d69aacd1a5a1853a597a5db \
+    --hash=sha256:24498ba8ed6c2e0b56d4acbf83f2d989720a93b41d712ebd4f4979660db4417b \
+    --hash=sha256:25a23ea5c7edc53e0f29bae2c44fcb5a1aa10591aae107f2a2b2583a9c5cbc64 \
+    --hash=sha256:289200a18fa698949d2b39c671c2cc7a24d44096784e76614899a7ccf2574b7b \
+    --hash=sha256:28a1005facc94196e1fb3e82a3d442a9d9110b8434fc1ded7a24a2983c9888d8 \
+    --hash=sha256:32fc0341d72e0f73f80acb0a2c94216bd704f4f0bce10aedea38f30502b271ff \
+    --hash=sha256:36b31da18b8890a76ec181c3cf44326bf2c48e36d393ca1b72b3f484113ea344 \
+    --hash=sha256:3c21d4fca343c805a52c0c78edc01e3477f6dd1ad7c47653241cf2a206d4fc58 \
+    --hash=sha256:3fddb7e2c84ac87ac3a947cb4e66d143ca5863ef48e4a5ecb83bd48619e4634e \
+    --hash=sha256:43e0933a0eff183ee85833f341ec567c0980dae57c464d8a508e1b2ceb336471 \
+    --hash=sha256:4a476b06fbcf359ad25d34a057b7219281286ae2477cc5ff5e3f70a246971148 \
+    --hash=sha256:4e594135de17ab3866138f496755f302b72157d115086d100c3f19370839dd3a \
+    --hash=sha256:50bf98d5e563b83cc29471fa114366e6806bc06bc7a25fd59641e41445327836 \
+    --hash=sha256:5a9979887252a82fefd3d3ed2a8e3b937a7a809f65dcb1e068b090e165bbe99e \
+    --hash=sha256:5baececa9ecba31eff645232d59845c07aa030f0c81ee70184a90d35099a0e63 \
+    --hash=sha256:5bf4545e3b962767e5c06fe1738f951f77d27967cb2caa64c28be7c4563e162c \
+    --hash=sha256:6333b3aa5a12c26b2a4d4e7335a28f1475e0e5e17d69d55141ee3cab736f66d1 \
+    --hash=sha256:65c981bdbd3f57670af8b59777cbfae75364b483fa8a9f420f08094531d54a01 \
+    --hash=sha256:68a328e5f55ec37c57f19ebb1fdc56a248db2e3e9ad769919a58672958e8f366 \
+    --hash=sha256:6a0289e4589e8bdfef02a80478f1dfcb14f0ab696b5a00e1f4b8a14a307a3c58 \
+    --hash=sha256:6b66f92b17849b85cad91259efc341dce9c1af48e2173bf38a85c6329f1033e5 \
+    --hash=sha256:6c9379d65defcab82d07b2a9dfbfc2e95bc8fe0ebb1b176a3190230a3ef0e07c \
+    --hash=sha256:6fc1f5b51fa4cecaa18f2bd7a003f3dd039dd615cd69a2afd6d3b19aed6775f2 \
+    --hash=sha256:70f7172939fdf8790425ba31915bfbe8335030f05b9913d7ae00a87d4395620a \
+    --hash=sha256:721c76e84fe669be19c5791da68232ca2e05ba5185575086e384352e2c309597 \
+    --hash=sha256:7222ffd5e4de8e57e03ce2cef95a4c43c98fcb72ad86909abdfc2c17d227fc1b \
+    --hash=sha256:75d10d37a47afee94919c4fab4c22b9bc2a8bf7d4f46f87363bcf0573f3ff4f5 \
+    --hash=sha256:76af085e67e56c8816c3ccf256ebd136def2ed9654525348cfa744b6802b69eb \
+    --hash=sha256:770cab594ecf99ae64c236bc9ee3439c3f46be49796e265ce0cc8bc17b10294f \
+    --hash=sha256:7a6ab32f7210554a96cd9e33abe3ddd86732beeafc7a28e9955cdf22ffadbab0 \
+    --hash=sha256:7c48ed483eb946e6c04ccbe02c6b4d1d48e51944b6db70f697e089c193404941 \
+    --hash=sha256:7f56930ab0abd1c45cd15be65cc741c28b1c9a34876ce8c17a2fa107810c0af0 \
+    --hash=sha256:8075c35cd58273fee266c58c0c9b670947c19df5fb98e7b66710e04ad4e9ff86 \
+    --hash=sha256:8272b73e1c5603666618805fe821edba66892e2870058c94c53147602eab29c7 \
+    --hash=sha256:82d8fd25b7f4675d0c47cf95b594d4e7b158aca33b76aa63d07186e13c0e0ab7 \
+    --hash=sha256:844da2b5728b5ce0e32d863af26f32b5ce61bc4273a9c720a9f3aa9df73b1455 \
+    --hash=sha256:8755483f3c00d6c9a77f490c17e6ab0c8729e39e6390328e42521ef175380ae6 \
+    --hash=sha256:915f3849a011c1f593ab99092f3cecfcb4d65d8feb4a64cf1bf2d22074dc0ec4 \
+    --hash=sha256:926ca93accd5d36ccdabd803392ddc3e03e6d4cd1cf17deff3b989ab8e9dbcf0 \
+    --hash=sha256:982bb1e8b4ffda883b3d0a521e23abcd6fd17418f6d2c4118d257a10199c0ce3 \
+    --hash=sha256:98f862da73774290f251b9df8d11161b6cf25b599a66baf087c1ffe340e9bfd1 \
+    --hash=sha256:9cbfacf36cb0ec2897ce0ebc5d08ca44213af24265bd56eca54bee7923c48fd6 \
+    --hash=sha256:a370b3e078e418187da8c3674eddb9d983ec09445c99a3a263c2011993522981 \
+    --hash=sha256:a955b438e62efdf7e0b7b52a64dc5c3396e2634baa62471768a64bc2adb73d5c \
+    --hash=sha256:aa6af9e7d59f9c12b33ae4e9450619cf2488e2bbe9b44030905877f0b2324980 \
+    --hash=sha256:aa88ca0b1932e93f2d961bf3addbb2db902198dca337d88c89e1559e066e7645 \
+    --hash=sha256:aaeeb6a479c7667fbe1099af9617c83aaca22182d6cf8c53966491a0f1b7ffb7 \
+    --hash=sha256:aaf27faa992bfee0264dc1f03f4c75e9fcdda66a519db6b957a3f826e285cf12 \
+    --hash=sha256:b2680962a4848b3c4f155dc2ee64505a9c57186d0d56b43123b17ca3de18f0fa \
+    --hash=sha256:b2d318c11350e10662026ad0eb71bb51c7812fc8590825304ae0bdd4ac283acd \
+    --hash=sha256:b33de11b92e9f75a2b545d6e9b6f37e398d86c3e9e9653c4864eb7e89c5773ef \
+    --hash=sha256:b3daeac64d5b371dea99714f08ffc2c208522ec6b06fbc7866a450dd446f5c0f \
+    --hash=sha256:be1e352acbe3c78727a16a455126d9ff83ea2dfdcbc83148d2982305a04714c2 \
+    --hash=sha256:bee093bf902e1d8fc0ac143c88902c3dfc8941f7ea1d6a8dd2bcb786d33db03d \
+    --hash=sha256:c72fbbe68c6f32f251bdc08b8611c7b3060612236e960ef848e0a517ddbe76c5 \
+    --hash=sha256:c9e36a97bee9b86ef9a1cf7bb96747eb7a15c2f22bdb5b516434b00f2a599f02 \
+    --hash=sha256:cddf7bd982eaa998934a91f69d182aec997c6c468898efe6679af88283b498d3 \
+    --hash=sha256:cf713fe9a71ef6fd5adf7a79670135081cd4431c2943864757f0fa3a65b1fafd \
+    --hash=sha256:d11b54acf878eef558599658b0ffca78138c8c3655cf4f3a4a673c437e67732e \
+    --hash=sha256:d41c4d287cfc69060fa91cae9683eacffad989f1a10811995fa309df656ec214 \
+    --hash=sha256:d524ba3f1581b35c03cb42beebab4a13e6cdad7b36246bd22541fa585a56cccd \
+    --hash=sha256:daac4765328a919a805fa5e2720f3e94767abd632ae410a9062dff5412bae65a \
+    --hash=sha256:db4c7bf0e07fc3b7d89ac2a5880a6a8062056801b83ff56d8464b70f65482b6c \
+    --hash=sha256:dc7039885fa1baf9be153a0626e337aa7ec8bf96b0128605fb0d77788ddc1681 \
+    --hash=sha256:dccab8d5fa1ef9bfba0590ecf4d46df048d18ffe3eec01eeb73a42e0d9e7a8ba \
+    --hash=sha256:dedb8adb91d11846ee08bec4c8236c8549ac721c245678282dcb06b221aab59f \
+    --hash=sha256:e45ba65510e2647721e35323d6ef54c7974959f6081b58d4ef5d87c60c84919a \
+    --hash=sha256:e53efc7c7cee4c1e70661e2e112ca46a575f90ed9ae3fef200f2a25e954f4b28 \
+    --hash=sha256:e635b87f01ebc977342e2697d05b56632f5f879a4f15955dfe8cef2448b51691 \
+    --hash=sha256:e70e990b2137b29dc5564715de1e12701815dacc1d056308e2b17e9095372a82 \
+    --hash=sha256:e8082b26888e2f8b36a042a58307d5b917ef2b1cacab921ad3323ef91901c71a \
+    --hash=sha256:e8323a9b031aa0393768b87f04b4164a40037fb2a3c11ac06a03ffecd3618027 \
+    --hash=sha256:e92fca20c46e9f5e1bb485887d074918b13543b1c2a1185e69bb8d17ab6236a7 \
+    --hash=sha256:eb30abc20df9ab0814b5a2524f23d75dcf83cde762c161917a2b4b7b55b1e518 \
+    --hash=sha256:eba9904b0f38a143592d9fc0e19e2df0fa2e41c3c3745554761c5f6447eedabf \
+    --hash=sha256:ef8de666d6179b009dce7bcb2ad4c4a779f113f12caf8dc77f0162c29d20490b \
+    --hash=sha256:efd387a49825780ff861998cd959767800d54f8308936b21025326de4b5a42b9 \
+    --hash=sha256:f0aa37f3c979cf2546b73e8222bbfa3dc07a641585340179d768068e3455e544 \
+    --hash=sha256:f4074c5a429281bf056ddd4c5d3b740ebca4d43ffffe2ef4bf4d2d05114299da \
+    --hash=sha256:f69a27e45c43520f5487f27627059b64aaf160415589230992cec34c5e18a509 \
+    --hash=sha256:fb707f3e15060adf5b7ada797624a6c6e0138e2a26baa089df64c68ee98e040f \
+    --hash=sha256:fcbe676a55d7445b22c10967bceaaf0ee69407fbe0ece4d032b6eb8d4565982a \
+    --hash=sha256:fdb20a30fe1175ecabed17cbf7812f7b804b8a315a25f24678bcdf120a90077f
     # via requests
-docker==7.0.0 \
-    --hash=sha256:12ba681f2777a0ad28ffbcc846a69c31b4dfd9752b47eb425a274ee269c5e14b \
-    --hash=sha256:323736fb92cd9418fc5e7133bc953e11a9da04f4483f828b527db553f1e7e5a3
+docker==7.1.0 \
+    --hash=sha256:ad8c70e6e3f8926cb8a92619b832b4ea5299e2831c14284663184e200546fa6c \
+    --hash=sha256:c96b93b7f0a746f9e77d325bcfb87422a3d8bd4f03136ae8a85b37f1898d5fc0
     # via -r requirements.in
-idna==3.6 \
-    --hash=sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca \
-    --hash=sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f
+idna==3.10 \
+    --hash=sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9 \
+    --hash=sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3
     # via requests
 jinja2==3.1.6 \
     --hash=sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d \
     --hash=sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67
     # via -r requirements.in
-jsonschema==4.21.1 \
-    --hash=sha256:7996507afae316306f9e2290407761157c6f78002dcf7419acb99822143d1c6f \
-    --hash=sha256:85727c00279f5fa6bedbe6238d2aa6403bedd8b4864ab11207d07df3cc1b2ee5
+jsonschema==4.24.0 \
+    --hash=sha256:0b4e8069eb12aedfa881333004bccaec24ecef5a8a6a4b6df142b2cc9599d196 \
+    --hash=sha256:a462455f19f5faf404a7902952b6f0e3ce868f3ee09a359b05eca6673bd8412d
     # via -r requirements.in
-jsonschema-specifications==2023.12.1 \
-    --hash=sha256:48a76787b3e70f5ed53f1160d2b81f586e4ca6d1548c5de7085d1682674764cc \
-    --hash=sha256:87e4fdf3a94858b8a2ba2778d9ba57d8a9cafca7c7489c46ba0d30a8bc6a9c3c
+jsonschema-specifications==2025.4.1 \
+    --hash=sha256:4653bffbd6584f7de83a67e0d620ef16900b390ddc7939d56684d6c81e33f1af \
+    --hash=sha256:630159c9f4dbea161a6a2205c3011cc4f18ff381b189fff48bb39b9bf26ae608
     # via jsonschema
-markupsafe==2.1.5 \
-    --hash=sha256:00e046b6dd71aa03a41079792f8473dc494d564611a8f89bbbd7cb93295ebdcf \
-    --hash=sha256:075202fa5b72c86ad32dc7d0b56024ebdbcf2048c0ba09f1cde31bfdd57bcfff \
-    --hash=sha256:0e397ac966fdf721b2c528cf028494e86172b4feba51d65f81ffd65c63798f3f \
-    --hash=sha256:17b950fccb810b3293638215058e432159d2b71005c74371d784862b7e4683f3 \
-    --hash=sha256:1f3fbcb7ef1f16e48246f704ab79d79da8a46891e2da03f8783a5b6fa41a9532 \
-    --hash=sha256:2174c595a0d73a3080ca3257b40096db99799265e1c27cc5a610743acd86d62f \
-    --hash=sha256:2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617 \
-    --hash=sha256:2d2d793e36e230fd32babe143b04cec8a8b3eb8a3122d2aceb4a371e6b09b8df \
-    --hash=sha256:30b600cf0a7ac9234b2638fbc0fb6158ba5bdcdf46aeb631ead21248b9affbc4 \
-    --hash=sha256:397081c1a0bfb5124355710fe79478cdbeb39626492b15d399526ae53422b906 \
-    --hash=sha256:3a57fdd7ce31c7ff06cdfbf31dafa96cc533c21e443d57f5b1ecc6cdc668ec7f \
-    --hash=sha256:3c6b973f22eb18a789b1460b4b91bf04ae3f0c4234a0a6aa6b0a92f6f7b951d4 \
-    --hash=sha256:3e53af139f8579a6d5f7b76549125f0d94d7e630761a2111bc431fd820e163b8 \
-    --hash=sha256:4096e9de5c6fdf43fb4f04c26fb114f61ef0bf2e5604b6ee3019d51b69e8c371 \
-    --hash=sha256:4275d846e41ecefa46e2015117a9f491e57a71ddd59bbead77e904dc02b1bed2 \
-    --hash=sha256:4c31f53cdae6ecfa91a77820e8b151dba54ab528ba65dfd235c80b086d68a465 \
-    --hash=sha256:4f11aa001c540f62c6166c7726f71f7573b52c68c31f014c25cc7901deea0b52 \
-    --hash=sha256:5049256f536511ee3f7e1b3f87d1d1209d327e818e6ae1365e8653d7e3abb6a6 \
-    --hash=sha256:58c98fee265677f63a4385256a6d7683ab1832f3ddd1e66fe948d5880c21a169 \
-    --hash=sha256:598e3276b64aff0e7b3451b72e94fa3c238d452e7ddcd893c3ab324717456bad \
-    --hash=sha256:5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2 \
-    --hash=sha256:5dedb4db619ba5a2787a94d877bc8ffc0566f92a01c0ef214865e54ecc9ee5e0 \
-    --hash=sha256:619bc166c4f2de5caa5a633b8b7326fbe98e0ccbfacabd87268a2b15ff73a029 \
-    --hash=sha256:629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f \
-    --hash=sha256:656f7526c69fac7f600bd1f400991cc282b417d17539a1b228617081106feb4a \
-    --hash=sha256:6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced \
-    --hash=sha256:72b6be590cc35924b02c78ef34b467da4ba07e4e0f0454a2c5907f473fc50ce5 \
-    --hash=sha256:7502934a33b54030eaf1194c21c692a534196063db72176b0c4028e140f8f32c \
-    --hash=sha256:7a68b554d356a91cce1236aa7682dc01df0edba8d043fd1ce607c49dd3c1edcf \
-    --hash=sha256:7b2e5a267c855eea6b4283940daa6e88a285f5f2a67f2220203786dfa59b37e9 \
-    --hash=sha256:823b65d8706e32ad2df51ed89496147a42a2a6e01c13cfb6ffb8b1e92bc910bb \
-    --hash=sha256:8590b4ae07a35970728874632fed7bd57b26b0102df2d2b233b6d9d82f6c62ad \
-    --hash=sha256:8dd717634f5a044f860435c1d8c16a270ddf0ef8588d4887037c5028b859b0c3 \
-    --hash=sha256:8dec4936e9c3100156f8a2dc89c4b88d5c435175ff03413b443469c7c8c5f4d1 \
-    --hash=sha256:97cafb1f3cbcd3fd2b6fbfb99ae11cdb14deea0736fc2b0952ee177f2b813a46 \
-    --hash=sha256:a17a92de5231666cfbe003f0e4b9b3a7ae3afb1ec2845aadc2bacc93ff85febc \
-    --hash=sha256:a549b9c31bec33820e885335b451286e2969a2d9e24879f83fe904a5ce59d70a \
-    --hash=sha256:ac07bad82163452a6884fe8fa0963fb98c2346ba78d779ec06bd7a6262132aee \
-    --hash=sha256:ae2ad8ae6ebee9d2d94b17fb62763125f3f374c25618198f40cbb8b525411900 \
-    --hash=sha256:b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5 \
-    --hash=sha256:bc1667f8b83f48511b94671e0e441401371dfd0f0a795c7daa4a3cd1dde55bea \
-    --hash=sha256:bec0a414d016ac1a18862a519e54b2fd0fc8bbfd6890376898a6c0891dd82e9f \
-    --hash=sha256:bf50cd79a75d181c9181df03572cdce0fbb75cc353bc350712073108cba98de5 \
-    --hash=sha256:bff1b4290a66b490a2f4719358c0cdcd9bafb6b8f061e45c7a2460866bf50c2e \
-    --hash=sha256:c061bb86a71b42465156a3ee7bd58c8c2ceacdbeb95d05a99893e08b8467359a \
-    --hash=sha256:c8b29db45f8fe46ad280a7294f5c3ec36dbac9491f2d1c17345be8e69cc5928f \
-    --hash=sha256:ce409136744f6521e39fd8e2a24c53fa18ad67aa5bc7c2cf83645cce5b5c4e50 \
-    --hash=sha256:d050b3361367a06d752db6ead6e7edeb0009be66bc3bae0ee9d97fb326badc2a \
-    --hash=sha256:d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b \
-    --hash=sha256:d9fad5155d72433c921b782e58892377c44bd6252b5af2f67f16b194987338a4 \
-    --hash=sha256:daa4ee5a243f0f20d528d939d06670a298dd39b1ad5f8a72a4275124a7819eff \
-    --hash=sha256:db0b55e0f3cc0be60c1f19efdde9a637c32740486004f20d1cff53c3c0ece4d2 \
-    --hash=sha256:e61659ba32cf2cf1481e575d0462554625196a1f2fc06a1c777d3f48e8865d46 \
-    --hash=sha256:ea3d8a3d18833cf4304cd2fc9cbb1efe188ca9b5efef2bdac7adc20594a0e46b \
-    --hash=sha256:ec6a563cff360b50eed26f13adc43e61bc0c04d94b8be985e6fb24b81f6dcfdf \
-    --hash=sha256:f5dfb42c4604dddc8e4305050aa6deb084540643ed5804d7455b5df8fe16f5e5 \
-    --hash=sha256:fa173ec60341d6bb97a89f5ea19c85c5643c1e7dedebc22f5181eb73573142c5 \
-    --hash=sha256:fa9db3f79de01457b03d4f01b34cf91bc0048eb2c3846ff26f66687c2f6d16ab \
-    --hash=sha256:fce659a462a1be54d2ffcacea5e3ba2d74daa74f30f5f143fe0c58636e355fdd \
-    --hash=sha256:ffee1f21e5ef0d712f9033568f8344d5da8cc2869dbd08d87c84656e6a2d2f68
+markupsafe==3.0.2 \
+    --hash=sha256:0bff5e0ae4ef2e1ae4fdf2dfd5b76c75e5c2fa4132d05fc1b0dabcd20c7e28c4 \
+    --hash=sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30 \
+    --hash=sha256:1225beacc926f536dc82e45f8a4d68502949dc67eea90eab715dea3a21c1b5f0 \
+    --hash=sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9 \
+    --hash=sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396 \
+    --hash=sha256:1a9d3f5f0901fdec14d8d2f66ef7d035f2157240a433441719ac9a3fba440b13 \
+    --hash=sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028 \
+    --hash=sha256:1e084f686b92e5b83186b07e8a17fc09e38fff551f3602b249881fec658d3eca \
+    --hash=sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557 \
+    --hash=sha256:2cb8438c3cbb25e220c2ab33bb226559e7afb3baec11c4f218ffa7308603c832 \
+    --hash=sha256:3169b1eefae027567d1ce6ee7cae382c57fe26e82775f460f0b2778beaad66c0 \
+    --hash=sha256:3809ede931876f5b2ec92eef964286840ed3540dadf803dd570c3b7e13141a3b \
+    --hash=sha256:38a9ef736c01fccdd6600705b09dc574584b89bea478200c5fbf112a6b0d5579 \
+    --hash=sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a \
+    --hash=sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c \
+    --hash=sha256:48032821bbdf20f5799ff537c7ac3d1fba0ba032cfc06194faffa8cda8b560ff \
+    --hash=sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c \
+    --hash=sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22 \
+    --hash=sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094 \
+    --hash=sha256:57cb5a3cf367aeb1d316576250f65edec5bb3be939e9247ae594b4bcbc317dfb \
+    --hash=sha256:5b02fb34468b6aaa40dfc198d813a641e3a63b98c2b05a16b9f80b7ec314185e \
+    --hash=sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5 \
+    --hash=sha256:6af100e168aa82a50e186c82875a5893c5597a0c1ccdb0d8b40240b1f28b969a \
+    --hash=sha256:6c89876f41da747c8d3677a2b540fb32ef5715f97b66eeb0c6b66f5e3ef6f59d \
+    --hash=sha256:6e296a513ca3d94054c2c881cc913116e90fd030ad1c656b3869762b754f5f8a \
+    --hash=sha256:70a87b411535ccad5ef2f1df5136506a10775d267e197e4cf531ced10537bd6b \
+    --hash=sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8 \
+    --hash=sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225 \
+    --hash=sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c \
+    --hash=sha256:88b49a3b9ff31e19998750c38e030fc7bb937398b1f78cfa599aaef92d693144 \
+    --hash=sha256:8c4e8c3ce11e1f92f6536ff07154f9d49677ebaaafc32db9db4620bc11ed480f \
+    --hash=sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87 \
+    --hash=sha256:9025b4018f3a1314059769c7bf15441064b2207cb3f065e6ea1e7359cb46db9d \
+    --hash=sha256:93335ca3812df2f366e80509ae119189886b0f3c2b81325d39efdb84a1e2ae93 \
+    --hash=sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf \
+    --hash=sha256:9e2d922824181480953426608b81967de705c3cef4d1af983af849d7bd619158 \
+    --hash=sha256:a123e330ef0853c6e822384873bef7507557d8e4a082961e1defa947aa59ba84 \
+    --hash=sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb \
+    --hash=sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48 \
+    --hash=sha256:b424c77b206d63d500bcb69fa55ed8d0e6a3774056bdc4839fc9298a7edca171 \
+    --hash=sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c \
+    --hash=sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6 \
+    --hash=sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd \
+    --hash=sha256:bbcb445fa71794da8f178f0f6d66789a28d7319071af7a496d4d507ed566270d \
+    --hash=sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1 \
+    --hash=sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d \
+    --hash=sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca \
+    --hash=sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a \
+    --hash=sha256:cfad01eed2c2e0c01fd0ecd2ef42c492f7f93902e39a42fc9ee1692961443a29 \
+    --hash=sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe \
+    --hash=sha256:d8213e09c917a951de9d09ecee036d5c7d36cb6cb7dbaece4c71a60d79fb9798 \
+    --hash=sha256:e07c3764494e3776c602c1e78e298937c3315ccc9043ead7e685b7f2b8d47b3c \
+    --hash=sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8 \
+    --hash=sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f \
+    --hash=sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f \
+    --hash=sha256:eaa0a10b7f72326f1372a713e73c3f739b524b3af41feb43e4921cb529f5929a \
+    --hash=sha256:eb7972a85c54febfb25b5c4b4f3af4dcc731994c7da0d8a0b4a6eb0640e1d178 \
+    --hash=sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0 \
+    --hash=sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79 \
+    --hash=sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430 \
+    --hash=sha256:fcabf5ff6eea076f859677f5f0b6b5c1a51e70a376b0579e0eadef8db48c6b50
     # via jinja2
-packaging==23.2 \
-    --hash=sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5 \
-    --hash=sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7
-    # via docker
-pywin32==308 \
-    --hash=sha256:00b3e11ef09ede56c6a43c71f2d31857cf7c54b0ab6e78ac659497abd2834f47 \
-    --hash=sha256:100a5442b7332070983c4cd03f2e906a5648a5104b8a7f50175f7906efd16bb6 \
-    --hash=sha256:13dcb914ed4347019fbec6697a01a0aec61019c1046c2b905410d197856326a6 \
-    --hash=sha256:1c44539a37a5b7b21d02ab34e6a4d314e0788f1690d65b48e9b0b89f31abbbed \
-    --hash=sha256:1f696ab352a2ddd63bd07430080dd598e6369152ea13a25ebcdd2f503a38f1ff \
-    --hash=sha256:3b92622e29d651c6b783e368ba7d6722b1634b8e70bd376fd7610fe1992e19de \
-    --hash=sha256:4fc888c59b3c0bef905ce7eb7e2106a07712015ea1c8234b703a088d46110e8e \
-    --hash=sha256:575621b90f0dc2695fec346b2d6302faebd4f0f45c05ea29404cefe35d89442b \
-    --hash=sha256:5794e764ebcabf4ff08c555b31bd348c9025929371763b2183172ff4708152f0 \
-    --hash=sha256:587f3e19696f4bf96fde9d8a57cec74a57021ad5f204c9e627e15c33ff568897 \
-    --hash=sha256:5d8c8015b24a7d6855b1550d8e660d8daa09983c80e5daf89a273e5c6fb5095a \
-    --hash=sha256:71b3322d949b4cc20776436a9c9ba0eeedcbc9c650daa536df63f0ff111bb920 \
-    --hash=sha256:7873ca4dc60ab3287919881a7d4f88baee4a6e639aa6962de25a98ba6b193341 \
-    --hash=sha256:796ff4426437896550d2981b9c2ac0ffd75238ad9ea2d3bfa67a1abd546d262e \
-    --hash=sha256:9b4de86c8d909aed15b7011182c8cab38c8850de36e6afb1f0db22b8959e3091 \
-    --hash=sha256:a5ab5381813b40f264fa3495b98af850098f814a25a63589a8e9eb12560f450c \
-    --hash=sha256:ef313c46d4c18dfb82a2431e3051ac8f112ccee1a34f29c263c583c568db63cd \
-    --hash=sha256:fd380990e792eaf6827fcb7e187b2b4b1cede0585e3d0c9e84201ec27b9905e4
+pywin32==310 \
+    --hash=sha256:0867beb8addefa2e3979d4084352e4ac6e991ca45373390775f7084cc0209b9c \
+    --hash=sha256:126298077a9d7c95c53823934f000599f66ec9296b09167810eb24875f32689c \
+    --hash=sha256:19ec5fc9b1d51c4350be7bb00760ffce46e6c95eaf2f0b2f1150657b1a43c582 \
+    --hash=sha256:1e765f9564e83011a63321bb9d27ec456a0ed90d3732c4b2e312b855365ed8bd \
+    --hash=sha256:2349cc906eae872d0663d4d6290d13b90621eaf78964bb1578632ff20e152966 \
+    --hash=sha256:30f0a9b3138fb5e07eb4973b7077e1883f558e40c578c6925acc7a94c34eaa36 \
+    --hash=sha256:33babed0cf0c92a6f94cc6cc13546ab24ee13e3e800e61ed87609ab91e4c8213 \
+    --hash=sha256:5d241a659c496ada3253cd01cfaa779b048e90ce4b2b38cd44168ad555ce74ab \
+    --hash=sha256:667827eb3a90208ddbdcc9e860c81bde63a135710e21e4cb3348968e4bd5249e \
+    --hash=sha256:6dd97011efc8bf51d6793a82292419eba2c71cf8e7250cfac03bba284454abc1 \
+    --hash=sha256:851c8d927af0d879221e616ae1f66145253537bbdd321a77e8ef701b443a9a1a \
+    --hash=sha256:8a75a5cc3893e83a108c05d82198880704c44bbaee4d06e442e471d3c9ea4f3d \
+    --hash=sha256:96867217335559ac619f00ad70e513c0fcf84b8a3af9fc2bba3b59b97da70475 \
+    --hash=sha256:bf5c397c9a9a19a6f62f3fb821fbf36cac08f03770056711f765ec1503972060 \
+    --hash=sha256:c3e78706e4229b915a0821941a84e7ef420bf2b77e08c9dae3c76fd03fd2ae3d \
+    --hash=sha256:e308f831de771482b7cf692a1f308f8fca701b2d8f9dde6cc440c7da17e47b33
     # via docker
 pyyaml==6.0.1 \
     --hash=sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5 \
@@ -261,178 +258,281 @@ pyyaml==6.0.1 \
     --hash=sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d \
     --hash=sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f
     # via -r requirements.in
-referencing==0.33.0 \
-    --hash=sha256:39240f2ecc770258f28b642dd47fd74bc8b02484de54e1882b74b35ebd779bd5 \
-    --hash=sha256:c775fedf74bc0f9189c2a3be1c12fd03e8c23f4d371dce795df44e06c5b412f7
+referencing==0.36.2 \
+    --hash=sha256:df2e89862cd09deabbdba16944cc3f10feb6b3e6f18e902f7cc25609a34775aa \
+    --hash=sha256:e8699adbbf8b5c7de96d8ffa0eb5c158b3beafce084968e2ea8bb08c6794dcd0
     # via
     #   jsonschema
     #   jsonschema-specifications
-requests==2.32.2 \
-    --hash=sha256:dd951ff5ecf3e3b3aa26b40703ba77495dab41da839ae72ef3c8e5d8e2433289 \
-    --hash=sha256:fc06670dd0ed212426dfeb94fc1b983d917c4f9847c863f313c9dfaaffb7c23c
+requests==2.32.3 \
+    --hash=sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760 \
+    --hash=sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6
     # via docker
-rpds-py==0.18.0 \
-    --hash=sha256:01e36a39af54a30f28b73096dd39b6802eddd04c90dbe161c1b8dbe22353189f \
-    --hash=sha256:044a3e61a7c2dafacae99d1e722cc2d4c05280790ec5a05031b3876809d89a5c \
-    --hash=sha256:08231ac30a842bd04daabc4d71fddd7e6d26189406d5a69535638e4dcb88fe76 \
-    --hash=sha256:08f9ad53c3f31dfb4baa00da22f1e862900f45908383c062c27628754af2e88e \
-    --hash=sha256:0ab39c1ba9023914297dd88ec3b3b3c3f33671baeb6acf82ad7ce883f6e8e157 \
-    --hash=sha256:0af039631b6de0397ab2ba16eaf2872e9f8fca391b44d3d8cac317860a700a3f \
-    --hash=sha256:0b8612cd233543a3781bc659c731b9d607de65890085098986dfd573fc2befe5 \
-    --hash=sha256:11a8c85ef4a07a7638180bf04fe189d12757c696eb41f310d2426895356dcf05 \
-    --hash=sha256:1374f4129f9bcca53a1bba0bb86bf78325a0374577cf7e9e4cd046b1e6f20e24 \
-    --hash=sha256:1d4acf42190d449d5e89654d5c1ed3a4f17925eec71f05e2a41414689cda02d1 \
-    --hash=sha256:1d9a5be316c15ffb2b3c405c4ff14448c36b4435be062a7f578ccd8b01f0c4d8 \
-    --hash=sha256:1df3659d26f539ac74fb3b0c481cdf9d725386e3552c6fa2974f4d33d78e544b \
-    --hash=sha256:22806714311a69fd0af9b35b7be97c18a0fc2826e6827dbb3a8c94eac6cf7eeb \
-    --hash=sha256:2644e47de560eb7bd55c20fc59f6daa04682655c58d08185a9b95c1970fa1e07 \
-    --hash=sha256:2e6d75ab12b0bbab7215e5d40f1e5b738aa539598db27ef83b2ec46747df90e1 \
-    --hash=sha256:30f43887bbae0d49113cbaab729a112251a940e9b274536613097ab8b4899cf6 \
-    --hash=sha256:34b18ba135c687f4dac449aa5157d36e2cbb7c03cbea4ddbd88604e076aa836e \
-    --hash=sha256:36b3ee798c58ace201289024b52788161e1ea133e4ac93fba7d49da5fec0ef9e \
-    --hash=sha256:39514da80f971362f9267c600b6d459bfbbc549cffc2cef8e47474fddc9b45b1 \
-    --hash=sha256:39f5441553f1c2aed4de4377178ad8ff8f9d733723d6c66d983d75341de265ab \
-    --hash=sha256:3a96e0c6a41dcdba3a0a581bbf6c44bb863f27c541547fb4b9711fd8cf0ffad4 \
-    --hash=sha256:3f26b5bd1079acdb0c7a5645e350fe54d16b17bfc5e71f371c449383d3342e17 \
-    --hash=sha256:41ef53e7c58aa4ef281da975f62c258950f54b76ec8e45941e93a3d1d8580594 \
-    --hash=sha256:42821446ee7a76f5d9f71f9e33a4fb2ffd724bb3e7f93386150b61a43115788d \
-    --hash=sha256:43fbac5f22e25bee1d482c97474f930a353542855f05c1161fd804c9dc74a09d \
-    --hash=sha256:4457a94da0d5c53dc4b3e4de1158bdab077db23c53232f37a3cb7afdb053a4e3 \
-    --hash=sha256:465a3eb5659338cf2a9243e50ad9b2296fa15061736d6e26240e713522b6235c \
-    --hash=sha256:482103aed1dfe2f3b71a58eff35ba105289b8d862551ea576bd15479aba01f66 \
-    --hash=sha256:4832d7d380477521a8c1644bbab6588dfedea5e30a7d967b5fb75977c45fd77f \
-    --hash=sha256:4901165d170a5fde6f589acb90a6b33629ad1ec976d4529e769c6f3d885e3e80 \
-    --hash=sha256:5307def11a35f5ae4581a0b658b0af8178c65c530e94893345bebf41cc139d33 \
-    --hash=sha256:5417558f6887e9b6b65b4527232553c139b57ec42c64570569b155262ac0754f \
-    --hash=sha256:56a737287efecafc16f6d067c2ea0117abadcd078d58721f967952db329a3e5c \
-    --hash=sha256:586f8204935b9ec884500498ccc91aa869fc652c40c093bd9e1471fbcc25c022 \
-    --hash=sha256:5b4e7d8d6c9b2e8ee2d55c90b59c707ca59bc30058269b3db7b1f8df5763557e \
-    --hash=sha256:5ddcba87675b6d509139d1b521e0c8250e967e63b5909a7e8f8944d0f90ff36f \
-    --hash=sha256:618a3d6cae6ef8ec88bb76dd80b83cfe415ad4f1d942ca2a903bf6b6ff97a2da \
-    --hash=sha256:635dc434ff724b178cb192c70016cc0ad25a275228f749ee0daf0eddbc8183b1 \
-    --hash=sha256:661d25cbffaf8cc42e971dd570d87cb29a665f49f4abe1f9e76be9a5182c4688 \
-    --hash=sha256:66e6a3af5a75363d2c9a48b07cb27c4ea542938b1a2e93b15a503cdfa8490795 \
-    --hash=sha256:67071a6171e92b6da534b8ae326505f7c18022c6f19072a81dcf40db2638767c \
-    --hash=sha256:685537e07897f173abcf67258bee3c05c374fa6fff89d4c7e42fb391b0605e98 \
-    --hash=sha256:69e64831e22a6b377772e7fb337533c365085b31619005802a79242fee620bc1 \
-    --hash=sha256:6b0817e34942b2ca527b0e9298373e7cc75f429e8da2055607f4931fded23e20 \
-    --hash=sha256:6c81e5f372cd0dc5dc4809553d34f832f60a46034a5f187756d9b90586c2c307 \
-    --hash=sha256:6d7faa6f14017c0b1e69f5e2c357b998731ea75a442ab3841c0dbbbfe902d2c4 \
-    --hash=sha256:6ef0befbb5d79cf32d0266f5cff01545602344eda89480e1dd88aca964260b18 \
-    --hash=sha256:6ef687afab047554a2d366e112dd187b62d261d49eb79b77e386f94644363294 \
-    --hash=sha256:7223a2a5fe0d217e60a60cdae28d6949140dde9c3bcc714063c5b463065e3d66 \
-    --hash=sha256:77f195baa60a54ef9d2de16fbbfd3ff8b04edc0c0140a761b56c267ac11aa467 \
-    --hash=sha256:793968759cd0d96cac1e367afd70c235867831983f876a53389ad869b043c948 \
-    --hash=sha256:7bd339195d84439cbe5771546fe8a4e8a7a045417d8f9de9a368c434e42a721e \
-    --hash=sha256:7cd863afe7336c62ec78d7d1349a2f34c007a3cc6c2369d667c65aeec412a5b1 \
-    --hash=sha256:7f2facbd386dd60cbbf1a794181e6aa0bd429bd78bfdf775436020172e2a23f0 \
-    --hash=sha256:84ffab12db93b5f6bad84c712c92060a2d321b35c3c9960b43d08d0f639d60d7 \
-    --hash=sha256:8c8370641f1a7f0e0669ddccca22f1da893cef7628396431eb445d46d893e5cd \
-    --hash=sha256:8db715ebe3bb7d86d77ac1826f7d67ec11a70dbd2376b7cc214199360517b641 \
-    --hash=sha256:8e8916ae4c720529e18afa0b879473049e95949bf97042e938530e072fde061d \
-    --hash=sha256:8f03bccbd8586e9dd37219bce4d4e0d3ab492e6b3b533e973fa08a112cb2ffc9 \
-    --hash=sha256:8f2fc11e8fe034ee3c34d316d0ad8808f45bc3b9ce5857ff29d513f3ff2923a1 \
-    --hash=sha256:923d39efa3cfb7279a0327e337a7958bff00cc447fd07a25cddb0a1cc9a6d2da \
-    --hash=sha256:93df1de2f7f7239dc9cc5a4a12408ee1598725036bd2dedadc14d94525192fc3 \
-    --hash=sha256:998e33ad22dc7ec7e030b3df701c43630b5bc0d8fbc2267653577e3fec279afa \
-    --hash=sha256:99f70b740dc04d09e6b2699b675874367885217a2e9f782bdf5395632ac663b7 \
-    --hash=sha256:9a00312dea9310d4cb7dbd7787e722d2e86a95c2db92fbd7d0155f97127bcb40 \
-    --hash=sha256:9d54553c1136b50fd12cc17e5b11ad07374c316df307e4cfd6441bea5fb68496 \
-    --hash=sha256:9dbbeb27f4e70bfd9eec1be5477517365afe05a9b2c441a0b21929ee61048124 \
-    --hash=sha256:a1ce3ba137ed54f83e56fb983a5859a27d43a40188ba798993812fed73c70836 \
-    --hash=sha256:a34d557a42aa28bd5c48a023c570219ba2593bcbbb8dc1b98d8cf5d529ab1434 \
-    --hash=sha256:a5f446dd5055667aabaee78487f2b5ab72e244f9bc0b2ffebfeec79051679984 \
-    --hash=sha256:ad36cfb355e24f1bd37cac88c112cd7730873f20fb0bdaf8ba59eedf8216079f \
-    --hash=sha256:aec493917dd45e3c69d00a8874e7cbed844efd935595ef78a0f25f14312e33c6 \
-    --hash=sha256:b316144e85316da2723f9d8dc75bada12fa58489a527091fa1d5a612643d1a0e \
-    --hash=sha256:b34ae4636dfc4e76a438ab826a0d1eed2589ca7d9a1b2d5bb546978ac6485461 \
-    --hash=sha256:b34b7aa8b261c1dbf7720b5d6f01f38243e9b9daf7e6b8bc1fd4657000062f2c \
-    --hash=sha256:bc362ee4e314870a70f4ae88772d72d877246537d9f8cb8f7eacf10884862432 \
-    --hash=sha256:bed88b9a458e354014d662d47e7a5baafd7ff81c780fd91584a10d6ec842cb73 \
-    --hash=sha256:c0013fe6b46aa496a6749c77e00a3eb07952832ad6166bd481c74bda0dcb6d58 \
-    --hash=sha256:c0b5dcf9193625afd8ecc92312d6ed78781c46ecbf39af9ad4681fc9f464af88 \
-    --hash=sha256:c4325ff0442a12113a6379af66978c3fe562f846763287ef66bdc1d57925d337 \
-    --hash=sha256:c463ed05f9dfb9baebef68048aed8dcdc94411e4bf3d33a39ba97e271624f8f7 \
-    --hash=sha256:c8362467a0fdeccd47935f22c256bec5e6abe543bf0d66e3d3d57a8fb5731863 \
-    --hash=sha256:cd5bf1af8efe569654bbef5a3e0a56eca45f87cfcffab31dd8dde70da5982475 \
-    --hash=sha256:cf1ea2e34868f6fbf070e1af291c8180480310173de0b0c43fc38a02929fc0e3 \
-    --hash=sha256:d62dec4976954a23d7f91f2f4530852b0c7608116c257833922a896101336c51 \
-    --hash=sha256:d68c93e381010662ab873fea609bf6c0f428b6d0bb00f2c6939782e0818d37bf \
-    --hash=sha256:d7c36232a90d4755b720fbd76739d8891732b18cf240a9c645d75f00639a9024 \
-    --hash=sha256:dd18772815d5f008fa03d2b9a681ae38d5ae9f0e599f7dda233c439fcaa00d40 \
-    --hash=sha256:ddc2f4dfd396c7bfa18e6ce371cba60e4cf9d2e5cdb71376aa2da264605b60b9 \
-    --hash=sha256:e003b002ec72c8d5a3e3da2989c7d6065b47d9eaa70cd8808b5384fbb970f4ec \
-    --hash=sha256:e32a92116d4f2a80b629778280103d2a510a5b3f6314ceccd6e38006b5e92dcb \
-    --hash=sha256:e4461d0f003a0aa9be2bdd1b798a041f177189c1a0f7619fe8c95ad08d9a45d7 \
-    --hash=sha256:e541ec6f2ec456934fd279a3120f856cd0aedd209fc3852eca563f81738f6861 \
-    --hash=sha256:e546e768d08ad55b20b11dbb78a745151acbd938f8f00d0cfbabe8b0199b9880 \
-    --hash=sha256:ea7d4a99f3b38c37eac212dbd6ec42b7a5ec51e2c74b5d3223e43c811609e65f \
-    --hash=sha256:ed4eb745efbff0a8e9587d22a84be94a5eb7d2d99c02dacf7bd0911713ed14dd \
-    --hash=sha256:f8a2f084546cc59ea99fda8e070be2fd140c3092dc11524a71aa8f0f3d5a55ca \
-    --hash=sha256:fcb25daa9219b4cf3a0ab24b0eb9a5cc8949ed4dc72acb8fa16b7e1681aa3c58 \
-    --hash=sha256:fdea4952db2793c4ad0bdccd27c1d8fdd1423a92f04598bc39425bcc2b8ee46e
+rpds-py==0.25.1 \
+    --hash=sha256:0317177b1e8691ab5879f4f33f4b6dc55ad3b344399e23df2e499de7b10a548d \
+    --hash=sha256:036ded36bedb727beeabc16dc1dad7cb154b3fa444e936a03b67a86dc6a5066e \
+    --hash=sha256:048893e902132fd6548a2e661fb38bf4896a89eea95ac5816cf443524a85556f \
+    --hash=sha256:0701942049095741a8aeb298a31b203e735d1c61f4423511d2b1a41dcd8a16da \
+    --hash=sha256:083a9513a33e0b92cf6e7a6366036c6bb43ea595332c1ab5c8ae329e4bcc0a9c \
+    --hash=sha256:09eab132f41bf792c7a0ea1578e55df3f3e7f61888e340779b06050a9a3f16e9 \
+    --hash=sha256:0e6a327af8ebf6baba1c10fadd04964c1965d375d318f4435d5f3f9651550f4a \
+    --hash=sha256:0eb90e94f43e5085623932b68840b6f379f26db7b5c2e6bcef3179bd83c9330f \
+    --hash=sha256:114a07e85f32b125404f28f2ed0ba431685151c037a26032b213c882f26eb908 \
+    --hash=sha256:115874ae5e2fdcfc16b2aedc95b5eef4aebe91b28e7e21951eda8a5dc0d3461b \
+    --hash=sha256:140f61d9bed7839446bdd44852e30195c8e520f81329b4201ceead4d64eb3a9f \
+    --hash=sha256:1521031351865e0181bc585147624d66b3b00a84109b57fcb7a779c3ec3772cd \
+    --hash=sha256:1c0c434a53714358532d13539272db75a5ed9df75a4a090a753ac7173ec14e11 \
+    --hash=sha256:1d1fadd539298e70cac2f2cb36f5b8a65f742b9b9f1014dd4ea1f7785e2470bf \
+    --hash=sha256:1de336a4b164c9188cb23f3703adb74a7623ab32d20090d0e9bf499a2203ad65 \
+    --hash=sha256:1ee3e26eb83d39b886d2cb6e06ea701bba82ef30a0de044d34626ede51ec98b0 \
+    --hash=sha256:245550f5a1ac98504147cba96ffec8fabc22b610742e9150138e5d60774686d7 \
+    --hash=sha256:2a40046a529cc15cef88ac5ab589f83f739e2d332cb4d7399072242400ed68c9 \
+    --hash=sha256:2c2cd1a4b0c2b8c5e31ffff50d09f39906fe351389ba143c195566056c13a7ea \
+    --hash=sha256:2cb9e5b5e26fc02c8a4345048cd9998c2aca7c2712bd1b36da0c72ee969a3523 \
+    --hash=sha256:33358883a4490287e67a2c391dfaea4d9359860281db3292b6886bf0be3d8692 \
+    --hash=sha256:35634369325906bcd01577da4c19e3b9541a15e99f31e91a02d010816b49bfda \
+    --hash=sha256:35a8d1a24b5936b35c5003313bc177403d8bdef0f8b24f28b1c4a255f94ea992 \
+    --hash=sha256:3af5b4cc10fa41e5bc64e5c198a1b2d2864337f8fcbb9a67e747e34002ce812b \
+    --hash=sha256:3bcce0edc1488906c2d4c75c94c70a0417e83920dd4c88fec1078c94843a6ce9 \
+    --hash=sha256:3c5b317ecbd8226887994852e85de562f7177add602514d4ac40f87de3ae45a8 \
+    --hash=sha256:3c6564c0947a7f52e4792983f8e6cf9bac140438ebf81f527a21d944f2fd0a40 \
+    --hash=sha256:3ebd879ab996537fc510a2be58c59915b5dd63bccb06d1ef514fee787e05984a \
+    --hash=sha256:3f0b1798cae2bbbc9b9db44ee068c556d4737911ad53a4e5093d09d04b3bbc24 \
+    --hash=sha256:401ca1c4a20cc0510d3435d89c069fe0a9ae2ee6495135ac46bdd49ec0495763 \
+    --hash=sha256:454601988aab2c6e8fd49e7634c65476b2b919647626208e376afcd22019eeb8 \
+    --hash=sha256:4593c4eae9b27d22df41cde518b4b9e4464d139e4322e2127daa9b5b981b76be \
+    --hash=sha256:45e484db65e5380804afbec784522de84fa95e6bb92ef1bd3325d33d13efaebd \
+    --hash=sha256:48d64155d02127c249695abb87d39f0faf410733428d499867606be138161d65 \
+    --hash=sha256:4fbb0dbba559959fcb5d0735a0f87cdbca9e95dac87982e9b95c0f8f7ad10255 \
+    --hash=sha256:4fd52d3455a0aa997734f3835cbc4c9f32571345143960e7d7ebfe7b5fbfa3b2 \
+    --hash=sha256:50f2c501a89c9a5f4e454b126193c5495b9fb441a75b298c60591d8a2eb92e1b \
+    --hash=sha256:58f77c60956501a4a627749a6dcb78dac522f249dd96b5c9f1c6af29bfacfb66 \
+    --hash=sha256:5a3ddb74b0985c4387719fc536faced33cadf2172769540c62e2a94b7b9be1c4 \
+    --hash=sha256:5c4a128527fe415d73cf1f70a9a688d06130d5810be69f3b553bf7b45e8acf79 \
+    --hash=sha256:5d473be2b13600b93a5675d78f59e63b51b1ba2d0476893415dfbb5477e65b31 \
+    --hash=sha256:5d9e40f32745db28c1ef7aad23f6fc458dc1e29945bd6781060f0d15628b8ddf \
+    --hash=sha256:5f048bbf18b1f9120685c6d6bb70cc1a52c8cc11bdd04e643d28d3be0baf666d \
+    --hash=sha256:605ffe7769e24b1800b4d024d24034405d9404f0bc2f55b6db3362cd34145a6f \
+    --hash=sha256:6099263f526efff9cf3883dfef505518730f7a7a93049b1d90d42e50a22b4793 \
+    --hash=sha256:659d87430a8c8c704d52d094f5ba6fa72ef13b4d385b7e542a08fc240cb4a559 \
+    --hash=sha256:666fa7b1bd0a3810a7f18f6d3a25ccd8866291fbbc3c9b912b917a6715874bb9 \
+    --hash=sha256:68f6f060f0bbdfb0245267da014d3a6da9be127fe3e8cc4a68c6f833f8a23bb1 \
+    --hash=sha256:6d273f136e912aa101a9274c3145dcbddbe4bac560e77e6d5b3c9f6e0ed06d34 \
+    --hash=sha256:6d50841c425d16faf3206ddbba44c21aa3310a0cebc3c1cdfc3e3f4f9f6f5728 \
+    --hash=sha256:771c16060ff4e79584dc48902a91ba79fd93eade3aa3a12d6d2a4aadaf7d542b \
+    --hash=sha256:785ffacd0ee61c3e60bdfde93baa6d7c10d86f15655bd706c89da08068dc5038 \
+    --hash=sha256:796ad874c89127c91970652a4ee8b00d56368b7e00d3477f4415fe78164c8000 \
+    --hash=sha256:79dc317a5f1c51fd9c6a0c4f48209c6b8526d0524a6904fc1076476e79b00f98 \
+    --hash=sha256:7c9409b47ba0650544b0bb3c188243b83654dfe55dcc173a86832314e1a6a35d \
+    --hash=sha256:7d779b325cc8238227c47fbc53964c8cc9a941d5dbae87aa007a1f08f2f77b23 \
+    --hash=sha256:816568614ecb22b18a010c7a12559c19f6fe993526af88e95a76d5a60b8b75fb \
+    --hash=sha256:8378fa4a940f3fb509c081e06cb7f7f2adae8cf46ef258b0e0ed7519facd573e \
+    --hash=sha256:85608eb70a659bf4c1142b2781083d4b7c0c4e2c90eff11856a9754e965b2540 \
+    --hash=sha256:85fc223d9c76cabe5d0bff82214459189720dc135db45f9f66aa7cffbf9ff6c1 \
+    --hash=sha256:88ec04afe0c59fa64e2f6ea0dd9657e04fc83e38de90f6de201954b4d4eb59bd \
+    --hash=sha256:8960b6dac09b62dac26e75d7e2c4a22efb835d827a7278c34f72b2b84fa160e3 \
+    --hash=sha256:89706d0683c73a26f76a5315d893c051324d771196ae8b13e6ffa1ffaf5e574f \
+    --hash=sha256:89c24300cd4a8e4a51e55c31a8ff3918e6651b241ee8876a42cc2b2a078533ba \
+    --hash=sha256:8c742af695f7525e559c16f1562cf2323db0e3f0fbdcabdf6865b095256b2d40 \
+    --hash=sha256:8dbd586bfa270c1103ece2109314dd423df1fa3d9719928b5d09e4840cec0d72 \
+    --hash=sha256:8eb8c84ecea987a2523e057c0d950bcb3f789696c0499290b8d7b3107a719d78 \
+    --hash=sha256:921954d7fbf3fccc7de8f717799304b14b6d9a45bbeec5a8d7408ccbf531faf5 \
+    --hash=sha256:9a46c2fb2545e21181445515960006e85d22025bd2fe6db23e76daec6eb689fe \
+    --hash=sha256:9c006f3aadeda131b438c3092124bd196b66312f0caa5823ef09585a669cf449 \
+    --hash=sha256:9ceca1cf097ed77e1a51f1dbc8d174d10cb5931c188a4505ff9f3e119dfe519b \
+    --hash=sha256:9e5fc7484fa7dce57e25063b0ec9638ff02a908304f861d81ea49273e43838c1 \
+    --hash=sha256:9f2f48ab00181600ee266a095fe815134eb456163f7d6699f525dee471f312cf \
+    --hash=sha256:9fca84a15333e925dd59ce01da0ffe2ffe0d6e5d29a9eeba2148916d1824948c \
+    --hash=sha256:a49e1d7a4978ed554f095430b89ecc23f42014a50ac385eb0c4d163ce213c325 \
+    --hash=sha256:a58d1ed49a94d4183483a3ce0af22f20318d4a1434acee255d683ad90bf78129 \
+    --hash=sha256:a61d0b2c7c9a0ae45732a77844917b427ff16ad5464b4d4f5e4adb955f582890 \
+    --hash=sha256:a714bf6e5e81b0e570d01f56e0c89c6375101b8463999ead3a93a5d2a4af91fa \
+    --hash=sha256:a7b74e92a3b212390bdce1d93da9f6488c3878c1d434c5e751cbc202c5e09500 \
+    --hash=sha256:a8bd2f19e312ce3e1d2c635618e8a8d8132892bb746a7cf74780a489f0f6cdcb \
+    --hash=sha256:b0be9965f93c222fb9b4cc254235b3b2b215796c03ef5ee64f995b1b69af0762 \
+    --hash=sha256:b24bf3cd93d5b6ecfbedec73b15f143596c88ee249fa98cefa9a9dc9d92c6f28 \
+    --hash=sha256:b5ffe453cde61f73fea9430223c81d29e2fbf412a6073951102146c84e19e34c \
+    --hash=sha256:bc120d1132cff853ff617754196d0ac0ae63befe7c8498bd67731ba368abe451 \
+    --hash=sha256:bd035756830c712b64725a76327ce80e82ed12ebab361d3a1cdc0f51ea21acb0 \
+    --hash=sha256:bffcf57826d77a4151962bf1701374e0fc87f536e56ec46f1abdd6a903354042 \
+    --hash=sha256:c2013ee878c76269c7b557a9a9c042335d732e89d482606990b70a839635feb7 \
+    --hash=sha256:c4feb9211d15d9160bc85fa72fed46432cdc143eb9cf6d5ca377335a921ac37b \
+    --hash=sha256:c8980cde3bb8575e7c956a530f2c217c1d6aac453474bf3ea0f9c89868b531b6 \
+    --hash=sha256:c98f126c4fc697b84c423e387337d5b07e4a61e9feac494362a59fd7a2d9ed80 \
+    --hash=sha256:ccc6f3ddef93243538be76f8e47045b4aad7a66a212cd3a0f23e34469473d36b \
+    --hash=sha256:ccfa689b9246c48947d31dd9d8b16d89a0ecc8e0e26ea5253068efb6c542b76e \
+    --hash=sha256:cda776f1967cb304816173b30994faaf2fd5bcb37e73118a47964a02c348e1bc \
+    --hash=sha256:ce4c8e485a3c59593f1a6f683cf0ea5ab1c1dc94d11eea5619e4fb5228b40fbd \
+    --hash=sha256:d3c10228d6cf6fe2b63d2e7985e94f6916fa46940df46b70449e9ff9297bd3d1 \
+    --hash=sha256:d4ca54b9cf9d80b4016a67a0193ebe0bcf29f6b0a96f09db942087e294d3d4c2 \
+    --hash=sha256:d4cb2b3ddc16710548801c6fcc0cfcdeeff9dafbc983f77265877793f2660309 \
+    --hash=sha256:d50e4864498a9ab639d6d8854b25e80642bd362ff104312d9770b05d66e5fb13 \
+    --hash=sha256:d74ec9bc0e2feb81d3f16946b005748119c0f52a153f6db6a29e8cd68636f295 \
+    --hash=sha256:d8222acdb51a22929c3b2ddb236b69c59c72af4019d2cba961e2f9add9b6e634 \
+    --hash=sha256:db58483f71c5db67d643857404da360dce3573031586034b7d59f245144cc192 \
+    --hash=sha256:dc3c1ff0abc91444cd20ec643d0f805df9a3661fcacf9c95000329f3ddf268a4 \
+    --hash=sha256:dd326a81afe332ede08eb39ab75b301d5676802cdffd3a8f287a5f0b694dc3f5 \
+    --hash=sha256:dec21e02e6cc932538b5203d3a8bd6aa1480c98c4914cb88eea064ecdbc6396a \
+    --hash=sha256:e1dafef8df605fdb46edcc0bf1573dea0d6d7b01ba87f85cd04dc855b2b4479e \
+    --hash=sha256:e2f6a2347d3440ae789505693a02836383426249d5293541cd712e07e7aecf54 \
+    --hash=sha256:e37caa8cdb3b7cf24786451a0bdb853f6347b8b92005eeb64225ae1db54d1c2b \
+    --hash=sha256:e43a005671a9ed5a650f3bc39e4dbccd6d4326b24fb5ea8be5f3a43a6f576c72 \
+    --hash=sha256:e5e2f7280d8d0d3ef06f3ec1b4fd598d386cc6f0721e54f09109a8132182fbfe \
+    --hash=sha256:e87798852ae0b37c88babb7f7bbbb3e3fecc562a1c340195b44c7e24d403e380 \
+    --hash=sha256:ee86d81551ec68a5c25373c5643d343150cc54672b5e9a0cafc93c1870a53954 \
+    --hash=sha256:f251bf23deb8332823aef1da169d5d89fa84c89f67bdfb566c49dea1fccfd50d \
+    --hash=sha256:f3d86373ff19ca0441ebeb696ef64cb58b8b5cbacffcda5a0ec2f3911732a194 \
+    --hash=sha256:f4ad628b5174d5315761b67f212774a32f5bad5e61396d38108bd801c0a8f5d9 \
+    --hash=sha256:f70316f760174ca04492b5ab01be631a8ae30cadab1d1081035136ba12738cfa \
+    --hash=sha256:f73ce1512e04fbe2bc97836e89830d6b4314c171587a99688082d090f934d20a \
+    --hash=sha256:ff7c23ba0a88cb7b104281a99476cccadf29de2a0ef5ce864959a52675b1ca83
     # via
     #   jsonschema
     #   referencing
-six==1.16.0 \
-    --hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 \
-    --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254
+six==1.17.0 \
+    --hash=sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274 \
+    --hash=sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81
+    # via -r requirements.in
+tomli==2.2.1 \
+    --hash=sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6 \
+    --hash=sha256:02abe224de6ae62c19f090f68da4e27b10af2b93213d36cf44e6e1c5abd19fdd \
+    --hash=sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c \
+    --hash=sha256:2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b \
+    --hash=sha256:33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8 \
+    --hash=sha256:400e720fe168c0f8521520190686ef8ef033fb19fc493da09779e592861b78c6 \
+    --hash=sha256:40741994320b232529c802f8bc86da4e1aa9f413db394617b9a256ae0f9a7f77 \
+    --hash=sha256:465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff \
+    --hash=sha256:4a8f6e44de52d5e6c657c9fe83b562f5f4256d8ebbfe4ff922c495620a7f6cea \
+    --hash=sha256:4e340144ad7ae1533cb897d406382b4b6fede8890a03738ff1683af800d54192 \
+    --hash=sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249 \
+    --hash=sha256:6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee \
+    --hash=sha256:7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4 \
+    --hash=sha256:889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98 \
+    --hash=sha256:8d57ca8095a641b8237d5b079147646153d22552f1c637fd3ba7f4b0b29167a8 \
+    --hash=sha256:8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4 \
+    --hash=sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281 \
+    --hash=sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744 \
+    --hash=sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69 \
+    --hash=sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13 \
+    --hash=sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140 \
+    --hash=sha256:b82ebccc8c8a36f2094e969560a1b836758481f3dc360ce9a3277c65f374285e \
+    --hash=sha256:c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e \
+    --hash=sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc \
+    --hash=sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff \
+    --hash=sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec \
+    --hash=sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2 \
+    --hash=sha256:db2b95f9de79181805df90bedc5a5ab4c165e6ec3fe99f970d0e302f384ad222 \
+    --hash=sha256:e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106 \
+    --hash=sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272 \
+    --hash=sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a \
+    --hash=sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7
     # via -r requirements.in
-tomli==2.0.1 \
-    --hash=sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc \
-    --hash=sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f
+typing-extensions==4.13.2 \
+    --hash=sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c \
+    --hash=sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef
     # via -r requirements.in
-urllib3==2.2.2 \
-    --hash=sha256:a448b2f64d686155468037e1ace9f2d2199776e17f0a46610480d311f73e3472 \
-    --hash=sha256:dd505485549a7a552833da5e6063639d0d177c04f23bc3864e41e5dc5f612168
+urllib3==2.4.0 \
+    --hash=sha256:414bc6535b787febd7567804cc015fee39daab8ad86268f1310a9250697de466 \
+    --hash=sha256:4e16665048960a0900c702d4a66415956a584919c03361cac9f1df5c5dd7e813
     # via
     #   docker
     #   requests
-zstandard==0.22.0 \
-    --hash=sha256:11f0d1aab9516a497137b41e3d3ed4bbf7b2ee2abc79e5c8b010ad286d7464bd \
-    --hash=sha256:1958100b8a1cc3f27fa21071a55cb2ed32e9e5df4c3c6e661c193437f171cba2 \
-    --hash=sha256:1a90ba9a4c9c884bb876a14be2b1d216609385efb180393df40e5172e7ecf356 \
-    --hash=sha256:1d43501f5f31e22baf822720d82b5547f8a08f5386a883b32584a185675c8fbf \
-    --hash=sha256:23d2b3c2b8e7e5a6cb7922f7c27d73a9a615f0a5ab5d0e03dd533c477de23004 \
-    --hash=sha256:2612e9bb4977381184bb2463150336d0f7e014d6bb5d4a370f9a372d21916f69 \
-    --hash=sha256:275df437ab03f8c033b8a2c181e51716c32d831082d93ce48002a5227ec93019 \
-    --hash=sha256:2ac9957bc6d2403c4772c890916bf181b2653640da98f32e04b96e4d6fb3252a \
-    --hash=sha256:2b11ea433db22e720758cba584c9d661077121fcf60ab43351950ded20283440 \
-    --hash=sha256:2fdd53b806786bd6112d97c1f1e7841e5e4daa06810ab4b284026a1a0e484c0b \
-    --hash=sha256:33591d59f4956c9812f8063eff2e2c0065bc02050837f152574069f5f9f17775 \
-    --hash=sha256:36a47636c3de227cd765e25a21dc5dace00539b82ddd99ee36abae38178eff9e \
-    --hash=sha256:39b2853efc9403927f9065cc48c9980649462acbdf81cd4f0cb773af2fd734bc \
-    --hash=sha256:3db41c5e49ef73641d5111554e1d1d3af106410a6c1fb52cf68912ba7a343a0d \
-    --hash=sha256:445b47bc32de69d990ad0f34da0e20f535914623d1e506e74d6bc5c9dc40bb09 \
-    --hash=sha256:466e6ad8caefb589ed281c076deb6f0cd330e8bc13c5035854ffb9c2014b118c \
-    --hash=sha256:48f260e4c7294ef275744210a4010f116048e0c95857befb7462e033f09442fe \
-    --hash=sha256:4ac59d5d6910b220141c1737b79d4a5aa9e57466e7469a012ed42ce2d3995e88 \
-    --hash=sha256:53866a9d8ab363271c9e80c7c2e9441814961d47f88c9bc3b248142c32141d94 \
-    --hash=sha256:589402548251056878d2e7c8859286eb91bd841af117dbe4ab000e6450987e08 \
-    --hash=sha256:68953dc84b244b053c0d5f137a21ae8287ecf51b20872eccf8eaac0302d3e3b0 \
-    --hash=sha256:6c25b8eb733d4e741246151d895dd0308137532737f337411160ff69ca24f93a \
-    --hash=sha256:7034d381789f45576ec3f1fa0e15d741828146439228dc3f7c59856c5bcd3292 \
-    --hash=sha256:73a1d6bd01961e9fd447162e137ed949c01bdb830dfca487c4a14e9742dccc93 \
-    --hash=sha256:8226a33c542bcb54cd6bd0a366067b610b41713b64c9abec1bc4533d69f51e70 \
-    --hash=sha256:888196c9c8893a1e8ff5e89b8f894e7f4f0e64a5af4d8f3c410f0319128bb2f8 \
-    --hash=sha256:88c5b4b47a8a138338a07fc94e2ba3b1535f69247670abfe422de4e0b344aae2 \
-    --hash=sha256:8a1b2effa96a5f019e72874969394edd393e2fbd6414a8208fea363a22803b45 \
-    --hash=sha256:93e1856c8313bc688d5df069e106a4bc962eef3d13372020cc6e3ebf5e045202 \
-    --hash=sha256:9501f36fac6b875c124243a379267d879262480bf85b1dbda61f5ad4d01b75a3 \
-    --hash=sha256:959665072bd60f45c5b6b5d711f15bdefc9849dd5da9fb6c873e35f5d34d8cfb \
-    --hash=sha256:a1d67d0d53d2a138f9e29d8acdabe11310c185e36f0a848efa104d4e40b808e4 \
-    --hash=sha256:a493d470183ee620a3df1e6e55b3e4de8143c0ba1b16f3ded83208ea8ddfd91d \
-    --hash=sha256:a7ccf5825fd71d4542c8ab28d4d482aace885f5ebe4b40faaa290eed8e095a4c \
-    --hash=sha256:a88b7df61a292603e7cd662d92565d915796b094ffb3d206579aaebac6b85d5f \
-    --hash=sha256:a97079b955b00b732c6f280d5023e0eefe359045e8b83b08cf0333af9ec78f26 \
-    --hash=sha256:d22fdef58976457c65e2796e6730a3ea4a254f3ba83777ecfc8592ff8d77d303 \
-    --hash=sha256:d75f693bb4e92c335e0645e8845e553cd09dc91616412d1d4650da835b5449df \
-    --hash=sha256:d8593f8464fb64d58e8cb0b905b272d40184eac9a18d83cf8c10749c3eafcd7e \
-    --hash=sha256:d8fff0f0c1d8bc5d866762ae95bd99d53282337af1be9dc0d88506b340e74b73 \
-    --hash=sha256:de20a212ef3d00d609d0b22eb7cc798d5a69035e81839f549b538eff4105d01c \
-    --hash=sha256:e9e9d4e2e336c529d4c435baad846a181e39a982f823f7e4495ec0b0ec8538d2 \
-    --hash=sha256:f058a77ef0ece4e210bb0450e68408d4223f728b109764676e1a13537d056bb0 \
-    --hash=sha256:f1a4b358947a65b94e2501ce3e078bbc929b039ede4679ddb0460829b12f7375 \
-    --hash=sha256:f9b2cde1cd1b2a10246dbc143ba49d942d14fb3d2b4bccf4618d475c65464912 \
-    --hash=sha256:fe3390c538f12437b859d815040763abc728955a52ca6ff9c5d4ac707c4ad98e
+zstandard==0.23.0 \
+    --hash=sha256:034b88913ecc1b097f528e42b539453fa82c3557e414b3de9d5632c80439a473 \
+    --hash=sha256:0a7f0804bb3799414af278e9ad51be25edf67f78f916e08afdb983e74161b916 \
+    --hash=sha256:11e3bf3c924853a2d5835b24f03eeba7fc9b07d8ca499e247e06ff5676461a15 \
+    --hash=sha256:12a289832e520c6bd4dcaad68e944b86da3bad0d339ef7989fb7e88f92e96072 \
+    --hash=sha256:1516c8c37d3a053b01c1c15b182f3b5f5eef19ced9b930b684a73bad121addf4 \
+    --hash=sha256:157e89ceb4054029a289fb504c98c6a9fe8010f1680de0201b3eb5dc20aa6d9e \
+    --hash=sha256:1bfe8de1da6d104f15a60d4a8a768288f66aa953bbe00d027398b93fb9680b26 \
+    --hash=sha256:1e172f57cd78c20f13a3415cc8dfe24bf388614324d25539146594c16d78fcc8 \
+    --hash=sha256:1fd7e0f1cfb70eb2f95a19b472ee7ad6d9a0a992ec0ae53286870c104ca939e5 \
+    --hash=sha256:203d236f4c94cd8379d1ea61db2fce20730b4c38d7f1c34506a31b34edc87bdd \
+    --hash=sha256:27d3ef2252d2e62476389ca8f9b0cf2bbafb082a3b6bfe9d90cbcbb5529ecf7c \
+    --hash=sha256:29a2bc7c1b09b0af938b7a8343174b987ae021705acabcbae560166567f5a8db \
+    --hash=sha256:2ef230a8fd217a2015bc91b74f6b3b7d6522ba48be29ad4ea0ca3a3775bf7dd5 \
+    --hash=sha256:2ef3775758346d9ac6214123887d25c7061c92afe1f2b354f9388e9e4d48acfc \
+    --hash=sha256:2f146f50723defec2975fb7e388ae3a024eb7151542d1599527ec2aa9cacb152 \
+    --hash=sha256:2fb4535137de7e244c230e24f9d1ec194f61721c86ebea04e1581d9d06ea1269 \
+    --hash=sha256:32ba3b5ccde2d581b1e6aa952c836a6291e8435d788f656fe5976445865ae045 \
+    --hash=sha256:34895a41273ad33347b2fc70e1bff4240556de3c46c6ea430a7ed91f9042aa4e \
+    --hash=sha256:379b378ae694ba78cef921581ebd420c938936a153ded602c4fea612b7eaa90d \
+    --hash=sha256:38302b78a850ff82656beaddeb0bb989a0322a8bbb1bf1ab10c17506681d772a \
+    --hash=sha256:3aa014d55c3af933c1315eb4bb06dd0459661cc0b15cd61077afa6489bec63bb \
+    --hash=sha256:4051e406288b8cdbb993798b9a45c59a4896b6ecee2f875424ec10276a895740 \
+    --hash=sha256:40b33d93c6eddf02d2c19f5773196068d875c41ca25730e8288e9b672897c105 \
+    --hash=sha256:43da0f0092281bf501f9c5f6f3b4c975a8a0ea82de49ba3f7100e64d422a1274 \
+    --hash=sha256:445e4cb5048b04e90ce96a79b4b63140e3f4ab5f662321975679b5f6360b90e2 \
+    --hash=sha256:48ef6a43b1846f6025dde6ed9fee0c24e1149c1c25f7fb0a0585572b2f3adc58 \
+    --hash=sha256:50a80baba0285386f97ea36239855f6020ce452456605f262b2d33ac35c7770b \
+    --hash=sha256:519fbf169dfac1222a76ba8861ef4ac7f0530c35dd79ba5727014613f91613d4 \
+    --hash=sha256:53dd9d5e3d29f95acd5de6802e909ada8d8d8cfa37a3ac64836f3bc4bc5512db \
+    --hash=sha256:53ea7cdc96c6eb56e76bb06894bcfb5dfa93b7adcf59d61c6b92674e24e2dd5e \
+    --hash=sha256:576856e8594e6649aee06ddbfc738fec6a834f7c85bf7cadd1c53d4a58186ef9 \
+    --hash=sha256:59556bf80a7094d0cfb9f5e50bb2db27fefb75d5138bb16fb052b61b0e0eeeb0 \
+    --hash=sha256:5d41d5e025f1e0bccae4928981e71b2334c60f580bdc8345f824e7c0a4c2a813 \
+    --hash=sha256:61062387ad820c654b6a6b5f0b94484fa19515e0c5116faf29f41a6bc91ded6e \
+    --hash=sha256:61f89436cbfede4bc4e91b4397eaa3e2108ebe96d05e93d6ccc95ab5714be512 \
+    --hash=sha256:62136da96a973bd2557f06ddd4e8e807f9e13cbb0bfb9cc06cfe6d98ea90dfe0 \
+    --hash=sha256:64585e1dba664dc67c7cdabd56c1e5685233fbb1fc1966cfba2a340ec0dfff7b \
+    --hash=sha256:65308f4b4890aa12d9b6ad9f2844b7ee42c7f7a4fd3390425b242ffc57498f48 \
+    --hash=sha256:66b689c107857eceabf2cf3d3fc699c3c0fe8ccd18df2219d978c0283e4c508a \
+    --hash=sha256:6a41c120c3dbc0d81a8e8adc73312d668cd34acd7725f036992b1b72d22c1772 \
+    --hash=sha256:6f77fa49079891a4aab203d0b1744acc85577ed16d767b52fc089d83faf8d8ed \
+    --hash=sha256:72c68dda124a1a138340fb62fa21b9bf4848437d9ca60bd35db36f2d3345f373 \
+    --hash=sha256:752bf8a74412b9892f4e5b58f2f890a039f57037f52c89a740757ebd807f33ea \
+    --hash=sha256:76e79bc28a65f467e0409098fa2c4376931fd3207fbeb6b956c7c476d53746dd \
+    --hash=sha256:774d45b1fac1461f48698a9d4b5fa19a69d47ece02fa469825b442263f04021f \
+    --hash=sha256:77da4c6bfa20dd5ea25cbf12c76f181a8e8cd7ea231c673828d0386b1740b8dc \
+    --hash=sha256:77ea385f7dd5b5676d7fd943292ffa18fbf5c72ba98f7d09fc1fb9e819b34c23 \
+    --hash=sha256:80080816b4f52a9d886e67f1f96912891074903238fe54f2de8b786f86baded2 \
+    --hash=sha256:80a539906390591dd39ebb8d773771dc4db82ace6372c4d41e2d293f8e32b8db \
+    --hash=sha256:82d17e94d735c99621bf8ebf9995f870a6b3e6d14543b99e201ae046dfe7de70 \
+    --hash=sha256:837bb6764be6919963ef41235fd56a6486b132ea64afe5fafb4cb279ac44f259 \
+    --hash=sha256:84433dddea68571a6d6bd4fbf8ff398236031149116a7fff6f777ff95cad3df9 \
+    --hash=sha256:8c24f21fa2af4bb9f2c492a86fe0c34e6d2c63812a839590edaf177b7398f700 \
+    --hash=sha256:8ed7d27cb56b3e058d3cf684d7200703bcae623e1dcc06ed1e18ecda39fee003 \
+    --hash=sha256:9206649ec587e6b02bd124fb7799b86cddec350f6f6c14bc82a2b70183e708ba \
+    --hash=sha256:983b6efd649723474f29ed42e1467f90a35a74793437d0bc64a5bf482bedfa0a \
+    --hash=sha256:98da17ce9cbf3bfe4617e836d561e433f871129e3a7ac16d6ef4c680f13a839c \
+    --hash=sha256:9c236e635582742fee16603042553d276cca506e824fa2e6489db04039521e90 \
+    --hash=sha256:9da6bc32faac9a293ddfdcb9108d4b20416219461e4ec64dfea8383cac186690 \
+    --hash=sha256:a05e6d6218461eb1b4771d973728f0133b2a4613a6779995df557f70794fd60f \
+    --hash=sha256:a0817825b900fcd43ac5d05b8b3079937073d2b1ff9cf89427590718b70dd840 \
+    --hash=sha256:a4ae99c57668ca1e78597d8b06d5af837f377f340f4cce993b551b2d7731778d \
+    --hash=sha256:a8c86881813a78a6f4508ef9daf9d4995b8ac2d147dcb1a450448941398091c9 \
+    --hash=sha256:a8fffdbd9d1408006baaf02f1068d7dd1f016c6bcb7538682622c556e7b68e35 \
+    --hash=sha256:a9b07268d0c3ca5c170a385a0ab9fb7fdd9f5fd866be004c4ea39e44edce47dd \
+    --hash=sha256:ab19a2d91963ed9e42b4e8d77cd847ae8381576585bad79dbd0a8837a9f6620a \
+    --hash=sha256:ac184f87ff521f4840e6ea0b10c0ec90c6b1dcd0bad2f1e4a9a1b4fa177982ea \
+    --hash=sha256:b0e166f698c5a3e914947388c162be2583e0c638a4703fc6a543e23a88dea3c1 \
+    --hash=sha256:b2170c7e0367dde86a2647ed5b6f57394ea7f53545746104c6b09fc1f4223573 \
+    --hash=sha256:b2d8c62d08e7255f68f7a740bae85b3c9b8e5466baa9cbf7f57f1cde0ac6bc09 \
+    --hash=sha256:b4567955a6bc1b20e9c31612e615af6b53733491aeaa19a6b3b37f3b65477094 \
+    --hash=sha256:b69bb4f51daf461b15e7b3db033160937d3ff88303a7bc808c67bbc1eaf98c78 \
+    --hash=sha256:b8c0bd73aeac689beacd4e7667d48c299f61b959475cdbb91e7d3d88d27c56b9 \
+    --hash=sha256:be9b5b8659dff1f913039c2feee1aca499cfbc19e98fa12bc85e037c17ec6ca5 \
+    --hash=sha256:bf0a05b6059c0528477fba9054d09179beb63744355cab9f38059548fedd46a9 \
+    --hash=sha256:c16842b846a8d2a145223f520b7e18b57c8f476924bda92aeee3a88d11cfc391 \
+    --hash=sha256:c363b53e257246a954ebc7c488304b5592b9c53fbe74d03bc1c64dda153fb847 \
+    --hash=sha256:c7c517d74bea1a6afd39aa612fa025e6b8011982a0897768a2f7c8ab4ebb78a2 \
+    --hash=sha256:d20fd853fbb5807c8e84c136c278827b6167ded66c72ec6f9a14b863d809211c \
+    --hash=sha256:d2240ddc86b74966c34554c49d00eaafa8200a18d3a5b6ffbf7da63b11d74ee2 \
+    --hash=sha256:d477ed829077cd945b01fc3115edd132c47e6540ddcd96ca169facff28173057 \
+    --hash=sha256:d50d31bfedd53a928fed6707b15a8dbeef011bb6366297cc435accc888b27c20 \
+    --hash=sha256:dc1d33abb8a0d754ea4763bad944fd965d3d95b5baef6b121c0c9013eaf1907d \
+    --hash=sha256:dc5d1a49d3f8262be192589a4b72f0d03b72dcf46c51ad5852a4fdc67be7b9e4 \
+    --hash=sha256:e2d1a054f8f0a191004675755448d12be47fa9bebbcffa3cdf01db19f2d30a54 \
+    --hash=sha256:e7792606d606c8df5277c32ccb58f29b9b8603bf83b48639b7aedf6df4fe8171 \
+    --hash=sha256:ed1708dbf4d2e3a1c5c69110ba2b4eb6678262028afd6c6fbcc5a8dac9cda68e \
+    --hash=sha256:f2d4380bf5f62daabd7b751ea2339c1a21d1c9463f1feb7fc2bdcea2c29c3160 \
+    --hash=sha256:f3513916e8c645d0610815c257cbfd3242adfd5c4cfa78be514e5a3ebb42a41b \
+    --hash=sha256:f8346bfa098532bc1fb6c7ef06783e969d87a99dd1d2a5a18a892c1d7a643c58 \
+    --hash=sha256:f83fa6cae3fff8e98691248c9320356971b59678a17f20656a9e59cd32cee6d8 \
+    --hash=sha256:fa6ce8b52c5987b3e34d5674b0ab529a4602b632ebab0a93b07bfb4dfc8f8a33 \
+    --hash=sha256:fb2b1ecfef1e67897d336de3a0e3f52478182d6a47eda86cbd42504c5cbd009a \
+    --hash=sha256:fc9ca1c9718cb3b06634c7c8dec57d24e9438b2aa9a0f02b8bb36bf478538880 \
+    --hash=sha256:fd30d9c67d13d891f2360b2a120186729c111238ac63b43dbd37a5a40670b8ca \
+    --hash=sha256:fd7699e8fd9969f455ef2926221e0233f81a2542921471382e77a9e2f2b57f4b \
+    --hash=sha256:fe3b385d996ee0822fd46528d9f0443b880d4d05528fd26a9119a54ec3f91c69
     # via -r requirements.in

From 8f3c1d155abcdef8a1e98f2e3f3435f7f711fea4 Mon Sep 17 00:00:00 2001
From: Geoffrey Thomas <geofft@ldpreload.com>
Date: Wed, 4 Jun 2025 11:36:08 -0400
Subject: [PATCH 102/157] Use `gh release` instead of someone's release action
 (#635)

The upstream action times out because it requests every release (without
pagination), and there's no real need to use a third-party action for
this when the `gh` command does a perfectly fine job too.
---
 .github/workflows/release.yml | 11 ++---------
 Justfile                      | 22 ++++++++++++++++++++++
 2 files changed, 24 insertions(+), 9 deletions(-)

diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index aa2d3a70..83cee9b6 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -41,7 +41,7 @@ jobs:
       - run: just release-dry-run ${{ secrets.GITHUB_TOKEN }} ${{ github.event.inputs.sha }} ${{ github.event.inputs.tag }}
         if: ${{ github.event.inputs.dry-run == 'true' }}
 
-      # Create the release itself.
+      # Set our identity for git operations (on the latest-release branch).
       - name: Configure Git identity
         if: ${{ github.event.inputs.dry-run == 'false' }}
         run: |
@@ -66,14 +66,7 @@ jobs:
       # Create a GitHub release.
       - name: Create GitHub Release
         if: ${{ github.event.inputs.dry-run == 'false' }}
-        uses: ncipollo/release-action@v1
-        with:
-          tag: ${{ github.event.inputs.tag }}
-          name: ${{ github.event.inputs.tag }}
-          prerelease: true
-          body: TBD
-          allowUpdates: true
-          updateOnlyUnreleased: true
+        run: just release-create ${{ github.events.input.tag }}
 
       # Uploading the relevant artifact to the GitHub release.
       - run: just release-run ${{ secrets.GITHUB_TOKEN }} ${{ github.event.inputs.sha }} ${{ github.event.inputs.tag }}
diff --git a/Justfile b/Justfile
index 0255bd22..c9b8167f 100644
--- a/Justfile
+++ b/Justfile
@@ -67,6 +67,28 @@ release-set-latest-release tag:
     echo "No changes to commit."
   fi
 
+# Create a GitHub release object, or reuse an existing prerelease.
+release-create tag:
+  #!/usr/bin/env bash
+  set -euo pipefail
+  prerelease_exists=$(gh release view {{tag}} --json isPrerelease -t '{{{{.isPrerelease}}' 2>&1 || true)
+  case "$prerelease_exists" in
+    true)
+      echo "note: updating existing prerelease {{tag}}"
+      ;;
+    false)
+      echo "error: release {{tag}} already exists"
+      exit 1
+      ;;
+    "release not found")
+      gh release create {{tag}} --prerelease --notes TBD --verify-tag
+      ;;
+    *)
+      echo "error: unexpected gh cli output: $prerelease_exists"
+      exit 1
+      ;;
+  esac
+
 # Perform the release job. Assumes that the GitHub Release has been created.
 release-run token commit tag:
   #!/bin/bash

From d2030cb517582a4b0fa7bdafe1aa7587b001ecdd Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Wed, 4 Jun 2025 11:20:38 -0500
Subject: [PATCH 103/157] Update to 3.14.0b1 (#610)

- https://github.com/python/cpython/pull/133027
- https://github.com/python/cpython/pull/133366
- https://github.com/python/cpython/pull/133284
- https://github.com/python/cpython/pull/133398
- https://github.com/python/cpython/issues/131298
- https://github.com/python/cpython/pull/132438
- https://github.com/python/cpython/pull/133012

---------

Co-authored-by: Wingy <git@wingysam.xyz>
Co-authored-by: Geoffrey Thomas <geofft@ldpreload.com>
---
 cpython-unix/build-cpython.sh                 | 10 ++++-
 cpython-unix/extension-modules.yml            | 35 +++++++++++------
 cpython-unix/patch-jit-cflags-314.patch       | 38 ++++++++++---------
 .../patch-python-configure-hacl-no-simd.patch | 24 ++++++++++++
 cpython-windows/build.py                      | 21 ++++++++++
 pythonbuild/cpython.py                        | 25 ++++++++++++
 pythonbuild/downloads.py                      | 17 +++++++--
 src/validation.rs                             | 14 +++----
 8 files changed, 144 insertions(+), 40 deletions(-)
 create mode 100644 cpython-unix/patch-python-configure-hacl-no-simd.patch

diff --git a/cpython-unix/build-cpython.sh b/cpython-unix/build-cpython.sh
index b44bb971..49e1873c 100755
--- a/cpython-unix/build-cpython.sh
+++ b/cpython-unix/build-cpython.sh
@@ -466,7 +466,8 @@ if [ -n "${CPYTHON_OPTIMIZED}" ]; then
 
         # Do not enable on x86-64 macOS because the JIT requires macOS 11+ and we are currently
         # using 10.15 as a miniumum version.
-        if [ "${TARGET_TRIPLE}" != "x86_64-apple-darwin" ]; then
+        # Do not enable when free-threading, because they're not compatible yet.
+        if [[ ! ( "${TARGET_TRIPLE}" == "x86_64-apple-darwin" || -n "${CPYTHON_FREETHREADED}" ) ]]; then
             CONFIGURE_FLAGS="${CONFIGURE_FLAGS} --enable-experimental-jit=yes-off"
         fi
 
@@ -588,6 +589,13 @@ if [[ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_14}" && -n "${CROSS_COMPILING}" && "$
     export PROFILE_TASK='-m test --pgo --ignore test_strftime_y2k'
 fi
 
+# ./configure tries to auto-detect whether it can build 128-bit and 256-bit SIMD helpers for HACL,
+# but on x86-64 that requires v2 and v3 respectively, and on arm64 the performance is bad as noted
+# in the comments, so just don't even try. (We should check if we can make this conditional)
+if [[ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_14}" ]]; then
+    patch -p1 -i "${ROOT}/patch-python-configure-hacl-no-simd.patch"
+fi
+
 # We use ndbm on macOS and BerkeleyDB elsewhere.
 if [[ "${PYBUILD_PLATFORM}" = macos* ]]; then
     CONFIGURE_FLAGS="${CONFIGURE_FLAGS} --with-dbmliborder=ndbm"
diff --git a/cpython-unix/extension-modules.yml b/cpython-unix/extension-modules.yml
index 028eadde..3d69f049 100644
--- a/cpython-unix/extension-modules.yml
+++ b/cpython-unix/extension-modules.yml
@@ -43,7 +43,7 @@ _blake2:
       minimum-python-version: "3.14"
     - define: _DEFAULT_SOURCE
       minimum-python-version: "3.14"
-    # Disable `explicit_bzero`, it requires glib 2.25+
+    # Disable `explicit_bzero`, it requires glibc 2.25+
     - define: LINUX_NO_EXPLICIT_BZERO
       minimum-python-version: "3.14"
 
@@ -88,6 +88,9 @@ _collections:
 _contextvars:
   sources:
     - _contextvarsmodule.c
+  config-c-only-conditional:
+    - config-c-only: true
+      minimum-python-version: "3.14"
 
 _crypt:
   maximum-python-version: "3.12"
@@ -315,12 +318,6 @@ _hmac:
   includes:
     - Modules/_hacl/
     - Modules/_hacl/include/
-  links:
-    - :libHacl_Hash_Blake2.a
-    - :libHacl_Hash_SHA1.a
-    - :libHacl_Hash_SHA2.a
-    - :libHacl_Hash_SHA3.a
-    - :libHacl_Hash_MD5.a
   defines:
     - _BSD_SOURCE
     - _DEFAULT_SOURCE
@@ -376,7 +373,6 @@ _md5:
   sources-conditional:
     - source: _hacl/Hacl_Hash_MD5.c
       minimum-python-version: "3.12"
-      maximum-python-version: "3.13"
   defines-conditional:
     - define: _BSD_SOURCE
       minimum-python-version: "3.12"
@@ -435,6 +431,12 @@ _random:
   sources:
     - _randommodule.c
 
+
+_remote_debugging:
+  minimum-python-version: "3.14"
+  sources:
+    - _remote_debugging_module.c
+
 _scproxy:
   # _scproxy is Apple OS only.
   # APIs required by _scproxy not available on iOS.
@@ -453,7 +455,6 @@ _sha1:
   sources-conditional:
     - source: _hacl/Hacl_Hash_SHA1.c
       minimum-python-version: "3.12"
-      maximum-python-version: "3.13"
   includes:
     - Modules/_hacl/include
   defines-conditional:
@@ -475,7 +476,6 @@ _sha2:
     - sha2module.c
   sources-conditional:
     - source: _hacl/Hacl_Hash_SHA2.c
-      maximum-python-version: "3.13"
   includes:
     - Modules/_hacl/include
   defines:
@@ -491,7 +491,6 @@ _sha3:
       minimum-python-version: "3.12"
     - source: _hacl/Hacl_Hash_SHA3.c
       minimum-python-version: "3.12"
-      maximum-python-version: "3.13"
   includes:
     - Modules/_hacl/include
   defines-conditional:
@@ -617,6 +616,7 @@ _testcapi:
 
 _testexternalinspection:
   minimum-python-version: '3.13'
+  maximum-python-version: '3.13'
   sources:
     - _testexternalinspection.c
 
@@ -645,6 +645,8 @@ _testinternalcapi:
       minimum-python-version: "3.13"
     - source: _testinternalcapi/test_lock.c
       minimum-python-version: "3.13"
+    - source: _testinternalcapi/complex.c
+      minimum-python-version: "3.14"
 
 _testmultiphase:
   minimum-python-version: '3.9'
@@ -769,6 +771,17 @@ _xxtestfuzz:
     - _xxtestfuzz/_xxtestfuzz.c
     - _xxtestfuzz/fuzzer.c
 
+_zstd:
+  # Disable on all targets until we add a zstd library
+  disabled-targets:
+    - .*
+  minimum-python-version: '3.14'
+  sources:
+    - _zstd/_zstdmodule.c
+    - _zstd/zdict.c
+    - _zstd/compressor.c
+    - _zstd/decompressor.c
+
 _zoneinfo:
   minimum-python-version: "3.9"
   sources:
diff --git a/cpython-unix/patch-jit-cflags-314.patch b/cpython-unix/patch-jit-cflags-314.patch
index 81f6fd02..3fc200ad 100644
--- a/cpython-unix/patch-jit-cflags-314.patch
+++ b/cpython-unix/patch-jit-cflags-314.patch
@@ -1,5 +1,5 @@
 diff --git a/Tools/jit/_targets.py b/Tools/jit/_targets.py
-index b3b065652e0..d361f57382e 100644
+index 6ceb4404e74..94b74b5c8b0 100644
 --- a/Tools/jit/_targets.py
 +++ b/Tools/jit/_targets.py
 @@ -10,6 +10,7 @@
@@ -10,7 +10,7 @@ index b3b065652e0..d361f57382e 100644
  
  import _llvm
  import _schema
-@@ -42,6 +43,7 @@ class _Target(typing.Generic[_S, _R]):
+@@ -46,6 +47,7 @@ class _Target(typing.Generic[_S, _R]):
      stable: bool = False
      debug: bool = False
      verbose: bool = False
@@ -18,7 +18,7 @@ index b3b065652e0..d361f57382e 100644
      known_symbols: dict[str, int] = dataclasses.field(default_factory=dict)
  
      def _get_nop(self) -> bytes:
-@@ -115,6 +117,7 @@ async def _compile(
+@@ -119,6 +121,7 @@ async def _compile(
      ) -> _stencils.StencilGroup:
          o = tempdir / f"{opname}.o"
          args = [
@@ -27,10 +27,10 @@ index b3b065652e0..d361f57382e 100644
              "-DPy_BUILD_CORE_MODULE",
              "-D_DEBUG" if self.debug else "-DNDEBUG",
 diff --git a/Tools/jit/build.py b/Tools/jit/build.py
-index a8cb0f67c36..663874ad439 100644
+index 49b08f477db..49a1b11de47 100644
 --- a/Tools/jit/build.py
 +++ b/Tools/jit/build.py
-@@ -22,7 +22,11 @@
+@@ -26,11 +26,15 @@
      parser.add_argument(
          "-v", "--verbose", action="store_true", help="echo commands as they are run"
      )
@@ -38,33 +38,37 @@ index a8cb0f67c36..663874ad439 100644
 +        "--with-cflags", help="additional flags to pass to the compiler", default=""
 +    )
      args = parser.parse_args()
-     args.target.debug = args.debug
-     args.target.verbose = args.verbose
-+    args.target.cflags = args.with_cflags
-     args.target.build(pathlib.Path.cwd(), comment=comment, force=args.force)
+     for target in args.target:
+         target.debug = args.debug
+         target.force = args.force
+         target.verbose = args.verbose
++        target.cflags = args.with_cflags
+         target.build(
+             out,
+             comment=comment,
 diff --git a/configure b/configure
-index 1b75ddfa26d..3c9e550b5d3 100755
+index c51192f12c8..0dcef7c2617 100755
 --- a/configure
 +++ b/configure
-@@ -8399,7 +8399,7 @@ then :
+@@ -10863,7 +10863,7 @@ then :
  
  else case e in #(
    e) as_fn_append CFLAGS_NODIST " $jit_flags"
--           REGEN_JIT_COMMAND="\$(PYTHON_FOR_REGEN) \$(srcdir)/Tools/jit/build.py $host"
-+           REGEN_JIT_COMMAND="\$(PYTHON_FOR_REGEN) \$(srcdir)/Tools/jit/build.py $host --with-cflags=\"\$(CONFIGURE_CFLAGS)\""
+-           REGEN_JIT_COMMAND="\$(PYTHON_FOR_REGEN) \$(srcdir)/Tools/jit/build.py ${ARCH_TRIPLES:-$host}"
++           REGEN_JIT_COMMAND="\$(PYTHON_FOR_REGEN) \$(srcdir)/Tools/jit/build.py ${ARCH_TRIPLES:-$host} --with-cflags=\"\$(CONFIGURE_CFLAGS)\""
             JIT_STENCILS_H="jit_stencils.h"
             if test "x$Py_DEBUG" = xtrue
  then :
 diff --git a/configure.ac b/configure.ac
-index c449bb5ebb3..5f9d08a4ee7 100644
+index a7b2f62579b..5998f896a4e 100644
 --- a/configure.ac
 +++ b/configure.ac
-@@ -1827,7 +1827,7 @@ AS_VAR_IF([jit_flags],
+@@ -2776,7 +2776,7 @@ AS_VAR_IF([jit_flags],
            [],
            [AS_VAR_APPEND([CFLAGS_NODIST], [" $jit_flags"])
             AS_VAR_SET([REGEN_JIT_COMMAND],
--                      ["\$(PYTHON_FOR_REGEN) \$(srcdir)/Tools/jit/build.py $host"])
-+                      ["\$(PYTHON_FOR_REGEN) \$(srcdir)/Tools/jit/build.py $host --with-cflags=\"\$(CONFIGURE_CFLAGS)\""])
+-                      ["\$(PYTHON_FOR_REGEN) \$(srcdir)/Tools/jit/build.py ${ARCH_TRIPLES:-$host}"])
++                      ["\$(PYTHON_FOR_REGEN) \$(srcdir)/Tools/jit/build.py ${ARCH_TRIPLES:-$host} --with-cflags=\"\$(CONFIGURE_CFLAGS)\""])
             AS_VAR_SET([JIT_STENCILS_H], ["jit_stencils.h"])
             AS_VAR_IF([Py_DEBUG],
                       [true],
diff --git a/cpython-unix/patch-python-configure-hacl-no-simd.patch b/cpython-unix/patch-python-configure-hacl-no-simd.patch
new file mode 100644
index 00000000..125aea33
--- /dev/null
+++ b/cpython-unix/patch-python-configure-hacl-no-simd.patch
@@ -0,0 +1,24 @@
+diff --git a/configure.ac b/configure.ac
+index a7b2f62579b..06c0c0c0da0 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -7897,8 +7897,7 @@ AC_SUBST([LIBHACL_LDFLAGS])
+ # The SIMD files use aligned_alloc, which is not available on older versions of
+ # Android.
+ # The *mmintrin.h headers are x86-family-specific, so can't be used on WASI.
+-if test "$ac_sys_system" != "Linux-android" -a "$ac_sys_system" != "WASI" || \
+-   { test -n "$ANDROID_API_LEVEL" && test "$ANDROID_API_LEVEL" -ge 28; }
++if false
+ then
+   dnl This can be extended here to detect e.g. Power8, which HACL* should also support.
+   AX_CHECK_COMPILE_FLAG([-msse -msse2 -msse3 -msse4.1 -msse4.2],[
+@@ -7930,8 +7929,7 @@ AC_SUBST([LIBHACL_BLAKE2_SIMD128_OBJS])
+ # Although AVX support is not guaranteed on Android
+ # (https://developer.android.com/ndk/guides/abis#86-64), this is safe because we do a
+ # runtime CPUID check.
+-if test "$ac_sys_system" != "Linux-android" -a "$ac_sys_system" != "WASI" || \
+-   { test -n "$ANDROID_API_LEVEL" && test "$ANDROID_API_LEVEL" -ge 28; }
++if false
+ then
+   AX_CHECK_COMPILE_FLAG([-mavx2],[
+     [LIBHACL_SIMD256_FLAGS="-mavx2"]
diff --git a/cpython-windows/build.py b/cpython-windows/build.py
index e981a8ac..15b0a44d 100644
--- a/cpython-windows/build.py
+++ b/cpython-windows/build.py
@@ -72,6 +72,10 @@
     },
     "_overlapped": {},
     "_multiprocessing": {},
+    "_remote_debugging": {
+        # Added in 3.14
+        "ignore_missing": True
+    },
     "_socket": {},
     "_sqlite3": {"shared_depends": ["sqlite3"]},
     # See the one-off calls to copy_link_to_lib() and elsewhere to hack up
@@ -90,6 +94,10 @@
         "ignore_missing": True,
     },
     "_zoneinfo": {"ignore_missing": True},
+    "_zstd": {
+        # Added in 3.14
+        "ignore_missing": True
+    },
     "pyexpat": {},
     "select": {},
     "unicodedata": {},
@@ -117,6 +125,7 @@
     "_tkinter": ["tcl-8612", "tk-8612", "tix"],
     "_uuid": ["uuid"],
     "zlib": ["zlib"],
+    "_zstd": ["zstd"],
 }
 
 
@@ -357,6 +366,7 @@ def hack_props(
     sqlite_version = DOWNLOADS["sqlite"]["version"]
     xz_version = DOWNLOADS["xz"]["version"]
     zlib_version = DOWNLOADS[zlib_entry]["version"]
+    zstd_version = DOWNLOADS["zstd"]["version"]
 
     mpdecimal_version = DOWNLOADS["mpdecimal"]["version"]
 
@@ -372,6 +382,7 @@ def hack_props(
     xz_path = td / ("xz-%s" % xz_version)
     zlib_prefix = "cpython-source-deps-" if zlib_entry == "zlib-ng" else ""
     zlib_path = td / ("%s%s-%s" % (zlib_prefix, zlib_entry, zlib_version))
+    zstd_path = td / ("cpython-source-deps-zstd-%s" % zstd_version)
     mpdecimal_path = td / ("mpdecimal-%s" % mpdecimal_version)
 
     openssl_root = td / "openssl" / arch
@@ -416,6 +427,9 @@ def hack_props(
             elif b"<zlibNgDir" in line:
                 line = b"<zlibNgDir>%s\\</zlibNgDir>" % zlib_path
 
+            elif b"<zstdDir" in line:
+                line = b"<zstdDir>%s\\</zstdDir>" % zstd_path
+
             elif b"<mpdecimalDir" in line:
                 line = b"<mpdecimalDir>%s\\</mpdecimalDir>" % mpdecimal_path
 
@@ -1255,6 +1269,12 @@ def build_cpython(
             "tk-windows-bin-8612", BUILD, local_name="tk-windows-bin.tar.gz"
         )
 
+    # On CPython 3.14+, zstd is included
+    if meets_python_minimum_version(python_version, "3.14"):
+        zstd_archive = download_entry("zstd", BUILD)
+    else:
+        zstd_archive = None
+
     # CPython 3.13+ no longer uses a bundled `mpdecimal` version so we build it
     if meets_python_minimum_version(python_version, "3.13"):
         mpdecimal_archive = download_entry("mpdecimal", BUILD)
@@ -1297,6 +1317,7 @@ def build_cpython(
                 tk_bin_archive,
                 xz_archive,
                 zlib_archive,
+                zstd_archive,
             ):
                 if a is None:
                     continue
diff --git a/pythonbuild/cpython.py b/pythonbuild/cpython.py
index e59eecd3..f339037c 100644
--- a/pythonbuild/cpython.py
+++ b/pythonbuild/cpython.py
@@ -16,6 +16,19 @@
     "properties": {
         "build-mode": {"type": "string"},
         "config-c-only": {"type": "boolean"},
+        "config-c-only-conditional": {
+            "type": "array",
+            "items": {
+                "type": "object",
+                "properties": {
+                    "config-c-only": {"type": "boolean"},
+                    "minimum-python-version": {"type": "string"},
+                    "maximum-python-version": {"type": "string"},
+                },
+                "additionalProperties": False,
+                "required": ["config-c-only"],
+            },
+        },
         "defines": {"type": "array", "items": {"type": "string"}},
         "defines-conditional": {
             "type": "array",
@@ -286,6 +299,18 @@ def derive_setup_local(
         if info.get("config-c-only"):
             config_c_only_wanted.add(name)
 
+        for entry in info.get("config-c-only-conditional", []):
+            python_min_match_setup = meets_python_minimum_version(
+                python_version, entry.get("minimum-python-version", "1.0")
+            )
+            python_max_match_setup = meets_python_maximum_version(
+                python_version, entry.get("maximum-python-version", "100.0")
+            )
+            if entry.get("config-c-only", False) and (
+                python_min_match_setup and python_max_match_setup
+            ):
+                config_c_only_wanted.add(name)
+
     # Parse more files in the distribution for their metadata.
 
     with tarfile.open(str(cpython_source_archive)) as tf:
diff --git a/pythonbuild/downloads.py b/pythonbuild/downloads.py
index 12abd7ae..2fb34e89 100644
--- a/pythonbuild/downloads.py
+++ b/pythonbuild/downloads.py
@@ -82,10 +82,10 @@
         "python_tag": "cp313",
     },
     "cpython-3.14": {
-        "url": "https://www.python.org/ftp/python/3.14.0/Python-3.14.0a7.tar.xz",
-        "size": 23015952,
-        "sha256": "71adbcec3ac9edf93308e55cfb4184f2eb4b16fda2bb0a5a382929ed29c8386d",
-        "version": "3.14.0a7",
+        "url": "https://www.python.org/ftp/python/3.14.0/Python-3.14.0b1.tar.xz",
+        "size": 23358200,
+        "sha256": "2ddd30a77c9f62e065ce648664a254b9b0c011bcdaa8c1c2787087e644cbeb39",
+        "version": "3.14.0b1",
         "licenses": ["Python-2.0", "CNRI-Python"],
         "license_file": "LICENSE.cpython.txt",
         "python_tag": "cp314",
@@ -429,4 +429,13 @@
         "licenses": ["Zlib"],
         "license_file": "LICENSE.zlib-ng.txt",
     },
+    "zstd": {
+        "url": "https://github.com/python/cpython-source-deps/archive/refs/tags/zstd-1.5.7.tar.gz",
+        "size": 2440298,
+        "sha256": "f24b52470d12f466e9fa4fcc94e6c530625ada51d7b36de7fdc6ed7e6f499c8e",
+        "version": "1.5.7",
+        "library_names": ["zstd"],
+        "licenses": ["BSD-3-Clause"],
+        "license_file": "LICENSE.zstd.txt",
+    },
 }
diff --git a/src/validation.rs b/src/validation.rs
index 55139df7..19aace00 100644
--- a/src/validation.rs
+++ b/src/validation.rs
@@ -748,6 +748,7 @@ const GLOBAL_EXTENSIONS_PYTHON_3_13: &[&str] = &[
     "_interpqueues",
     "_interpreters",
     "_sha2",
+    "_suggestions",
     "_sysconfig",
     "_tokenize",
     "_typing",
@@ -758,7 +759,9 @@ const GLOBAL_EXTENSIONS_PYTHON_3_14: &[&str] = &[
     "_interpchannels",
     "_interpqueues",
     "_interpreters",
+    "_remote_debugging",
     "_sha2",
+    "_suggestions",
     "_sysconfig",
     "_tokenize",
     "_typing",
@@ -800,7 +803,8 @@ const GLOBAL_EXTENSIONS_WINDOWS: &[&str] = &[
     "winsound",
 ];
 
-const GLOBAL_EXTENSIONS_WINDOWS_3_14: &[&str] = &["_wmi"];
+// TODO(zanieb): Move `_zstd` to non-Windows specific once we add support on Unix.
+const GLOBAL_EXTENSIONS_WINDOWS_3_14: &[&str] = &["_wmi", "_zstd"];
 
 const GLOBAL_EXTENSIONS_WINDOWS_PRE_3_13: &[&str] = &["_msi"];
 
@@ -1598,12 +1602,8 @@ fn validate_extension_modules(
         ]);
     }
 
-    if is_windows && matches!(python_major_minor, "3.13" | "3.14") {
-        wanted.extend(["_suggestions"]);
-    }
-
-    if (is_linux || is_macos) && matches!(python_major_minor, "3.13" | "3.14") {
-        wanted.extend(["_suggestions", "_testexternalinspection"]);
+    if (is_linux || is_macos) && matches!(python_major_minor, "3.13") {
+        wanted.insert("_testexternalinspection");
     }
 
     if (is_linux || is_macos) && matches!(python_major_minor, "3.12" | "3.13" | "3.14") {

From f77aba04edb028938eace39443b848be6d817b0f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C3=9Clgen=20Sar=C4=B1kavak?=
 <ulgens@users.noreply.github.com>
Date: Wed, 4 Jun 2025 20:13:28 +0300
Subject: [PATCH 104/157] Bump stable Python versions: 3.13.4, 3.12.11,
 3.11.13, 3.10.18 and 3.9.23 (#644)

https://discuss.python.org/t/python-3-13-4-3-12-11-3-11-13-3-10-18-and-3-9-23-are-now-available/94367
---
 pythonbuild/downloads.py | 40 ++++++++++++++++++++--------------------
 1 file changed, 20 insertions(+), 20 deletions(-)

diff --git a/pythonbuild/downloads.py b/pythonbuild/downloads.py
index 2fb34e89..8add331d 100644
--- a/pythonbuild/downloads.py
+++ b/pythonbuild/downloads.py
@@ -37,46 +37,46 @@
         "license_file": "LICENSE.bzip2.txt",
     },
     "cpython-3.9": {
-        "url": "https://www.python.org/ftp/python/3.9.22/Python-3.9.22.tar.xz",
-        "size": 19652572,
-        "sha256": "8c136d199d3637a1fce98a16adc809c1d83c922d02d41f3614b34f8b6e7d38ec",
-        "version": "3.9.22",
+        "url": "https://www.python.org/ftp/python/3.9.23/Python-3.9.23.tar.xz",
+        "size": 19659284,
+        "sha256": "61a42919e13d539f7673cf11d1c404380e28e540510860b9d242196e165709c9",
+        "version": "3.9.23",
         "licenses": ["Python-2.0", "CNRI-Python"],
         "license_file": "LICENSE.cpython.txt",
         "python_tag": "cp39",
     },
     "cpython-3.10": {
-        "url": "https://www.python.org/ftp/python/3.10.17/Python-3.10.17.tar.xz",
-        "size": 19608144,
-        "sha256": "4c68050f049d1b4ac5aadd0df5f27941c0350d2a9e7ab0907ee5eb5225d9d6b0",
-        "version": "3.10.17",
+        "url": "https://www.python.org/ftp/python/3.10.18/Python-3.10.18.tar.xz",
+        "size": 19619316,
+        "sha256": "ae665bc678abd9ab6a6e1573d2481625a53719bc517e9a634ed2b9fefae3817f",
+        "version": "3.10.18",
         "licenses": ["Python-2.0", "CNRI-Python"],
         "license_file": "LICENSE.cpython.txt",
         "python_tag": "cp310",
     },
     "cpython-3.11": {
-        "url": "https://www.python.org/ftp/python/3.11.12/Python-3.11.12.tar.xz",
-        "size": 20112232,
-        "sha256": "849da87af4df137710c1796e276a955f7a85c9f971081067c8f565d15c352a09",
-        "version": "3.11.12",
+        "url": "https://www.python.org/ftp/python/3.11.13/Python-3.11.13.tar.xz",
+        "size": 20117496,
+        "sha256": "8fb5f9fbc7609fa822cb31549884575db7fd9657cbffb89510b5d7975963a83a",
+        "version": "3.11.13",
         "licenses": ["Python-2.0", "CNRI-Python"],
         "license_file": "LICENSE.cpython.txt",
         "python_tag": "cp311",
     },
     "cpython-3.12": {
-        "url": "https://www.python.org/ftp/python/3.12.10/Python-3.12.10.tar.xz",
-        "size": 20520960,
-        "sha256": "07ab697474595e06f06647417d3c7fa97ded07afc1a7e4454c5639919b46eaea",
-        "version": "3.12.10",
+        "url": "https://www.python.org/ftp/python/3.12.11/Python-3.12.11.tar.xz",
+        "size": 20525812,
+        "sha256": "c30bb24b7f1e9a19b11b55a546434f74e739bb4c271a3e3a80ff4380d49f7adb",
+        "version": "3.12.11",
         "licenses": ["Python-2.0", "CNRI-Python"],
         "license_file": "LICENSE.cpython.txt",
         "python_tag": "cp312",
     },
     "cpython-3.13": {
-        "url": "https://www.python.org/ftp/python/3.13.3/Python-3.13.3.tar.xz",
-        "size": 22654240,
-        "sha256": "40f868bcbdeb8149a3149580bb9bfd407b3321cd48f0be631af955ac92c0e041",
-        "version": "3.13.3",
+        "url": "https://www.python.org/ftp/python/3.13.4/Python-3.13.4.tar.xz",
+        "size": 22672472,
+        "sha256": "27b15a797562a2971dce3ffe31bb216042ce0b995b39d768cf15f784cc757365",
+        "version": "3.13.4",
         "licenses": ["Python-2.0", "CNRI-Python"],
         "license_file": "LICENSE.cpython.txt",
         "python_tag": "cp313",

From 5276f3b6042f5554ea69618ab1ada0cd3b7b2a84 Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Thu, 5 Jun 2025 08:27:16 -0500
Subject: [PATCH 105/157] Update to 3.14.0b2 (#647)

---
 cpython-unix/build-cpython.sh                 |  6 +++++
 cpython-unix/patch-jit-cflags-314.patch       | 24 +++++++++----------
 .../patch-static-remote-debug-3.14.patch      | 22 +++++++++++++++++
 pythonbuild/downloads.py                      |  8 +++----
 4 files changed, 44 insertions(+), 16 deletions(-)
 create mode 100644 cpython-unix/patch-static-remote-debug-3.14.patch

diff --git a/cpython-unix/build-cpython.sh b/cpython-unix/build-cpython.sh
index 49e1873c..f3597e5b 100755
--- a/cpython-unix/build-cpython.sh
+++ b/cpython-unix/build-cpython.sh
@@ -83,6 +83,12 @@ else
     patch -p1 -i ${ROOT}/patch-xopen-source-ios-legacy.patch
 fi
 
+# See https://github.com/python/cpython/pull/135146
+# TODO(zanieb): Drop in 3.14b3
+if [ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_14}" ]; then
+    patch -p1 -i ${ROOT}/patch-static-remote-debug-3.14.patch
+fi
+
 # LIBTOOL_CRUFT is unused and breaks cross-compiling on macOS. Nuke it.
 # Submitted upstream at https://github.com/python/cpython/pull/101048.
 if [ -n "${PYTHON_MEETS_MAXIMUM_VERSION_3_11}" ]; then
diff --git a/cpython-unix/patch-jit-cflags-314.patch b/cpython-unix/patch-jit-cflags-314.patch
index 3fc200ad..3a16fb5d 100644
--- a/cpython-unix/patch-jit-cflags-314.patch
+++ b/cpython-unix/patch-jit-cflags-314.patch
@@ -1,5 +1,5 @@
 diff --git a/Tools/jit/_targets.py b/Tools/jit/_targets.py
-index 6ceb4404e74..94b74b5c8b0 100644
+index d0a1c081ffe..deb83f275d2 100644
 --- a/Tools/jit/_targets.py
 +++ b/Tools/jit/_targets.py
 @@ -10,6 +10,7 @@
@@ -16,9 +16,9 @@ index 6ceb4404e74..94b74b5c8b0 100644
      verbose: bool = False
 +    cflags: str = ""
      known_symbols: dict[str, int] = dataclasses.field(default_factory=dict)
+     pyconfig_dir: pathlib.Path = pathlib.Path.cwd().resolve()
  
-     def _get_nop(self) -> bytes:
-@@ -119,6 +121,7 @@ async def _compile(
+@@ -120,6 +122,7 @@ async def _compile(
      ) -> _stencils.StencilGroup:
          o = tempdir / f"{opname}.o"
          args = [
@@ -27,10 +27,10 @@ index 6ceb4404e74..94b74b5c8b0 100644
              "-DPy_BUILD_CORE_MODULE",
              "-D_DEBUG" if self.debug else "-DNDEBUG",
 diff --git a/Tools/jit/build.py b/Tools/jit/build.py
-index 49b08f477db..49a1b11de47 100644
+index 1afd0c76bad..96c4cb07593 100644
 --- a/Tools/jit/build.py
 +++ b/Tools/jit/build.py
-@@ -26,11 +26,15 @@
+@@ -39,11 +39,15 @@
      parser.add_argument(
          "-v", "--verbose", action="store_true", help="echo commands as they are run"
      )
@@ -43,32 +43,32 @@ index 49b08f477db..49a1b11de47 100644
          target.force = args.force
          target.verbose = args.verbose
 +        target.cflags = args.with_cflags
+         target.pyconfig_dir = args.pyconfig_dir
          target.build(
-             out,
              comment=comment,
 diff --git a/configure b/configure
-index c51192f12c8..0dcef7c2617 100755
+index 884f8a4b068..2e6740c33d9 100755
 --- a/configure
 +++ b/configure
 @@ -10863,7 +10863,7 @@ then :
  
  else case e in #(
    e) as_fn_append CFLAGS_NODIST " $jit_flags"
--           REGEN_JIT_COMMAND="\$(PYTHON_FOR_REGEN) \$(srcdir)/Tools/jit/build.py ${ARCH_TRIPLES:-$host}"
-+           REGEN_JIT_COMMAND="\$(PYTHON_FOR_REGEN) \$(srcdir)/Tools/jit/build.py ${ARCH_TRIPLES:-$host} --with-cflags=\"\$(CONFIGURE_CFLAGS)\""
+-           REGEN_JIT_COMMAND="\$(PYTHON_FOR_REGEN) \$(srcdir)/Tools/jit/build.py ${ARCH_TRIPLES:-$host} --output-dir . --pyconfig-dir ."
++           REGEN_JIT_COMMAND="\$(PYTHON_FOR_REGEN) \$(srcdir)/Tools/jit/build.py ${ARCH_TRIPLES:-$host} --output-dir . --pyconfig-dir .  --with-cflags=\"\$(CONFIGURE_CFLAGS)\""
             JIT_STENCILS_H="jit_stencils.h"
             if test "x$Py_DEBUG" = xtrue
  then :
 diff --git a/configure.ac b/configure.ac
-index a7b2f62579b..5998f896a4e 100644
+index cf25148bad2..f8bfab7bf96 100644
 --- a/configure.ac
 +++ b/configure.ac
 @@ -2776,7 +2776,7 @@ AS_VAR_IF([jit_flags],
            [],
            [AS_VAR_APPEND([CFLAGS_NODIST], [" $jit_flags"])
             AS_VAR_SET([REGEN_JIT_COMMAND],
--                      ["\$(PYTHON_FOR_REGEN) \$(srcdir)/Tools/jit/build.py ${ARCH_TRIPLES:-$host}"])
-+                      ["\$(PYTHON_FOR_REGEN) \$(srcdir)/Tools/jit/build.py ${ARCH_TRIPLES:-$host} --with-cflags=\"\$(CONFIGURE_CFLAGS)\""])
+-                      ["\$(PYTHON_FOR_REGEN) \$(srcdir)/Tools/jit/build.py ${ARCH_TRIPLES:-$host} --output-dir . --pyconfig-dir ."])
++                      ["\$(PYTHON_FOR_REGEN) \$(srcdir)/Tools/jit/build.py ${ARCH_TRIPLES:-$host} --output-dir . --pyconfig-dir . --with-cflags=\"\$(CONFIGURE_CFLAGS)\""])
             AS_VAR_SET([JIT_STENCILS_H], ["jit_stencils.h"])
             AS_VAR_IF([Py_DEBUG],
                       [true],
diff --git a/cpython-unix/patch-static-remote-debug-3.14.patch b/cpython-unix/patch-static-remote-debug-3.14.patch
new file mode 100644
index 00000000..1c359c3d
--- /dev/null
+++ b/cpython-unix/patch-static-remote-debug-3.14.patch
@@ -0,0 +1,22 @@
+diff --git a/Python/remote_debug.h b/Python/remote_debug.h
+index 6cbf1c8deaa..ab494ea71da 100644
+--- a/Python/remote_debug.h
++++ b/Python/remote_debug.h
+@@ -131,7 +131,7 @@ _Py_RemoteDebug_FreePageCache(proc_handle_t *handle)
+     }
+ }
+ 
+-void
++static void
+ _Py_RemoteDebug_ClearCache(proc_handle_t *handle)
+ {
+     for (int i = 0; i < MAX_PAGES; i++) {
+@@ -989,7 +989,7 @@ _Py_RemoteDebug_ReadRemoteMemory(proc_handle_t *handle, uintptr_t remote_address
+ #endif
+ }
+ 
+-int
++static int
+ _Py_RemoteDebug_PagedReadRemoteMemory(proc_handle_t *handle,
+                                       uintptr_t addr,
+                                       size_t size,
diff --git a/pythonbuild/downloads.py b/pythonbuild/downloads.py
index 8add331d..d21bf948 100644
--- a/pythonbuild/downloads.py
+++ b/pythonbuild/downloads.py
@@ -82,10 +82,10 @@
         "python_tag": "cp313",
     },
     "cpython-3.14": {
-        "url": "https://www.python.org/ftp/python/3.14.0/Python-3.14.0b1.tar.xz",
-        "size": 23358200,
-        "sha256": "2ddd30a77c9f62e065ce648664a254b9b0c011bcdaa8c1c2787087e644cbeb39",
-        "version": "3.14.0b1",
+        "url": "https://www.python.org/ftp/python/3.14.0/Python-3.14.0b2.tar.xz",
+        "size": 23579860,
+        "sha256": "7ac9e84844bbc0a5a8f1f79a37a68b3b8caf2a58b4aa5999c49227cb36e70ea6",
+        "version": "3.14.0b2",
         "licenses": ["Python-2.0", "CNRI-Python"],
         "license_file": "LICENSE.cpython.txt",
         "python_tag": "cp314",

From 1a91cdade2eda52e9d911a3e85c98c848a5914bf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=90=B4=E5=B0=8F=E7=99=BD?= <296015668@qq.com>
Date: Fri, 6 Jun 2025 00:15:41 +0800
Subject: [PATCH 106/157] fix(workflow): use correct input variable for
 release-create step (#648)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

The release-create step was using an incorrect variable name
(`github.events.input.tag`), which resulted in the `just release-create`
command being called without the required tag argument. This commit
updates the workflow to use the correct variable
(`github.event.inputs.tag`), ensuring the tag is properly passed to the
command.

-
https://github.com/loong64/python-build-standalone/actions/runs/15469452121/job/43549720438

Signed-off-by: 吴小白 <296015668@qq.com>
---
 .github/workflows/release.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 83cee9b6..6381b3e5 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -66,7 +66,7 @@ jobs:
       # Create a GitHub release.
       - name: Create GitHub Release
         if: ${{ github.event.inputs.dry-run == 'false' }}
-        run: just release-create ${{ github.events.input.tag }}
+        run: just release-create ${{ github.event.inputs.tag }}
 
       # Uploading the relevant artifact to the GitHub release.
       - run: just release-run ${{ secrets.GITHUB_TOKEN }} ${{ github.event.inputs.sha }} ${{ github.event.inputs.tag }}

From ea5992016ef80f1de66146dd8865cb32d90b3cc0 Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Fri, 6 Jun 2025 14:18:07 -0500
Subject: [PATCH 107/157] Add patch for stable `uuid.getnode` on 3.13 (#634)

Cherry-picks https://github.com/python/cpython/pull/134704

See #587
---
 cpython-unix/build-cpython.sh                 |   7 +
 .../patch-uuid-getnode-stable-3.13.patch      | 708 ++++++++++++++++++
 2 files changed, 715 insertions(+)
 create mode 100644 cpython-unix/patch-uuid-getnode-stable-3.13.patch

diff --git a/cpython-unix/build-cpython.sh b/cpython-unix/build-cpython.sh
index f3597e5b..a77d6715 100755
--- a/cpython-unix/build-cpython.sh
+++ b/cpython-unix/build-cpython.sh
@@ -76,6 +76,13 @@ if [ -n "${CROSS_COMPILING}" ]; then
     fi
 fi
 
+# `uuid.getnode()` is not stable on our libuuid, CPython should fallback to another method
+# Cherry-pick https://github.com/python/cpython/pull/134704 until it is released
+# We could backport this to more versions too, it won't be done by the upstream
+if [[ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_13}" && -n "${PYTHON_MEETS_MAXIMUM_VERSION_3_14}" ]]; then
+    patch -p1 -i ${ROOT}/patch-uuid-getnode-stable-3.13.patch
+fi
+
 # This patch is slightly different on Python 3.10+.
 if [ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_10}" ]; then
     patch -p1 -i ${ROOT}/patch-xopen-source-ios.patch
diff --git a/cpython-unix/patch-uuid-getnode-stable-3.13.patch b/cpython-unix/patch-uuid-getnode-stable-3.13.patch
new file mode 100644
index 00000000..11bdf83a
--- /dev/null
+++ b/cpython-unix/patch-uuid-getnode-stable-3.13.patch
@@ -0,0 +1,708 @@
+diff --git a/Lib/test/test_uuid.py b/Lib/test/test_uuid.py
+index e7e44c6413c2e2..ce396aa942b6ed 100755
+--- a/Lib/test/test_uuid.py
++++ b/Lib/test/test_uuid.py
+@@ -1,6 +1,7 @@
+ import unittest
+ from test import support
+ from test.support import import_helper
++from test.support.script_helper import assert_python_ok
+ import builtins
+ import contextlib
+ import copy
+@@ -773,10 +774,37 @@ def test_cli_uuid5_ouputted_with_valid_namespace_and_name(self):
+ class TestUUIDWithoutExtModule(BaseTestUUID, unittest.TestCase):
+     uuid = py_uuid
+ 
++
+ @unittest.skipUnless(c_uuid, 'requires the C _uuid module')
+ class TestUUIDWithExtModule(BaseTestUUID, unittest.TestCase):
+     uuid = c_uuid
+ 
++    def check_has_stable_libuuid_extractable_node(self):
++        if not self.uuid._has_stable_extractable_node:
++            self.skipTest("libuuid cannot deduce MAC address")
++
++    @unittest.skipUnless(os.name == 'posix', 'POSIX only')
++    def test_unix_getnode_from_libuuid(self):
++        self.check_has_stable_libuuid_extractable_node()
++        script = 'import uuid; print(uuid._unix_getnode())'
++        _, n_a, _ = assert_python_ok('-c', script)
++        _, n_b, _ = assert_python_ok('-c', script)
++        n_a, n_b = n_a.decode().strip(), n_b.decode().strip()
++        self.assertTrue(n_a.isdigit())
++        self.assertTrue(n_b.isdigit())
++        self.assertEqual(n_a, n_b)
++
++    @unittest.skipUnless(os.name == 'nt', 'Windows only')
++    def test_windows_getnode_from_libuuid(self):
++        self.check_has_stable_libuuid_extractable_node()
++        script = 'import uuid; print(uuid._windll_getnode())'
++        _, n_a, _ = assert_python_ok('-c', script)
++        _, n_b, _ = assert_python_ok('-c', script)
++        n_a, n_b = n_a.decode().strip(), n_b.decode().strip()
++        self.assertTrue(n_a.isdigit())
++        self.assertTrue(n_b.isdigit())
++        self.assertEqual(n_a, n_b)
++
+ 
+ class BaseTestInternals:
+     _uuid = py_uuid
+diff --git a/Lib/uuid.py b/Lib/uuid.py
+index c286eac38e1ef4..6ab1658cc5249a 100644
+--- a/Lib/uuid.py
++++ b/Lib/uuid.py
+@@ -572,22 +572,24 @@ def _netstat_getnode():
+ try:
+     import _uuid
+     _generate_time_safe = getattr(_uuid, "generate_time_safe", None)
++    _has_stable_extractable_node = getattr(_uuid, "has_stable_extractable_node", False)
+     _UuidCreate = getattr(_uuid, "UuidCreate", None)
+ except ImportError:
+     _uuid = None
+     _generate_time_safe = None
++    _has_stable_extractable_node = False
+     _UuidCreate = None
+ 
+ 
+ def _unix_getnode():
+     """Get the hardware address on Unix using the _uuid extension module."""
+-    if _generate_time_safe:
++    if _generate_time_safe and _has_stable_extractable_node:
+         uuid_time, _ = _generate_time_safe()
+         return UUID(bytes=uuid_time).node
+ 
+ def _windll_getnode():
+     """Get the hardware address on Windows using the _uuid extension module."""
+-    if _UuidCreate:
++    if _UuidCreate and _has_stable_extractable_node:
+         uuid_bytes = _UuidCreate()
+         return UUID(bytes_le=uuid_bytes).node
+ 
+diff --git a/Modules/_uuidmodule.c b/Modules/_uuidmodule.c
+index c5e78b1510b5e3..c31a7e8fea5608 100644
+--- a/Modules/_uuidmodule.c
++++ b/Modules/_uuidmodule.c
+@@ -78,23 +78,47 @@ py_UuidCreate(PyObject *Py_UNUSED(context),
+     return NULL;
+ }
+ 
++static int
++py_windows_has_stable_node(void)
++{
++    UUID uuid;
++    RPC_STATUS res;
++    Py_BEGIN_ALLOW_THREADS
++    res = UuidCreateSequential(&uuid);
++    Py_END_ALLOW_THREADS
++    return res == RPC_S_OK;
++}
+ #endif /* MS_WINDOWS */
+ 
+ 
+ static int
+-uuid_exec(PyObject *module) {
++uuid_exec(PyObject *module)
++{
++#define ADD_INT(NAME, VALUE)                                        \
++    do {                                                            \
++        if (PyModule_AddIntConstant(module, (NAME), (VALUE)) < 0) { \
++           return -1;                                               \
++        }                                                           \
++    } while (0)
++
+     assert(sizeof(uuid_t) == 16);
+ #if defined(MS_WINDOWS)
+-    int has_uuid_generate_time_safe = 0;
++    ADD_INT("has_uuid_generate_time_safe", 0);
+ #elif defined(HAVE_UUID_GENERATE_TIME_SAFE)
+-    int has_uuid_generate_time_safe = 1;
++    ADD_INT("has_uuid_generate_time_safe", 1);
+ #else
+-    int has_uuid_generate_time_safe = 0;
++    ADD_INT("has_uuid_generate_time_safe", 0);
+ #endif
+-    if (PyModule_AddIntConstant(module, "has_uuid_generate_time_safe",
+-                                has_uuid_generate_time_safe) < 0) {
+-        return -1;
+-    }
++
++#if defined(MS_WINDOWS)
++    ADD_INT("has_stable_extractable_node", py_windows_has_stable_node());
++#elif defined(HAVE_UUID_GENERATE_TIME_SAFE_STABLE_MAC)
++    ADD_INT("has_stable_extractable_node", 1);
++#else
++    ADD_INT("has_stable_extractable_node", 0);
++#endif
++
++#undef ADD_INT
+     return 0;
+ }
+ 
+diff --git a/configure b/configure
+index 1cd1f690f7b9c1..cc976aafc09b34 100755
+--- a/configure
++++ b/configure
+@@ -13381,6 +13381,7 @@ fi
+ 
+ 
+ 
++
+ have_uuid=missing
+ 
+        for ac_header in uuid.h
+@@ -13390,6 +13391,7 @@ if test "x$ac_cv_header_uuid_h" = xyes
+ then :
+   printf "%s\n" "#define HAVE_UUID_H 1" >>confdefs.h
+ 
++
+   for ac_func in uuid_create uuid_enc_be
+ do :
+   as_ac_var=`printf "%s\n" "ac_cv_func_$ac_func" | $as_tr_sh`
+@@ -13399,7 +13401,9 @@ then :
+   cat >>confdefs.h <<_ACEOF
+ #define `printf "%s\n" "HAVE_$ac_func" | $as_tr_cpp` 1
+ _ACEOF
+- have_uuid=yes
++
++    have_uuid=yes
++    ac_cv_have_uuid_h=yes
+     LIBUUID_CFLAGS=${LIBUUID_CFLAGS-""}
+     LIBUUID_LIBS=${LIBUUID_LIBS-""}
+ 
+@@ -13489,6 +13493,7 @@ if test "x$ac_cv_header_uuid_uuid_h" = xyes
+ then :
+   printf "%s\n" "#define HAVE_UUID_UUID_H 1" >>confdefs.h
+ 
++          ac_cv_have_uuid_uuid_h=yes
+           py_check_lib_save_LIBS=$LIBS
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for uuid_generate_time in -luuid" >&5
+ printf %s "checking for uuid_generate_time in -luuid... " >&6; }
+@@ -13570,8 +13575,9 @@ fi
+ printf "%s\n" "$ac_cv_lib_uuid_uuid_generate_time_safe" >&6; }
+ if test "x$ac_cv_lib_uuid_uuid_generate_time_safe" = xyes
+ then :
+-  have_uuid=yes
+-            printf "%s\n" "#define HAVE_UUID_GENERATE_TIME_SAFE 1" >>confdefs.h
++
++            have_uuid=yes
++            ac_cv_have_uuid_generate_time_safe=yes
+ 
+ fi
+ 
+@@ -13615,6 +13621,7 @@ if test "x$ac_cv_header_uuid_uuid_h" = xyes
+ then :
+   printf "%s\n" "#define HAVE_UUID_UUID_H 1" >>confdefs.h
+ 
++          ac_cv_have_uuid_uuid_h=yes
+           py_check_lib_save_LIBS=$LIBS
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for uuid_generate_time in -luuid" >&5
+ printf %s "checking for uuid_generate_time in -luuid... " >&6; }
+@@ -13696,8 +13703,9 @@ fi
+ printf "%s\n" "$ac_cv_lib_uuid_uuid_generate_time_safe" >&6; }
+ if test "x$ac_cv_lib_uuid_uuid_generate_time_safe" = xyes
+ then :
+-  have_uuid=yes
+-            printf "%s\n" "#define HAVE_UUID_GENERATE_TIME_SAFE 1" >>confdefs.h
++
++            have_uuid=yes
++            ac_cv_have_uuid_generate_time_safe=yes
+ 
+ fi
+ 
+@@ -13727,11 +13735,25 @@ else
+ 	LIBUUID_LIBS=$pkg_cv_LIBUUID_LIBS
+         { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+ printf "%s\n" "yes" >&6; }
++<<<<<<< HEAD
+ 	            have_uuid=yes
+       printf "%s\n" "#define HAVE_UUID_H 1" >>confdefs.h
+ 
+       printf "%s\n" "#define HAVE_UUID_GENERATE_TIME_SAFE 1" >>confdefs.h
+ 
++=======
++                    have_uuid=yes
++      ac_cv_have_uuid_generate_time_safe=yes
++      # The uuid.h file to include may be <uuid.h> *or* <uuid/uuid.h>.
++      # Since pkg-config --cflags uuid may return -I/usr/include/uuid,
++      # it's possible to write '#include <uuid.h>' in _uuidmodule.c,
++      # assuming that the compiler flags are properly updated.
++      #
++      # Ideally, we should have defined HAVE_UUID_H if and only if
++      # #include <uuid.h> can be written, *without* assuming extra
++      # include path.
++      ac_cv_have_uuid_h=yes
++>>>>>>> 3bffada4672 (gh-132710: only use stable `_uuid.generate_time_safe()` to deduce MAC address (#132901))
+ 
+ fi
+ 
+@@ -13752,6 +13774,7 @@ if test "x$ac_cv_func_uuid_generate_time" = xyes
+ then :
+ 
+       have_uuid=yes
++      ac_cv_have_uuid_uuid_h=yes
+       LIBUUID_CFLAGS=${LIBUUID_CFLAGS-""}
+       LIBUUID_LIBS=${LIBUUID_LIBS-""}
+ 
+@@ -13764,11 +13787,198 @@ done
+ 
+ fi
+ 
++<<<<<<< HEAD
++=======
++if test "x$ac_cv_have_uuid_h" = xyes
++then :
++  printf "%s\n" "#define HAVE_UUID_H 1" >>confdefs.h
++
++fi
++if test "x$ac_cv_have_uuid_uuid_h" = xyes
++then :
++  printf "%s\n" "#define HAVE_UUID_UUID_H 1" >>confdefs.h
++
++fi
++if test "x$ac_cv_have_uuid_generate_time_safe" = xyes
++then :
++
++  printf "%s\n" "#define HAVE_UUID_GENERATE_TIME_SAFE 1" >>confdefs.h
++
++
++fi
++
++# gh-124228: While the libuuid library is available on NetBSD, it supports only UUID version 4.
++# This restriction inhibits the proper generation of time-based UUIDs.
++if test "$ac_sys_system" = "NetBSD"; then
++  have_uuid=missing
++  printf "%s\n" "#define HAVE_UUID_H 0" >>confdefs.h
++
++fi
++
++>>>>>>> 3bffada4672 (gh-132710: only use stable `_uuid.generate_time_safe()` to deduce MAC address (#132901))
+ if test "x$have_uuid" = xmissing
+ then :
+   have_uuid=no
+ fi
+ 
++# gh-132710: The UUID node is fetched by using libuuid when possible
++# and cached. While the node is constant within the same process,
++# different interpreters may have different values as libuuid may
++# randomize the node value if the latter cannot be deduced.
++#
++# Consumers may define HAVE_UUID_GENERATE_TIME_SAFE_STABLE_MAC
++# to indicate that libuuid is unstable and should not be relied
++# upon to deduce the MAC address.
++
++
++if test "$have_uuid" = "yes" -a "$HAVE_UUID_GENERATE_TIME_SAFE" = "1"
++then
++  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if uuid_generate_time_safe() node value is stable" >&5
++printf %s "checking if uuid_generate_time_safe() node value is stable... " >&6; }
++  save_CFLAGS=$CFLAGS
++save_CPPFLAGS=$CPPFLAGS
++save_LDFLAGS=$LDFLAGS
++save_LIBS=$LIBS
++
++
++  # Be sure to add the extra include path if we used pkg-config
++  # as HAVE_UUID_H may be set even though <uuid.h> is only reachable
++  # by adding extra -I flags.
++  #
++  # If the following script does not compile, we simply assume that
++  # libuuid is missing.
++  CFLAGS="$CFLAGS $LIBUUID_CFLAGS"
++  LIBS="$LIBS $LIBUUID_LIBS"
++  if test "$cross_compiling" = yes
++then :
++
++
++else case e in #(
++  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++
++    #include <inttypes.h>   // PRIu64
++    #include <stdint.h>     // uint64_t
++    #include <stdio.h>      // fopen(), fclose()
++
++    #ifdef HAVE_UUID_H
++    #include <uuid.h>
++    #else
++    #include <uuid/uuid.h>
++    #endif
++
++    #define ERR 1
++    int main(void) {
++        uuid_t uuid;  // unsigned char[16]
++        (void)uuid_generate_time_safe(uuid);
++        uint64_t node = 0;
++        for (size_t i = 0; i < 6; i++) {
++            node |= (uint64_t)uuid[15 - i] << (8 * i);
++        }
++        FILE *fp = fopen("conftest.out", "w");
++        if (fp == NULL) {
++            return ERR;
++        }
++        int rc = fprintf(fp, "%" PRIu64 "\n", node) >= 0;
++        rc |= fclose(fp);
++        return rc == 0 ? 0 : ERR;
++    }
++_ACEOF
++if ac_fn_c_try_run "$LINENO"
++then :
++
++      py_cv_uuid_node1=`cat conftest.out`
++
++fi
++rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
++  conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
++esac
++fi
++
++CFLAGS=$save_CFLAGS
++CPPFLAGS=$save_CPPFLAGS
++LDFLAGS=$save_LDFLAGS
++LIBS=$save_LIBS
++
++
++  save_CFLAGS=$CFLAGS
++save_CPPFLAGS=$CPPFLAGS
++save_LDFLAGS=$LDFLAGS
++save_LIBS=$LIBS
++
++
++  # Be sure to add the extra include path if we used pkg-config
++  # as HAVE_UUID_H may be set even though <uuid.h> is only reachable
++  # by adding extra -I flags.
++  #
++  # If the following script does not compile, we simply assume that
++  # libuuid is missing.
++  CFLAGS="$CFLAGS $LIBUUID_CFLAGS"
++  LIBS="$LIBS $LIBUUID_LIBS"
++  if test "$cross_compiling" = yes
++then :
++
++
++else case e in #(
++  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h.  */
++
++    #include <inttypes.h>   // PRIu64
++    #include <stdint.h>     // uint64_t
++    #include <stdio.h>      // fopen(), fclose()
++
++    #ifdef HAVE_UUID_H
++    #include <uuid.h>
++    #else
++    #include <uuid/uuid.h>
++    #endif
++
++    #define ERR 1
++    int main(void) {
++        uuid_t uuid;  // unsigned char[16]
++        (void)uuid_generate_time_safe(uuid);
++        uint64_t node = 0;
++        for (size_t i = 0; i < 6; i++) {
++            node |= (uint64_t)uuid[15 - i] << (8 * i);
++        }
++        FILE *fp = fopen("conftest.out", "w");
++        if (fp == NULL) {
++            return ERR;
++        }
++        int rc = fprintf(fp, "%" PRIu64 "\n", node) >= 0;
++        rc |= fclose(fp);
++        return rc == 0 ? 0 : ERR;
++    }
++_ACEOF
++if ac_fn_c_try_run "$LINENO"
++then :
++
++      py_cv_uuid_node2=`cat conftest.out`
++
++fi
++rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
++  conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
++esac
++fi
++
++CFLAGS=$save_CFLAGS
++CPPFLAGS=$save_CPPFLAGS
++LDFLAGS=$save_LDFLAGS
++LIBS=$save_LIBS
++
++
++  if test -n "$py_cv_uuid_node1" -a "$py_cv_uuid_node1" = "$py_cv_uuid_node2"
++  then
++    printf "%s\n" "#define HAVE_UUID_GENERATE_TIME_SAFE_STABLE_MAC 1" >>confdefs.h
++
++    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: stable" >&5
++printf "%s\n" "stable" >&6; }
++  else
++    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unstable" >&5
++printf "%s\n" "unstable" >&6; }
++  fi
++fi
++
+ # 'Real Time' functions on Solaris
+ # posix4 on Solaris 2.6
+ # pthread (first!) on Linux
+diff --git a/configure.ac b/configure.ac
+index 3fcb18922c5330..9898af7ffd5f25 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -3740,15 +3740,17 @@ dnl check for uuid dependencies
+ AH_TEMPLATE([HAVE_UUID_H], [Define to 1 if you have the <uuid.h> header file.])
+ AH_TEMPLATE([HAVE_UUID_UUID_H], [Define to 1 if you have the <uuid/uuid.h> header file.])
+ AH_TEMPLATE([HAVE_UUID_GENERATE_TIME_SAFE], [Define if uuid_generate_time_safe() exists.])
++AH_TEMPLATE([HAVE_UUID_GENERATE_TIME_SAFE_STABLE_MAC], [Define if uuid_generate_time_safe() is able to deduce a MAC address.])
+ have_uuid=missing
+ 
+ dnl AIX provides support for RFC4122 (uuid) in libc.a starting with AIX 6.1
+ dnl (anno 2007). FreeBSD and OpenBSD provides support in libc as well.
+ dnl Little-endian FreeBSD, OpenBSD and NetBSD needs encoding into an octet
+ dnl stream in big-endian byte-order
+-AC_CHECK_HEADERS([uuid.h],
+-  [AC_CHECK_FUNCS([uuid_create uuid_enc_be],
+-    [have_uuid=yes
++AC_CHECK_HEADERS([uuid.h], [
++  AC_CHECK_FUNCS([uuid_create uuid_enc_be], [
++    have_uuid=yes
++    ac_cv_have_uuid_h=yes
+     LIBUUID_CFLAGS=${LIBUUID_CFLAGS-""}
+     LIBUUID_LIBS=${LIBUUID_LIBS-""}
+   ])
+@@ -3758,19 +3760,29 @@ AS_VAR_IF([have_uuid], [missing], [
+   PKG_CHECK_MODULES(
+     [LIBUUID], [uuid >= 2.20],
+       [dnl linux-util's libuuid has uuid_generate_time_safe() since v2.20 (2011)
+-      dnl and provides <uuid.h>.
++      dnl and provides <uuid.h> assuming specific include paths are given
+       have_uuid=yes
+-      AC_DEFINE([HAVE_UUID_H], [1])
+-      AC_DEFINE([HAVE_UUID_GENERATE_TIME_SAFE], [1])
++      ac_cv_have_uuid_generate_time_safe=yes
++      # The uuid.h file to include may be <uuid.h> *or* <uuid/uuid.h>.
++      # Since pkg-config --cflags uuid may return -I/usr/include/uuid,
++      # it's possible to write '#include <uuid.h>' in _uuidmodule.c,
++      # assuming that the compiler flags are properly updated.
++      #
++      # Ideally, we should have defined HAVE_UUID_H if and only if
++      # #include <uuid.h> can be written, *without* assuming extra
++      # include path.
++      ac_cv_have_uuid_h=yes
+     ], [
+       WITH_SAVE_ENV([
+         CPPFLAGS="$CPPFLAGS $LIBUUID_CFLAGS"
+         LIBS="$LIBS $LIBUUID_LIBS"
+         AC_CHECK_HEADERS([uuid/uuid.h], [
++          ac_cv_have_uuid_uuid_h=yes
+           PY_CHECK_LIB([uuid], [uuid_generate_time], [have_uuid=yes])
+-          PY_CHECK_LIB([uuid], [uuid_generate_time_safe],
+-            [have_uuid=yes
+-            AC_DEFINE([HAVE_UUID_GENERATE_TIME_SAFE], [1]) ]) ])
++          PY_CHECK_LIB([uuid], [uuid_generate_time_safe], [
++            have_uuid=yes
++            ac_cv_have_uuid_generate_time_safe=yes
++          ])])
+         AS_VAR_IF([have_uuid], [yes], [
+           LIBUUID_CFLAGS=${LIBUUID_CFLAGS-""}
+           LIBUUID_LIBS=${LIBUUID_LIBS-"-luuid"}
+@@ -3785,14 +3797,90 @@ AS_VAR_IF([have_uuid], [missing], [
+   AC_CHECK_HEADERS([uuid/uuid.h], [
+     AC_CHECK_FUNC([uuid_generate_time], [
+       have_uuid=yes
++      ac_cv_have_uuid_uuid_h=yes
+       LIBUUID_CFLAGS=${LIBUUID_CFLAGS-""}
+       LIBUUID_LIBS=${LIBUUID_LIBS-""}
+     ])
+   ])
+ ])
+ 
++AS_VAR_IF([ac_cv_have_uuid_h], [yes], [AC_DEFINE([HAVE_UUID_H], [1])])
++AS_VAR_IF([ac_cv_have_uuid_uuid_h], [yes], [AC_DEFINE([HAVE_UUID_UUID_H], [1])])
++AS_VAR_IF([ac_cv_have_uuid_generate_time_safe], [yes], [
++  AC_DEFINE([HAVE_UUID_GENERATE_TIME_SAFE], [1])
++])
++
++# gh-124228: While the libuuid library is available on NetBSD, it supports only UUID version 4.
++# This restriction inhibits the proper generation of time-based UUIDs.
++if test "$ac_sys_system" = "NetBSD"; then
++  have_uuid=missing
++  AC_DEFINE([HAVE_UUID_H], [0])
++fi
++
+ AS_VAR_IF([have_uuid], [missing], [have_uuid=no])
+ 
++# gh-132710: The UUID node is fetched by using libuuid when possible
++# and cached. While the node is constant within the same process,
++# different interpreters may have different values as libuuid may
++# randomize the node value if the latter cannot be deduced.
++#
++# Consumers may define HAVE_UUID_GENERATE_TIME_SAFE_STABLE_MAC
++# to indicate that libuuid is unstable and should not be relied
++# upon to deduce the MAC address.
++AC_DEFUN([PY_EXTRACT_UUID_GENERATE_TIME_SAFE_MAC], [WITH_SAVE_ENV([
++  # Be sure to add the extra include path if we used pkg-config
++  # as HAVE_UUID_H may be set even though <uuid.h> is only reachable
++  # by adding extra -I flags.
++  #
++  # If the following script does not compile, we simply assume that
++  # libuuid is missing.
++  CFLAGS="$CFLAGS $LIBUUID_CFLAGS"
++  LIBS="$LIBS $LIBUUID_LIBS"
++  AC_RUN_IFELSE([AC_LANG_SOURCE([[
++    #include <inttypes.h>   // PRIu64
++    #include <stdint.h>     // uint64_t
++    #include <stdio.h>      // fopen(), fclose()
++
++    #ifdef HAVE_UUID_H
++    #include <uuid.h>
++    #else
++    #include <uuid/uuid.h>
++    #endif
++
++    #define ERR 1
++    int main(void) {
++        uuid_t uuid;  // unsigned char[16]
++        (void)uuid_generate_time_safe(uuid);
++        uint64_t node = 0;
++        for (size_t i = 0; i < 6; i++) {
++            node |= (uint64_t)uuid[15 - i] << (8 * i);
++        }
++        FILE *fp = fopen("conftest.out", "w");
++        if (fp == NULL) {
++            return ERR;
++        }
++        int rc = fprintf(fp, "%" PRIu64 "\n", node) >= 0;
++        rc |= fclose(fp);
++        return rc == 0 ? 0 : ERR;
++    }]])], [
++      AS_VAR_SET([$1], [`cat conftest.out`])
++    ], [], []
++  )])])
++
++if test "$have_uuid" = "yes" -a "$HAVE_UUID_GENERATE_TIME_SAFE" = "1"
++then
++  AC_MSG_CHECKING([if uuid_generate_time_safe() node value is stable])
++  PY_EXTRACT_UUID_GENERATE_TIME_SAFE_MAC([py_cv_uuid_node1])
++  PY_EXTRACT_UUID_GENERATE_TIME_SAFE_MAC([py_cv_uuid_node2])
++  if test -n "$py_cv_uuid_node1" -a "$py_cv_uuid_node1" = "$py_cv_uuid_node2"
++  then
++    AC_DEFINE([HAVE_UUID_GENERATE_TIME_SAFE_STABLE_MAC], [1])
++    AC_MSG_RESULT([stable])
++  else
++    AC_MSG_RESULT([unstable])
++  fi
++fi
++
+ # 'Real Time' functions on Solaris
+ # posix4 on Solaris 2.6
+ # pthread (first!) on Linux
+diff --git a/pyconfig.h.in b/pyconfig.h.in
+index 3c16c694c84599..73358a0f35ae82 100644
+--- a/pyconfig.h.in
++++ b/pyconfig.h.in
+@@ -1548,6 +1548,9 @@
+ /* Define if uuid_generate_time_safe() exists. */
+ #undef HAVE_UUID_GENERATE_TIME_SAFE
+ 
++/* Define if uuid_generate_time_safe() is able to deduce a MAC address. */
++#undef HAVE_UUID_GENERATE_TIME_SAFE_STABLE_MAC
++
+ /* Define to 1 if you have the <uuid.h> header file. */
+ #undef HAVE_UUID_H
+ 
+
+From cb0f32a7d64b6dc4a63c4a683bb52a97ebe1d78a Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?=
+ <10796600+picnixz@users.noreply.github.com>
+Date: Mon, 26 May 2025 12:34:00 +0200
+Subject: [PATCH 2/2] rgen
+
+---
+ configure | 25 ++++++-------------------
+ 1 file changed, 6 insertions(+), 19 deletions(-)
+
+diff --git a/configure b/configure
+index cc976aafc09b34..47e4f29e23a7ac 100755
+--- a/configure
++++ b/configure
+@@ -13735,14 +13735,7 @@ else
+ 	LIBUUID_LIBS=$pkg_cv_LIBUUID_LIBS
+         { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+ printf "%s\n" "yes" >&6; }
+-<<<<<<< HEAD
+ 	            have_uuid=yes
+-      printf "%s\n" "#define HAVE_UUID_H 1" >>confdefs.h
+-
+-      printf "%s\n" "#define HAVE_UUID_GENERATE_TIME_SAFE 1" >>confdefs.h
+-
+-=======
+-                    have_uuid=yes
+       ac_cv_have_uuid_generate_time_safe=yes
+       # The uuid.h file to include may be <uuid.h> *or* <uuid/uuid.h>.
+       # Since pkg-config --cflags uuid may return -I/usr/include/uuid,
+@@ -13753,7 +13746,6 @@ printf "%s\n" "yes" >&6; }
+       # #include <uuid.h> can be written, *without* assuming extra
+       # include path.
+       ac_cv_have_uuid_h=yes
+->>>>>>> 3bffada4672 (gh-132710: only use stable `_uuid.generate_time_safe()` to deduce MAC address (#132901))
+ 
+ fi
+ 
+@@ -13787,8 +13779,6 @@ done
+ 
+ fi
+ 
+-<<<<<<< HEAD
+-=======
+ if test "x$ac_cv_have_uuid_h" = xyes
+ then :
+   printf "%s\n" "#define HAVE_UUID_H 1" >>confdefs.h
+@@ -13815,7 +13805,6 @@ if test "$ac_sys_system" = "NetBSD"; then
+ 
+ fi
+ 
+->>>>>>> 3bffada4672 (gh-132710: only use stable `_uuid.generate_time_safe()` to deduce MAC address (#132901))
+ if test "x$have_uuid" = xmissing
+ then :
+   have_uuid=no
+@@ -13853,8 +13842,8 @@ save_LIBS=$LIBS
+ then :
+ 
+ 
+-else case e in #(
+-  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++else $as_nop
++  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+ /* end confdefs.h.  */
+ 
+     #include <inttypes.h>   // PRIu64
+@@ -13891,8 +13880,7 @@ then :
+ 
+ fi
+ rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+-  conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
+-esac
++  conftest.$ac_objext conftest.beam conftest.$ac_ext
+ fi
+ 
+ CFLAGS=$save_CFLAGS
+@@ -13919,8 +13907,8 @@ save_LIBS=$LIBS
+ then :
+ 
+ 
+-else case e in #(
+-  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++else $as_nop
++  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+ /* end confdefs.h.  */
+ 
+     #include <inttypes.h>   // PRIu64
+@@ -13957,8 +13945,7 @@ then :
+ 
+ fi
+ rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+-  conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
+-esac
++  conftest.$ac_objext conftest.beam conftest.$ac_ext
+ fi
+ 
+ CFLAGS=$save_CFLAGS

From 9edbb9d744adbbcc576c75387d10984464c05b0c Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Mon, 9 Jun 2025 12:49:10 -0500
Subject: [PATCH 108/157] Do not apply getnode patch for 3.13 on 3.14 (#649)

---
 cpython-unix/build-cpython.sh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/cpython-unix/build-cpython.sh b/cpython-unix/build-cpython.sh
index a77d6715..820b6a2d 100755
--- a/cpython-unix/build-cpython.sh
+++ b/cpython-unix/build-cpython.sh
@@ -79,7 +79,7 @@ fi
 # `uuid.getnode()` is not stable on our libuuid, CPython should fallback to another method
 # Cherry-pick https://github.com/python/cpython/pull/134704 until it is released
 # We could backport this to more versions too, it won't be done by the upstream
-if [[ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_13}" && -n "${PYTHON_MEETS_MAXIMUM_VERSION_3_14}" ]]; then
+if [[ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_13}" && -n "${PYTHON_MEETS_MAXIMUM_VERSION_3_13}" ]]; then
     patch -p1 -i ${ROOT}/patch-uuid-getnode-stable-3.13.patch
 fi
 

From 3228db3b1394bd2665548e105706eddc4eb772ad Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Tue, 10 Jun 2025 13:48:54 -0500
Subject: [PATCH 109/157] Bump the python group across 1 directory with 4
 updates (#650)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Bumps the python group with 4 updates in the / directory:
[requests](https://github.com/psf/requests),
[mypy](https://github.com/python/mypy),
[ruff](https://github.com/astral-sh/ruff) and
[types-jsonschema](https://github.com/typeshed-internal/stub_uploader).

Updates `requests` from 2.32.3 to 2.32.4
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/psf/requests/releases">requests's
releases</a>.</em></p>
<blockquote>
<h2>v2.32.4</h2>
<h2>2.32.4 (2025-06-10)</h2>
<p><strong>Security</strong></p>
<ul>
<li>CVE-2024-47081 Fixed an issue where a maliciously crafted URL and
trusted
environment will retrieve credentials for the wrong hostname/machine
from a
netrc file. (<a
href="https://redirect.github.com/psf/requests/issues/6965">#6965</a>)</li>
</ul>
<p><strong>Improvements</strong></p>
<ul>
<li>Numerous documentation improvements</li>
</ul>
<p><strong>Deprecations</strong></p>
<ul>
<li>Added support for pypy 3.11 for Linux and macOS. (<a
href="https://redirect.github.com/psf/requests/issues/6926">#6926</a>)</li>
<li>Dropped support for pypy 3.9 following its end of support. (<a
href="https://redirect.github.com/psf/requests/issues/6926">#6926</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/psf/requests/blob/main/HISTORY.md">requests's
changelog</a>.</em></p>
<blockquote>
<h2>2.32.4 (2025-06-10)</h2>
<p><strong>Security</strong></p>
<ul>
<li>CVE-2024-47081 Fixed an issue where a maliciously crafted URL and
trusted
environment will retrieve credentials for the wrong hostname/machine
from a
netrc file.</li>
</ul>
<p><strong>Improvements</strong></p>
<ul>
<li>Numerous documentation improvements</li>
</ul>
<p><strong>Deprecations</strong></p>
<ul>
<li>Added support for pypy 3.11 for Linux and macOS.</li>
<li>Dropped support for pypy 3.9 following its end of support.</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/psf/requests/commit/021dc729f0b71a3030cefdbec7fb57a0e80a6cfd"><code>021dc72</code></a>
Polish up release tooling for last manual release</li>
<li><a
href="https://github.com/psf/requests/commit/821770e822a20a21b207b3907ea83878bda1d396"><code>821770e</code></a>
Bump version and add release notes for v2.32.4</li>
<li><a
href="https://github.com/psf/requests/commit/59f8aa2adf1d3d06bcbf7ce6b13743a1639a5401"><code>59f8aa2</code></a>
Add netrc file search information to authentication documentation (<a
href="https://redirect.github.com/psf/requests/issues/6876">#6876</a>)</li>
<li><a
href="https://github.com/psf/requests/commit/5b4b64c3467fd7a3c03f91ee641aaa348b6bed3b"><code>5b4b64c</code></a>
Add more tests to prevent regression of CVE 2024 47081</li>
<li><a
href="https://github.com/psf/requests/commit/7bc45877a86192af77645e156eb3744f95b47dae"><code>7bc4587</code></a>
Add new test to check netrc auth leak (<a
href="https://redirect.github.com/psf/requests/issues/6962">#6962</a>)</li>
<li><a
href="https://github.com/psf/requests/commit/96ba401c1296ab1dda74a2365ef36d88f7d144ef"><code>96ba401</code></a>
Only use hostname to do netrc lookup instead of netloc</li>
<li><a
href="https://github.com/psf/requests/commit/7341690e842a23cf18ded0abd9229765fa88c4e2"><code>7341690</code></a>
Merge pull request <a
href="https://redirect.github.com/psf/requests/issues/6951">#6951</a>
from tswast/patch-1</li>
<li><a
href="https://github.com/psf/requests/commit/6716d7c9f29df636643fa2489f98890216525cb0"><code>6716d7c</code></a>
remove links</li>
<li><a
href="https://github.com/psf/requests/commit/a7e1c745dc23c18e836febd672416ed0c5d8d8ae"><code>a7e1c74</code></a>
Update docs/conf.py</li>
<li><a
href="https://github.com/psf/requests/commit/c799b8167a13416833ad3b4f3298261a477e826f"><code>c799b81</code></a>
docs: fix dead links to kenreitz.org</li>
<li>Additional commits viewable in <a
href="https://github.com/psf/requests/compare/v2.32.3...v2.32.4">compare
view</a></li>
</ul>
</details>
<br />

Updates `mypy` from 1.15.0 to 1.16.0
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/python/mypy/blob/master/CHANGELOG.md">mypy's
changelog</a>.</em></p>
<blockquote>
<h1>Mypy Release Notes</h1>
<h2>Next Release</h2>
<h3>Remove Support for targeting Python 3.8</h3>
<p>Mypy now requires <code>--python-version 3.9</code> or greater.
Support for only Python 3.8 is
fully removed now. Given an unsupported version, mypy will default to
the oldest
supported one, currently 3.9.</p>
<p>This change is necessary because typeshed stopped supporting Python
3.8 after it
reached its End of Life in October 2024.</p>
<p>Contributed by Marc Mueller
(PR <a
href="https://redirect.github.com/python/mypy/pull/19157">19157</a>, PR
<a
href="https://redirect.github.com/python/mypy/pull/19162">19162</a>).</p>
<h3>Initial Support for Python 3.14</h3>
<p>Mypy is now tested on 3.14 and mypyc works with 3.14.0b3 and later.
Mypyc compiled wheels of mypy itself will be available for new versions
after 3.14.0rc1 is released.</p>
<p>Note that not all new features might be supported just yet.</p>
<p>Contributed by Marc Mueller (PR <a
href="https://redirect.github.com/python/mypy/pull/19164">19164</a>)</p>
<h3>Deprecated Flag: --force-uppercase-builtins</h3>
<p>Mypy only supports Python 3.9+. The --force-uppercase-builtins flag
is now deprecated and a no-op. It will be removed in a future
version.</p>
<p>Contributed by Marc Mueller (PR <a
href="https://redirect.github.com/python/mypy/pull/19176">19176</a>)</p>
<h2>Mypy 1.16</h2>
<p>We’ve just uploaded mypy 1.16 to the Python Package Index (<a
href="https://pypi.org/project/mypy/">PyPI</a>).
Mypy is a static type checker for Python. This release includes new
features and bug fixes.
You can install it as follows:</p>
<pre><code>python3 -m pip install -U mypy
</code></pre>
<p>You can read the full documentation for this release on <a
href="http://mypy.readthedocs.io">Read the Docs</a>.</p>
<h3>Different Property Getter and Setter Types</h3>
<p>Mypy now supports using different types for a property getter and
setter:</p>
<pre lang="python"><code>class A:
    _value: int
<pre><code>@property
</code></pre>
<p>&lt;/tr&gt;&lt;/table&gt;
</code></pre></p>
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/python/mypy/commit/9e72e9601f4c2fb6866cfec98fc40a31c91ccdb0"><code>9e72e96</code></a>
Update version to 1.16.0</li>
<li><a
href="https://github.com/python/mypy/commit/8fe719ff3a8d1e26d3841a48df21ddf7d5b3c94d"><code>8fe719f</code></a>
Add changelog for 1.16 (<a
href="https://redirect.github.com/python/mypy/issues/19138">#19138</a>)</li>
<li><a
href="https://github.com/python/mypy/commit/2a036e739f8691576056669371d9f020e95c2603"><code>2a036e7</code></a>
Revert &quot;Infer correct types with overloads of <code>Type[Guard |
Is]</code> (<a
href="https://redirect.github.com/python/mypy/issues/19161">#19161</a>)</li>
<li><a
href="https://github.com/python/mypy/commit/b6da4fcf97fca9cd28e81a880f818dc364b5a06d"><code>b6da4fc</code></a>
Allow enum members to have type objects as values (<a
href="https://redirect.github.com/python/mypy/issues/19160">#19160</a>)</li>
<li><a
href="https://github.com/python/mypy/commit/334469f999c5c777124a123062b4349614447e0d"><code>334469f</code></a>
[mypyc] Improve documentation of native and non-native classes (<a
href="https://redirect.github.com/python/mypy/issues/19154">#19154</a>)</li>
<li><a
href="https://github.com/python/mypy/commit/a499d9fdba06732248c07586f2fd95c47a4fa0f7"><code>a499d9f</code></a>
Document --allow-redefinition-new (<a
href="https://redirect.github.com/python/mypy/issues/19153">#19153</a>)</li>
<li><a
href="https://github.com/python/mypy/commit/96525a23f0f8a3826d9875fa8b6e8e362cd9525e"><code>96525a2</code></a>
Merge commit '9e45dadcf6d8dbab36f83d9df94a706c0b4f9207' into
release-1.16</li>
<li><a
href="https://github.com/python/mypy/commit/9e45dadcf6d8dbab36f83d9df94a706c0b4f9207"><code>9e45dad</code></a>
Clear more data in TypeChecker.reset() instead of asserting (<a
href="https://redirect.github.com/python/mypy/issues/19087">#19087</a>)</li>
<li><a
href="https://github.com/python/mypy/commit/772cd0cebed6884636de0019e43caa06dbaa39ba"><code>772cd0c</code></a>
Add --strict-bytes to --strict (<a
href="https://redirect.github.com/python/mypy/issues/19049">#19049</a>)</li>
<li><a
href="https://github.com/python/mypy/commit/0b65f215996401264a68a3a06f3fbcd19915a9a5"><code>0b65f21</code></a>
Admit that Final variables are never redefined (<a
href="https://redirect.github.com/python/mypy/issues/19083">#19083</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/python/mypy/compare/v1.15.0...v1.16.0">compare
view</a></li>
</ul>
</details>
<br />

Updates `ruff` from 0.11.11 to 0.11.13
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/astral-sh/ruff/releases">ruff's
releases</a>.</em></p>
<blockquote>
<h2>0.11.13</h2>
<h2>Release Notes</h2>
<h3>Preview features</h3>
<ul>
<li>[<code>airflow</code>] Add unsafe fix for module moved cases
(<code>AIR301</code>,<code>AIR311</code>,<code>AIR312</code>,<code>AIR302</code>)
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/18367">#18367</a>,<a
href="https://redirect.github.com/astral-sh/ruff/pull/18366">#18366</a>,<a
href="https://redirect.github.com/astral-sh/ruff/pull/18363">#18363</a>,<a
href="https://redirect.github.com/astral-sh/ruff/pull/18093">#18093</a>)</li>
<li>[<code>refurb</code>] Add coverage of <code>set</code> and
<code>frozenset</code> calls (<code>FURB171</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/18035">#18035</a>)</li>
<li>[<code>refurb</code>] Mark <code>FURB180</code> fix unsafe when
class has bases (<a
href="https://redirect.github.com/astral-sh/ruff/pull/18149">#18149</a>)</li>
</ul>
<h3>Bug fixes</h3>
<ul>
<li>[<code>perflint</code>] Fix missing parentheses for lambda and
ternary conditions (<code>PERF401</code>, <code>PERF403</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/18412">#18412</a>)</li>
<li>[<code>pyupgrade</code>] Apply <code>UP035</code> only on py313+ for
<code>get_type_hints()</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/18476">#18476</a>)</li>
<li>[<code>pyupgrade</code>] Make fix unsafe if it deletes comments
(<code>UP004</code>,<code>UP050</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/18393">#18393</a>,
<a
href="https://redirect.github.com/astral-sh/ruff/pull/18390">#18390</a>)</li>
</ul>
<h3>Rule changes</h3>
<ul>
<li>[<code>fastapi</code>] Avoid false positive for class dependencies
(<code>FAST003</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/18271">#18271</a>)</li>
</ul>
<h3>Documentation</h3>
<ul>
<li>Update editor setup docs for Neovim and Vim (<a
href="https://redirect.github.com/astral-sh/ruff/pull/18324">#18324</a>)</li>
</ul>
<h3>Other changes</h3>
<ul>
<li>Support Python 3.14 template strings (t-strings) in formatter and
parser (<a
href="https://redirect.github.com/astral-sh/ruff/pull/17851">#17851</a>)</li>
</ul>
<h2>Contributors</h2>
<ul>
<li><a
href="https://github.com/AlexWaygood"><code>@​AlexWaygood</code></a></li>
<li><a
href="https://github.com/BurntSushi"><code>@​BurntSushi</code></a></li>
<li><a
href="https://github.com/InSyncWithFoo"><code>@​InSyncWithFoo</code></a></li>
<li><a href="https://github.com/Lee-W"><code>@​Lee-W</code></a></li>
<li><a
href="https://github.com/MatthewMckee4"><code>@​MatthewMckee4</code></a></li>
<li><a
href="https://github.com/MichaReiser"><code>@​MichaReiser</code></a></li>
<li><a href="https://github.com/Viicos"><code>@​Viicos</code></a></li>
<li><a
href="https://github.com/abhijeetbodas2001"><code>@​abhijeetbodas2001</code></a></li>
<li><a href="https://github.com/carljm"><code>@​carljm</code></a></li>
<li><a
href="https://github.com/chirizxc"><code>@​chirizxc</code></a></li>
<li><a
href="https://github.com/dcreager"><code>@​dcreager</code></a></li>
<li><a
href="https://github.com/dhruvmanila"><code>@​dhruvmanila</code></a></li>
<li><a href="https://github.com/dylwil3"><code>@​dylwil3</code></a></li>
<li><a
href="https://github.com/github-actions"><code>@​github-actions</code></a></li>
<li><a
href="https://github.com/ibraheemdev"><code>@​ibraheemdev</code></a></li>
<li><a
href="https://github.com/lipefree"><code>@​lipefree</code></a></li>
<li><a href="https://github.com/mtshiba"><code>@​mtshiba</code></a></li>
<li><a
href="https://github.com/naslundx"><code>@​naslundx</code></a></li>
<li><a href="https://github.com/ntBre"><code>@​ntBre</code></a></li>
<li><a
href="https://github.com/otakutyrant"><code>@​otakutyrant</code></a></li>
<li><a
href="https://github.com/renovate"><code>@​renovate</code></a></li>
<li><a
href="https://github.com/robsdedude"><code>@​robsdedude</code></a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md">ruff's
changelog</a>.</em></p>
<blockquote>
<h2>0.11.13</h2>
<h3>Preview features</h3>
<ul>
<li>[<code>airflow</code>] Add unsafe fix for module moved cases
(<code>AIR301</code>,<code>AIR311</code>,<code>AIR312</code>,<code>AIR302</code>)
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/18367">#18367</a>,<a
href="https://redirect.github.com/astral-sh/ruff/pull/18366">#18366</a>,<a
href="https://redirect.github.com/astral-sh/ruff/pull/18363">#18363</a>,<a
href="https://redirect.github.com/astral-sh/ruff/pull/18093">#18093</a>)</li>
<li>[<code>refurb</code>] Add coverage of <code>set</code> and
<code>frozenset</code> calls (<code>FURB171</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/18035">#18035</a>)</li>
<li>[<code>refurb</code>] Mark <code>FURB180</code> fix unsafe when
class has bases (<a
href="https://redirect.github.com/astral-sh/ruff/pull/18149">#18149</a>)</li>
</ul>
<h3>Bug fixes</h3>
<ul>
<li>[<code>perflint</code>] Fix missing parentheses for lambda and
ternary conditions (<code>PERF401</code>, <code>PERF403</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/18412">#18412</a>)</li>
<li>[<code>pyupgrade</code>] Apply <code>UP035</code> only on py313+ for
<code>get_type_hints()</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/18476">#18476</a>)</li>
<li>[<code>pyupgrade</code>] Make fix unsafe if it deletes comments
(<code>UP004</code>,<code>UP050</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/18393">#18393</a>,
<a
href="https://redirect.github.com/astral-sh/ruff/pull/18390">#18390</a>)</li>
</ul>
<h3>Rule changes</h3>
<ul>
<li>[<code>fastapi</code>] Avoid false positive for class dependencies
(<code>FAST003</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/18271">#18271</a>)</li>
</ul>
<h3>Documentation</h3>
<ul>
<li>Update editor setup docs for Neovim and Vim (<a
href="https://redirect.github.com/astral-sh/ruff/pull/18324">#18324</a>)</li>
</ul>
<h3>Other changes</h3>
<ul>
<li>Support Python 3.14 template strings (t-strings) in formatter and
parser (<a
href="https://redirect.github.com/astral-sh/ruff/pull/17851">#17851</a>)</li>
</ul>
<h2>0.11.12</h2>
<h3>Preview features</h3>
<ul>
<li>[<code>airflow</code>] Revise fix titles (<code>AIR3</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/18215">#18215</a>)</li>
<li>[<code>pylint</code>] Implement <code>missing-maxsplit-arg</code>
(<code>PLC0207</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/17454">#17454</a>)</li>
<li>[<code>pyupgrade</code>] New rule <code>UP050</code>
(<code>useless-class-metaclass-type</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/18334">#18334</a>)</li>
<li>[<code>flake8-use-pathlib</code>] Replace <code>os.symlink</code>
with <code>Path.symlink_to</code> (<code>PTH211</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/18337">#18337</a>)</li>
</ul>
<h3>Bug fixes</h3>
<ul>
<li>[<code>flake8-bugbear</code>] Ignore <code>__debug__</code>
attribute in <code>B010</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/18357">#18357</a>)</li>
<li>[<code>flake8-async</code>] Fix <code>anyio.sleep</code> argument
name (<code>ASYNC115</code>, <code>ASYNC116</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/18262">#18262</a>)</li>
<li>[<code>refurb</code>] Fix <code>FURB129</code> autofix generating
invalid syntax (<a
href="https://redirect.github.com/astral-sh/ruff/pull/18235">#18235</a>)</li>
</ul>
<h3>Rule changes</h3>
<ul>
<li>[<code>flake8-implicit-str-concat</code>] Add autofix for
<code>ISC003</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/18256">#18256</a>)</li>
<li>[<code>pycodestyle</code>] Improve the diagnostic message for
<code>E712</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/18328">#18328</a>)</li>
<li>[<code>flake8-2020</code>] Fix diagnostic message for
<code>!=</code> comparisons (<code>YTT201</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/18293">#18293</a>)</li>
<li>[<code>pyupgrade</code>] Make fix unsafe if it deletes comments
(<code>UP010</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/18291">#18291</a>)</li>
</ul>
<h3>Documentation</h3>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/astral-sh/ruff/commit/5faf72a4d9b50c6e330165685e57fae14ca68b73"><code>5faf72a</code></a>
Bump 0.11.13 (<a
href="https://redirect.github.com/astral-sh/ruff/issues/18484">#18484</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/28dbc5c51eeb167f5e28308d77dbc697f19bdb10"><code>28dbc5c</code></a>
[ty] Fix completion order in playground (<a
href="https://redirect.github.com/astral-sh/ruff/issues/18480">#18480</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/ce216c79cc853181694439a5f6175bd25fd0d56d"><code>ce216c7</code></a>
Remove <code>Message::to_rule</code> (<a
href="https://redirect.github.com/astral-sh/ruff/issues/18447">#18447</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/33468cc8cc74c2bbbbe8602db9f31dd7d39e0723"><code>33468cc</code></a>
[<code>pyupgrade</code>] Apply <code>UP035</code> only on py313+ for
<code>get_type_hints()</code> (<a
href="https://redirect.github.com/astral-sh/ruff/issues/18476">#18476</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/8531f4b3ca23b1bc877ddd3a4204832673851468"><code>8531f4b</code></a>
[ty] Add infrastructure for AST garbage collection (<a
href="https://redirect.github.com/astral-sh/ruff/issues/18445">#18445</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/55100209c781b35e22b38d22bd7a732ac6b1cc5c"><code>5510020</code></a>
[ty] IDE: add support for <code>object.\&lt;CURSOR&gt;</code>
completions (<a
href="https://redirect.github.com/astral-sh/ruff/issues/18468">#18468</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/c0bb83b88279f5ea21a3b9e8910d23e8437c89b5"><code>c0bb83b</code></a>
[<code>perflint</code>] fix missing parentheses for lambda and ternary
conditions (PERF4...</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/74a4e9af3d52142247be218bd4b524d58b1c56e5"><code>74a4e9a</code></a>
Combine lint and syntax error handling (<a
href="https://redirect.github.com/astral-sh/ruff/issues/18471">#18471</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/8485dbb324212dab0e26d2afb5929097af129bbf"><code>8485dbb</code></a>
[ty] Fix <code>--python</code> argument for Windows, and improve error
messages for bad ...</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/0858896bc434bb7666b7230bde52d2113f328ac9"><code>0858896</code></a>
[ty] type narrowing by attribute/subscript assignments (<a
href="https://redirect.github.com/astral-sh/ruff/issues/18041">#18041</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/astral-sh/ruff/compare/0.11.11...0.11.13">compare
view</a></li>
</ul>
</details>
<br />

Updates `types-jsonschema` from 4.23.0.20250516 to 4.24.0.20250528
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a
href="https://github.com/typeshed-internal/stub_uploader/commits">compare
view</a></li>
</ul>
</details>
<br />


Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
 requirements.dev.txt | 114 ++++++++++++++++++++++---------------------
 requirements.win.txt |   6 +--
 2 files changed, 62 insertions(+), 58 deletions(-)

diff --git a/requirements.dev.txt b/requirements.dev.txt
index 9cb9cd6b..68171eb5 100644
--- a/requirements.dev.txt
+++ b/requirements.dev.txt
@@ -198,44 +198,48 @@ markupsafe==3.0.2 \
     # via
     #   -r requirements.txt
     #   jinja2
-mypy==1.15.0 \
-    --hash=sha256:1124a18bc11a6a62887e3e137f37f53fbae476dc36c185d549d4f837a2a6a14e \
-    --hash=sha256:171a9ca9a40cd1843abeca0e405bc1940cd9b305eaeea2dda769ba096932bb22 \
-    --hash=sha256:1905f494bfd7d85a23a88c5d97840888a7bd516545fc5aaedff0267e0bb54e2f \
-    --hash=sha256:1fbb8da62dc352133d7d7ca90ed2fb0e9d42bb1a32724c287d3c76c58cbaa9c2 \
-    --hash=sha256:2922d42e16d6de288022e5ca321cd0618b238cfc5570e0263e5ba0a77dbef56f \
-    --hash=sha256:2e2c2e6d3593f6451b18588848e66260ff62ccca522dd231cd4dd59b0160668b \
-    --hash=sha256:2ee2d57e01a7c35de00f4634ba1bbf015185b219e4dc5909e281016df43f5ee5 \
-    --hash=sha256:2f2147ab812b75e5b5499b01ade1f4a81489a147c01585cda36019102538615f \
-    --hash=sha256:404534629d51d3efea5c800ee7c42b72a6554d6c400e6a79eafe15d11341fd43 \
-    --hash=sha256:5469affef548bd1895d86d3bf10ce2b44e33d86923c29e4d675b3e323437ea3e \
-    --hash=sha256:5a95fb17c13e29d2d5195869262f8125dfdb5c134dc8d9a9d0aecf7525b10c2c \
-    --hash=sha256:6983aae8b2f653e098edb77f893f7b6aca69f6cffb19b2cc7443f23cce5f4828 \
-    --hash=sha256:712e962a6357634fef20412699a3655c610110e01cdaa6180acec7fc9f8513ba \
-    --hash=sha256:8023ff13985661b50a5928fc7a5ca15f3d1affb41e5f0a9952cb68ef090b31ee \
-    --hash=sha256:811aeccadfb730024c5d3e326b2fbe9249bb7413553f15499a4050f7c30e801d \
-    --hash=sha256:8f8722560a14cde92fdb1e31597760dc35f9f5524cce17836c0d22841830fd5b \
-    --hash=sha256:93faf3fdb04768d44bf28693293f3904bbb555d076b781ad2530214ee53e3445 \
-    --hash=sha256:973500e0774b85d9689715feeffcc980193086551110fd678ebe1f4342fb7c5e \
-    --hash=sha256:979e4e1a006511dacf628e36fadfecbcc0160a8af6ca7dad2f5025529e082c13 \
-    --hash=sha256:98b7b9b9aedb65fe628c62a6dc57f6d5088ef2dfca37903a7d9ee374d03acca5 \
-    --hash=sha256:aea39e0583d05124836ea645f412e88a5c7d0fd77a6d694b60d9b6b2d9f184fd \
-    --hash=sha256:b9378e2c00146c44793c98b8d5a61039a048e31f429fb0eb546d93f4b000bedf \
-    --hash=sha256:baefc32840a9f00babd83251560e0ae1573e2f9d1b067719479bfb0e987c6357 \
-    --hash=sha256:be68172e9fd9ad8fb876c6389f16d1c1b5f100ffa779f77b1fb2176fcc9ab95b \
-    --hash=sha256:c43a7682e24b4f576d93072216bf56eeff70d9140241f9edec0c104d0c515036 \
-    --hash=sha256:c4bb0e1bd29f7d34efcccd71cf733580191e9a264a2202b0239da95984c5b559 \
-    --hash=sha256:c7be1e46525adfa0d97681432ee9fcd61a3964c2446795714699a998d193f1a3 \
-    --hash=sha256:c9817fa23833ff189db061e6d2eff49b2f3b6ed9856b4a0a73046e41932d744f \
-    --hash=sha256:ce436f4c6d218a070048ed6a44c0bbb10cd2cc5e272b29e7845f6a2f57ee4464 \
-    --hash=sha256:d10d994b41fb3497719bbf866f227b3489048ea4bbbb5015357db306249f7980 \
-    --hash=sha256:e601a7fa172c2131bff456bb3ee08a88360760d0d2f8cbd7a75a65497e2df078 \
-    --hash=sha256:f95579473af29ab73a10bada2f9722856792a36ec5af5399b653aa28360290a5
+mypy==1.16.0 \
+    --hash=sha256:021a68568082c5b36e977d54e8f1de978baf401a33884ffcea09bd8e88a98f4c \
+    --hash=sha256:089bedc02307c2548eb51f426e085546db1fa7dd87fbb7c9fa561575cf6eb1ff \
+    --hash=sha256:09a8da6a0ee9a9770b8ff61b39c0bb07971cda90e7297f4213741b48a0cc8d93 \
+    --hash=sha256:0b07e107affb9ee6ce1f342c07f51552d126c32cd62955f59a7db94a51ad12c0 \
+    --hash=sha256:15486beea80be24ff067d7d0ede673b001d0d684d0095803b3e6e17a886a2a92 \
+    --hash=sha256:29e1499864a3888bca5c1542f2d7232c6e586295183320caa95758fc84034031 \
+    --hash=sha256:2e7e0ad35275e02797323a5aa1be0b14a4d03ffdb2e5f2b0489fa07b89c67b21 \
+    --hash=sha256:4086883a73166631307fdd330c4a9080ce24913d4f4c5ec596c601b3a4bdd777 \
+    --hash=sha256:54066fed302d83bf5128632d05b4ec68412e1f03ef2c300434057d66866cea4b \
+    --hash=sha256:55f9076c6ce55dd3f8cd0c6fff26a008ca8e5131b89d5ba6d86bd3f47e736eeb \
+    --hash=sha256:6a2322896003ba66bbd1318c10d3afdfe24e78ef12ea10e2acd985e9d684a666 \
+    --hash=sha256:7909541fef256527e5ee9c0a7e2aeed78b6cda72ba44298d1334fe7881b05c5c \
+    --hash=sha256:82d056e6faa508501af333a6af192c700b33e15865bda49611e3d7d8358ebea2 \
+    --hash=sha256:84b94283f817e2aa6350a14b4a8fb2a35a53c286f97c9d30f53b63620e7af8ab \
+    --hash=sha256:936ccfdd749af4766be824268bfe22d1db9eb2f34a3ea1d00ffbe5b5265f5491 \
+    --hash=sha256:9f826aaa7ff8443bac6a494cf743f591488ea940dd360e7dd330e30dd772a5ab \
+    --hash=sha256:a5fcfdb7318c6a8dd127b14b1052743b83e97a970f0edb6c913211507a255e20 \
+    --hash=sha256:a7e32297a437cc915599e0578fa6bc68ae6a8dc059c9e009c628e1c47f91495d \
+    --hash=sha256:a9e056237c89f1587a3be1a3a70a06a698d25e2479b9a2f57325ddaaffc3567b \
+    --hash=sha256:afe420c9380ccec31e744e8baff0d406c846683681025db3531b32db56962d52 \
+    --hash=sha256:b4968f14f44c62e2ec4a038c8797a87315be8df7740dc3ee8d3bfe1c6bf5dba8 \
+    --hash=sha256:bd4e1ebe126152a7bbaa4daedd781c90c8f9643c79b9748caa270ad542f12bec \
+    --hash=sha256:c5436d11e89a3ad16ce8afe752f0f373ae9620841c50883dc96f8b8805620b13 \
+    --hash=sha256:c6fb60cbd85dc65d4d63d37cb5c86f4e3a301ec605f606ae3a9173e5cf34997b \
+    --hash=sha256:d045d33c284e10a038f5e29faca055b90eee87da3fc63b8889085744ebabb5a1 \
+    --hash=sha256:e71d6f0090c2256c713ed3d52711d01859c82608b5d68d4fa01a3fe30df95571 \
+    --hash=sha256:eb14a4a871bb8efb1e4a50360d4e3c8d6c601e7a31028a2c79f9bb659b63d730 \
+    --hash=sha256:eb5fbc8063cb4fde7787e4c0406aa63094a34a2daf4673f359a1fb64050e9cb2 \
+    --hash=sha256:f2622af30bf01d8fc36466231bdd203d120d7a599a6d88fb22bdcb9dbff84090 \
+    --hash=sha256:f2ed0e0847a80655afa2c121835b848ed101cc7b8d8d6ecc5205aedc732b1436 \
+    --hash=sha256:f56236114c425620875c7cf71700e3d60004858da856c6fc78998ffe767b73d3 \
+    --hash=sha256:feec38097f71797da0231997e0de3a58108c51845399669ebc532c815f93866b
     # via -r requirements.dev.in
 mypy-extensions==1.0.0 \
     --hash=sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d \
     --hash=sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782
     # via mypy
+pathspec==0.12.1 \
+    --hash=sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08 \
+    --hash=sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712
+    # via mypy
 pyyaml==6.0.2 \
     --hash=sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff \
     --hash=sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48 \
@@ -413,25 +417,25 @@ rpds-py==0.22.3 \
     #   -r requirements.txt
     #   jsonschema
     #   referencing
-ruff==0.11.11 \
-    --hash=sha256:1adcb9a18802268aaa891ffb67b1c94cd70578f126637118e8099b8e4adcf112 \
-    --hash=sha256:1b5ab797fcc09121ed82e9b12b6f27e34859e4227080a42d090881be888755d4 \
-    --hash=sha256:6224076c344a7694c6fbbb70d4f2a7b730f6d47d2a9dc1e7f9d9bb583faf390b \
-    --hash=sha256:64ac6f885e3ecb2fdbb71de2701d4e34526651f1e8503af8fb30d4915a3fe345 \
-    --hash=sha256:6c51f136c0364ab1b774767aa8b86331bd8e9d414e2d107db7a2189f35ea1f7b \
-    --hash=sha256:748b4bb245f11e91a04a4ff0f96e386711df0a30412b9fe0c74d5bdc0e4a531f \
-    --hash=sha256:7774173cc7c1980e6bf67569ebb7085989a78a103922fb83ef3dfe230cd0687d \
-    --hash=sha256:7885d9a5e4c77b24e8c88aba8c80be9255fa22ab326019dac2356cff42089fc6 \
-    --hash=sha256:882821fcdf7ae8db7a951df1903d9cb032bbe838852e5fc3c2b6c3ab54e39875 \
-    --hash=sha256:9263f9e5aa4ff1dec765e99810f1cc53f0c868c5329b69f13845f699fe74f639 \
-    --hash=sha256:9924e5ae54125ed8958a4f7de320dab7380f6e9fa3195e3dc3b137c6842a0092 \
-    --hash=sha256:99c28505ecbaeb6594701a74e395b187ee083ee26478c1a795d35084d53ebd81 \
-    --hash=sha256:a97c9babe1d4081037a90289986925726b802d180cca784ac8da2bbbc335f709 \
-    --hash=sha256:c8a93276393d91e952f790148eb226658dd275cddfde96c6ca304873f11d2ae4 \
-    --hash=sha256:d6e333dbe2e6ae84cdedefa943dfd6434753ad321764fd937eef9d6b62022bcd \
-    --hash=sha256:d8c4ddcbe8a19f59f57fd814b8b117d4fcea9bee7c0492e6cf5fdc22cfa563c8 \
-    --hash=sha256:dcec2d50756463d9df075a26a85a6affbc1b0148873da3997286caf1ce03cae1 \
-    --hash=sha256:e231ff3132c1119ece836487a02785f099a43992b95c2f62847d29bace3c75ac
+ruff==0.11.13 \
+    --hash=sha256:1808b3ed53e1a777c2ef733aca9051dc9bf7c99b26ece15cb59a0320fbdbd629 \
+    --hash=sha256:26816a218ca6ef02142343fd24c70f7cd8c5aa6c203bca284407adf675984432 \
+    --hash=sha256:26fa247dc68d1d4e72c179e08889a25ac0c7ba4d78aecfc835d49cbfd60bf514 \
+    --hash=sha256:29c3189895a8a6a657b7af4e97d330c8a3afd2c9c8f46c81e2fc5a31866517e3 \
+    --hash=sha256:4a9ddd3ec62a9a89578c85842b836e4ac832d4a2e0bfaad3b02243f930ceafcc \
+    --hash=sha256:4bdfbf1240533f40042ec00c9e09a3aade6f8c10b6414cf11b519488d2635d46 \
+    --hash=sha256:4ffbc82d70424b275b089166310448051afdc6e914fdab90e08df66c43bb5ca9 \
+    --hash=sha256:51c3f95abd9331dc5b87c47ac7f376db5616041173826dfd556cfe3d4977f492 \
+    --hash=sha256:53b15a9dfdce029c842e9a5aebc3855e9ab7771395979ff85b7c1dedb53ddc2b \
+    --hash=sha256:55e4bc3a77842da33c16d55b32c6cac1ec5fb0fbec9c8c513bdce76c4f922165 \
+    --hash=sha256:633bf2c6f35678c56ec73189ba6fa19ff1c5e4807a78bf60ef487b9dd272cc71 \
+    --hash=sha256:6c51f93029d54a910d3d24f7dd0bb909e31b6cd989a5e4ac513f4eb41629f0dc \
+    --hash=sha256:96c27935418e4e8e77a26bb05962817f28b8ef3843a6c6cc49d8783b5507f250 \
+    --hash=sha256:ab153241400789138d13f362c43f7edecc0edfffce2afa6a68434000ecd8f69a \
+    --hash=sha256:aef9c9ed1b5ca28bb15c7eac83b8670cf3b20b478195bd49c8d756ba0a36cf48 \
+    --hash=sha256:b4385285e9179d608ff1d2fb9922062663c658605819a6876d8beef0c30b7f3b \
+    --hash=sha256:d237a496e0778d719efb05058c64d28b757c77824e04ffe8796c7436e26712b7 \
+    --hash=sha256:d28ce58b5ecf0f43c1b71edffabe6ed7f245d5336b17805803312ec9bc665933
     # via -r requirements.dev.in
 six==1.17.0 \
     --hash=sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274 \
@@ -477,9 +481,9 @@ types-jinja2==2.11.9 \
     --hash=sha256:60a1e21e8296979db32f9374d8a239af4cb541ff66447bb915d8ad398f9c63b2 \
     --hash=sha256:dbdc74a40aba7aed520b7e4d89e8f0fe4286518494208b35123bcf084d4b8c81
     # via -r requirements.dev.in
-types-jsonschema==4.23.0.20250516 \
-    --hash=sha256:9ace09d9d35c4390a7251ccd7d833b92ccc189d24d1b347f26212afce361117e \
-    --hash=sha256:e7d0dd7db7e59e63c26e3230e26ffc64c4704cc5170dc21270b366a35ead1618
+types-jsonschema==4.24.0.20250528 \
+    --hash=sha256:6a906b5ff73ac11c8d1e0b6c30a9693e1e4e1ab56c56c932b3a7e081b86d187b \
+    --hash=sha256:7e28c64e0ae7980eeb158105b20663fc6a6b8f81d5f86ea6614aa0014417bd1e
     # via -r requirements.dev.in
 types-markupsafe==1.1.10 \
     --hash=sha256:85b3a872683d02aea3a5ac2a8ef590193c344092032f58457287fbf8e06711b1 \
diff --git a/requirements.win.txt b/requirements.win.txt
index 222620eb..d37a96ff 100644
--- a/requirements.win.txt
+++ b/requirements.win.txt
@@ -264,9 +264,9 @@ referencing==0.36.2 \
     # via
     #   jsonschema
     #   jsonschema-specifications
-requests==2.32.3 \
-    --hash=sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760 \
-    --hash=sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6
+requests==2.32.4 \
+    --hash=sha256:27babd3cda2a6d50b30443204ee89830707d396671944c998b5975b031ac2b2c \
+    --hash=sha256:27d0316682c8a29834d3264820024b62a36942083d52caf2f14c0591336d3422
     # via docker
 rpds-py==0.25.1 \
     --hash=sha256:0317177b1e8691ab5879f4f33f4b6dc55ad3b344399e23df2e499de7b10a548d \

From 383aa562ca1e32a58811a104284e75db1d411870 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Tue, 10 Jun 2025 13:49:05 -0500
Subject: [PATCH 110/157] Bump requests from 2.32.3 to 2.32.4 (#651)

Bumps [requests](https://github.com/psf/requests) from 2.32.3 to 2.32.4.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/psf/requests/releases">requests's
releases</a>.</em></p>
<blockquote>
<h2>v2.32.4</h2>
<h2>2.32.4 (2025-06-10)</h2>
<p><strong>Security</strong></p>
<ul>
<li>CVE-2024-47081 Fixed an issue where a maliciously crafted URL and
trusted
environment will retrieve credentials for the wrong hostname/machine
from a
netrc file. (<a
href="https://redirect.github.com/psf/requests/issues/6965">#6965</a>)</li>
</ul>
<p><strong>Improvements</strong></p>
<ul>
<li>Numerous documentation improvements</li>
</ul>
<p><strong>Deprecations</strong></p>
<ul>
<li>Added support for pypy 3.11 for Linux and macOS. (<a
href="https://redirect.github.com/psf/requests/issues/6926">#6926</a>)</li>
<li>Dropped support for pypy 3.9 following its end of support. (<a
href="https://redirect.github.com/psf/requests/issues/6926">#6926</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/psf/requests/blob/main/HISTORY.md">requests's
changelog</a>.</em></p>
<blockquote>
<h2>2.32.4 (2025-06-10)</h2>
<p><strong>Security</strong></p>
<ul>
<li>CVE-2024-47081 Fixed an issue where a maliciously crafted URL and
trusted
environment will retrieve credentials for the wrong hostname/machine
from a
netrc file.</li>
</ul>
<p><strong>Improvements</strong></p>
<ul>
<li>Numerous documentation improvements</li>
</ul>
<p><strong>Deprecations</strong></p>
<ul>
<li>Added support for pypy 3.11 for Linux and macOS.</li>
<li>Dropped support for pypy 3.9 following its end of support.</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/psf/requests/commit/021dc729f0b71a3030cefdbec7fb57a0e80a6cfd"><code>021dc72</code></a>
Polish up release tooling for last manual release</li>
<li><a
href="https://github.com/psf/requests/commit/821770e822a20a21b207b3907ea83878bda1d396"><code>821770e</code></a>
Bump version and add release notes for v2.32.4</li>
<li><a
href="https://github.com/psf/requests/commit/59f8aa2adf1d3d06bcbf7ce6b13743a1639a5401"><code>59f8aa2</code></a>
Add netrc file search information to authentication documentation (<a
href="https://redirect.github.com/psf/requests/issues/6876">#6876</a>)</li>
<li><a
href="https://github.com/psf/requests/commit/5b4b64c3467fd7a3c03f91ee641aaa348b6bed3b"><code>5b4b64c</code></a>
Add more tests to prevent regression of CVE 2024 47081</li>
<li><a
href="https://github.com/psf/requests/commit/7bc45877a86192af77645e156eb3744f95b47dae"><code>7bc4587</code></a>
Add new test to check netrc auth leak (<a
href="https://redirect.github.com/psf/requests/issues/6962">#6962</a>)</li>
<li><a
href="https://github.com/psf/requests/commit/96ba401c1296ab1dda74a2365ef36d88f7d144ef"><code>96ba401</code></a>
Only use hostname to do netrc lookup instead of netloc</li>
<li><a
href="https://github.com/psf/requests/commit/7341690e842a23cf18ded0abd9229765fa88c4e2"><code>7341690</code></a>
Merge pull request <a
href="https://redirect.github.com/psf/requests/issues/6951">#6951</a>
from tswast/patch-1</li>
<li><a
href="https://github.com/psf/requests/commit/6716d7c9f29df636643fa2489f98890216525cb0"><code>6716d7c</code></a>
remove links</li>
<li><a
href="https://github.com/psf/requests/commit/a7e1c745dc23c18e836febd672416ed0c5d8d8ae"><code>a7e1c74</code></a>
Update docs/conf.py</li>
<li><a
href="https://github.com/psf/requests/commit/c799b8167a13416833ad3b4f3298261a477e826f"><code>c799b81</code></a>
docs: fix dead links to kenreitz.org</li>
<li>Additional commits viewable in <a
href="https://github.com/psf/requests/compare/v2.32.3...v2.32.4">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=requests&package-manager=pip&previous-version=2.32.3&new-version=2.32.4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/astral-sh/python-build-standalone/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

From 5cc924bf04b73004c57bf438476255c1b5b63e9f Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Wed, 11 Jun 2025 14:08:37 -0500
Subject: [PATCH 111/157] Upgrade setuptools to 80.9.0 (#656)

Closes https://github.com/astral-sh/python-build-standalone/issues/654
---
 pythonbuild/downloads.py | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/pythonbuild/downloads.py b/pythonbuild/downloads.py
index d21bf948..5c022775 100644
--- a/pythonbuild/downloads.py
+++ b/pythonbuild/downloads.py
@@ -281,10 +281,10 @@
         "license_file": "LICENSE.readline.txt",
     },
     "setuptools": {
-        "url": "https://files.pythonhosted.org/packages/55/21/47d163f615df1d30c094f6c8bbb353619274edccf0327b185cc2493c2c33/setuptools-75.6.0-py3-none-any.whl",
-        "size": 1224032,
-        "sha256": "ce74b49e8f7110f9bf04883b730f4765b774ef3ef28f722cce7c273d253aaf7d",
-        "version": "75.6.0",
+        "url": "https://files.pythonhosted.org/packages/a3/dc/17031897dae0efacfea57dfd3a82fdd2a2aeb58e0ff71b77b87e44edc772/setuptools-80.9.0-py3-none-any.whl",
+        "size": 1201486,
+        "sha256": "062d34222ad13e0cc312a4c02d73f059e86a4acbfbdea8f8f76b28c99f306922",
+        "version": "80.9.0",
     },
     # Remember to update verify_distribution.py when version changed.
     "sqlite": {

From bd92d957e9779badfc1b42e8e307a5b8353108db Mon Sep 17 00:00:00 2001
From: Geoffrey Thomas <geofft@ldpreload.com>
Date: Thu, 12 Jun 2025 08:16:08 -0400
Subject: [PATCH 112/157] Upgrade CPython 3.13 to 3.13.5 (#657)

https://www.python.org/downloads/release/python-3135/
---
 pythonbuild/downloads.py | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/pythonbuild/downloads.py b/pythonbuild/downloads.py
index 5c022775..f59afd82 100644
--- a/pythonbuild/downloads.py
+++ b/pythonbuild/downloads.py
@@ -73,10 +73,10 @@
         "python_tag": "cp312",
     },
     "cpython-3.13": {
-        "url": "https://www.python.org/ftp/python/3.13.4/Python-3.13.4.tar.xz",
-        "size": 22672472,
-        "sha256": "27b15a797562a2971dce3ffe31bb216042ce0b995b39d768cf15f784cc757365",
-        "version": "3.13.4",
+        "url": "https://www.python.org/ftp/python/3.13.5/Python-3.13.5.tar.xz",
+        "size": 22856016,
+        "sha256": "93e583f243454e6e9e4588ca2c2662206ad961659863277afcdb96801647d640",
+        "version": "3.13.5",
         "licenses": ["Python-2.0", "CNRI-Python"],
         "license_file": "LICENSE.cpython.txt",
         "python_tag": "cp313",

From fe33e63812ce0758cf8c179afb8558a52d7d296c Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Thu, 12 Jun 2025 18:21:57 -0500
Subject: [PATCH 113/157] Use the latest patch for the CFLAGS JIT configuration
 (#659)

---
 cpython-unix/build-cpython.sh           |  3 +-
 cpython-unix/patch-jit-cflags-314.patch | 46 +++++++++++++++++--------
 2 files changed, 33 insertions(+), 16 deletions(-)

diff --git a/cpython-unix/build-cpython.sh b/cpython-unix/build-cpython.sh
index 820b6a2d..75f330d9 100755
--- a/cpython-unix/build-cpython.sh
+++ b/cpython-unix/build-cpython.sh
@@ -653,7 +653,8 @@ fi
 # We patched configure.ac above. Reflect those changes.
 autoconf
 
-CFLAGS=$CFLAGS CPPFLAGS=$CFLAGS LDFLAGS=$LDFLAGS \
+# Ensure `CFLAGS` are propagated to JIT compilation for 3.13+
+CFLAGS=$CFLAGS CPPFLAGS=$CFLAGS JIT_CFLAGS=$CFLAGS LDFLAGS=$LDFLAGS \
     ./configure ${CONFIGURE_FLAGS}
 
 # Supplement produced Makefile with our modifications.
diff --git a/cpython-unix/patch-jit-cflags-314.patch b/cpython-unix/patch-jit-cflags-314.patch
index 3a16fb5d..a75563b4 100644
--- a/cpython-unix/patch-jit-cflags-314.patch
+++ b/cpython-unix/patch-jit-cflags-314.patch
@@ -1,5 +1,12 @@
+diff --git a/Misc/NEWS.d/next/Build/2025-05-19-18-09-20.gh-issue-134273.ZAliyy.rst b/Misc/NEWS.d/next/Build/2025-05-19-18-09-20.gh-issue-134273.ZAliyy.rst
+new file mode 100644
+index 00000000000..3eb13cefbe6
+--- /dev/null
++++ b/Misc/NEWS.d/next/Build/2025-05-19-18-09-20.gh-issue-134273.ZAliyy.rst
+@@ -0,0 +1 @@
++Add support for configuring compiler flags for the JIT with ``CFLAGS_JIT``
 diff --git a/Tools/jit/_targets.py b/Tools/jit/_targets.py
-index d0a1c081ffe..deb83f275d2 100644
+index d0a1c081ffe..b383e39da19 100644
 --- a/Tools/jit/_targets.py
 +++ b/Tools/jit/_targets.py
 @@ -10,6 +10,7 @@
@@ -18,16 +25,25 @@ index d0a1c081ffe..deb83f275d2 100644
      known_symbols: dict[str, int] = dataclasses.field(default_factory=dict)
      pyconfig_dir: pathlib.Path = pathlib.Path.cwd().resolve()
  
-@@ -120,6 +122,7 @@ async def _compile(
-     ) -> _stencils.StencilGroup:
-         o = tempdir / f"{opname}.o"
-         args = [
+@@ -62,6 +64,7 @@ def _compute_digest(self) -> str:
+         hasher = hashlib.sha256()
+         hasher.update(self.triple.encode())
+         hasher.update(self.debug.to_bytes())
++        hasher.update(self.cflags.encode())
+         # These dependencies are also reflected in _JITSources in regen.targets:
+         hasher.update(PYTHON_EXECUTOR_CASES_C_H.read_bytes())
+         hasher.update((self.pyconfig_dir / "pyconfig.h").read_bytes())
+@@ -155,6 +158,8 @@ async def _compile(
+             f"{o}",
+             f"{c}",
+             *self.args,
++            # Allow user-provided CFLAGS to override any defaults
 +            *shlex.split(self.cflags),
-             f"--target={self.triple}",
-             "-DPy_BUILD_CORE_MODULE",
-             "-D_DEBUG" if self.debug else "-DNDEBUG",
+         ]
+         await _llvm.run("clang", args, echo=self.verbose)
+         return await self._parse(o)
 diff --git a/Tools/jit/build.py b/Tools/jit/build.py
-index 1afd0c76bad..96c4cb07593 100644
+index 1afd0c76bad..a0733005929 100644
 --- a/Tools/jit/build.py
 +++ b/Tools/jit/build.py
 @@ -39,11 +39,15 @@
@@ -35,19 +51,19 @@ index 1afd0c76bad..96c4cb07593 100644
          "-v", "--verbose", action="store_true", help="echo commands as they are run"
      )
 +    parser.add_argument(
-+        "--with-cflags", help="additional flags to pass to the compiler", default=""
++        "--cflags", help="additional flags to pass to the compiler", default=""
 +    )
      args = parser.parse_args()
      for target in args.target:
          target.debug = args.debug
          target.force = args.force
          target.verbose = args.verbose
-+        target.cflags = args.with_cflags
++        target.cflags = args.cflags
          target.pyconfig_dir = args.pyconfig_dir
          target.build(
              comment=comment,
 diff --git a/configure b/configure
-index 884f8a4b068..2e6740c33d9 100755
+index 029bf527da4..fef9f2d7da9 100755
 --- a/configure
 +++ b/configure
 @@ -10863,7 +10863,7 @@ then :
@@ -55,12 +71,12 @@ index 884f8a4b068..2e6740c33d9 100755
  else case e in #(
    e) as_fn_append CFLAGS_NODIST " $jit_flags"
 -           REGEN_JIT_COMMAND="\$(PYTHON_FOR_REGEN) \$(srcdir)/Tools/jit/build.py ${ARCH_TRIPLES:-$host} --output-dir . --pyconfig-dir ."
-+           REGEN_JIT_COMMAND="\$(PYTHON_FOR_REGEN) \$(srcdir)/Tools/jit/build.py ${ARCH_TRIPLES:-$host} --output-dir . --pyconfig-dir .  --with-cflags=\"\$(CONFIGURE_CFLAGS)\""
++           REGEN_JIT_COMMAND="\$(PYTHON_FOR_REGEN) \$(srcdir)/Tools/jit/build.py ${ARCH_TRIPLES:-$host} --output-dir . --pyconfig-dir . --cflags=\"$CFLAGS_JIT\""
             JIT_STENCILS_H="jit_stencils.h"
             if test "x$Py_DEBUG" = xtrue
  then :
 diff --git a/configure.ac b/configure.ac
-index cf25148bad2..f8bfab7bf96 100644
+index 371b2e8ed73..cc37a636c52 100644
 --- a/configure.ac
 +++ b/configure.ac
 @@ -2776,7 +2776,7 @@ AS_VAR_IF([jit_flags],
@@ -68,7 +84,7 @@ index cf25148bad2..f8bfab7bf96 100644
            [AS_VAR_APPEND([CFLAGS_NODIST], [" $jit_flags"])
             AS_VAR_SET([REGEN_JIT_COMMAND],
 -                      ["\$(PYTHON_FOR_REGEN) \$(srcdir)/Tools/jit/build.py ${ARCH_TRIPLES:-$host} --output-dir . --pyconfig-dir ."])
-+                      ["\$(PYTHON_FOR_REGEN) \$(srcdir)/Tools/jit/build.py ${ARCH_TRIPLES:-$host} --output-dir . --pyconfig-dir . --with-cflags=\"\$(CONFIGURE_CFLAGS)\""])
++                      ["\$(PYTHON_FOR_REGEN) \$(srcdir)/Tools/jit/build.py ${ARCH_TRIPLES:-$host} --output-dir . --pyconfig-dir . --cflags=\"$CFLAGS_JIT\""])
             AS_VAR_SET([JIT_STENCILS_H], ["jit_stencils.h"])
             AS_VAR_IF([Py_DEBUG],
                       [true],

From cb5ec0b456d7b929119cd9a8ad3fdca0f55e0115 Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Fri, 13 Jun 2025 09:14:45 -0500
Subject: [PATCH 114/157] Fix `CFLAGS_JIT` declaration (#660)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Silly typo in #659 — turns out macOS is where it fails with the wrong
flags, not Linux
---
 cpython-unix/build-cpython.sh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/cpython-unix/build-cpython.sh b/cpython-unix/build-cpython.sh
index 75f330d9..2296f2bf 100755
--- a/cpython-unix/build-cpython.sh
+++ b/cpython-unix/build-cpython.sh
@@ -654,7 +654,7 @@ fi
 autoconf
 
 # Ensure `CFLAGS` are propagated to JIT compilation for 3.13+
-CFLAGS=$CFLAGS CPPFLAGS=$CFLAGS JIT_CFLAGS=$CFLAGS LDFLAGS=$LDFLAGS \
+CFLAGS=$CFLAGS CPPFLAGS=$CFLAGS CFLAGS_JIT=$CFLAGS LDFLAGS=$LDFLAGS \
     ./configure ${CONFIGURE_FLAGS}
 
 # Supplement produced Makefile with our modifications.

From 69f53e2028a75d4c1d26de0bc5476d86fcae8836 Mon Sep 17 00:00:00 2001
From: Jack O'Connor <oconnor663@gmail.com>
Date: Tue, 10 Jun 2025 19:34:19 -0700
Subject: [PATCH 115/157] patch libedit to stop re-broadcasting signals

---
 cpython-unix/build-libedit.sh | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/cpython-unix/build-libedit.sh b/cpython-unix/build-libedit.sh
index 08387ece..61220593 100755
--- a/cpython-unix/build-libedit.sh
+++ b/cpython-unix/build-libedit.sh
@@ -82,6 +82,32 @@ index 614795f..4671f1b 100755
  fi
 EOF
 
+# When libedit receives a signal, it re-broadcasts it to its entire pgroup.
+# This seems intended to preserve normal ^C behavior in "raw" mode when the
+# terminal's ISIG flag is cleared? However, libedit does not in fact clear
+# ISIG. (And Jack can't find any evidence of any version that ever did.) This
+# sometimes results in the parent process receiving ^C twice back-to-back,
+# depending on the vagaries of signal coalescing. More pathologically, if the
+# parent tries to signal the child directly with e.g. `kill(pid, SIGTERM)`,
+# libedit *signals the parent right back* (not to mention any other pgroup
+# siblings or grandparents). This is just wild behavior, even though it's
+# probably rare that it matters in practice. Patch it out. See also:
+# https://github.com/astral-sh/uv/issues/13919#issuecomment-2960501229.
+patch -p1 << "EOF"
+diff --git i/src/sig.c w/src/sig.c
+index d2b77e7..884b2dd 100644
+--- i/src/sig.c
++++ w/src/sig.c
+@@ -107,7 +107,7 @@ sig_handler(int signo)
+ 	sel->el_signal->sig_action[i].sa_flags = 0;
+ 	sigemptyset(&sel->el_signal->sig_action[i].sa_mask);
+ 	(void) sigprocmask(SIG_SETMASK, &oset, NULL);
+-	(void) kill(0, signo);
++	(void) raise(signo);
+ 	errno = save_errno;
+ }
+EOF
+
 cflags="${EXTRA_TARGET_CFLAGS} -fPIC -I${TOOLS_PATH}/deps/include -I${TOOLS_PATH}/deps/include/ncursesw"
 ldflags="${EXTRA_TARGET_LDFLAGS} -L${TOOLS_PATH}/deps/lib"
 

From 45f514c647b755d9d90f218b2bdbe6765cc5ecbd Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Wed, 18 Jun 2025 11:13:29 -0500
Subject: [PATCH 116/157] Use Depot runners for Windows builds (#664)

Goes from a range of 26-32m -> 15->23m
---
 ci-runners.yaml | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/ci-runners.yaml b/ci-runners.yaml
index aeb0e5ca..e8d9f5a0 100644
--- a/ci-runners.yaml
+++ b/ci-runners.yaml
@@ -26,6 +26,11 @@ macos-latest:
   platform: darwin
   free: true
 
+depot-windows-2022-8:
+  arch: x86_64
+  platform: windows
+  free: false
+
 windows-latest-large:
   arch: x86_64
   platform: windows

From 4c3dfd82929a3dc199a1e93a62589598e8271631 Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Thu, 26 Jun 2025 15:57:38 -0500
Subject: [PATCH 117/157] Bump to CPython 3.14.0b3 (#663)

---
 cpython-unix/build-cpython.sh                 | 25 ++++++++++++-------
 .../patch-static-remote-debug-3.14.patch      | 22 ----------------
 pythonbuild/downloads.py                      |  8 +++---
 3 files changed, 20 insertions(+), 35 deletions(-)
 delete mode 100644 cpython-unix/patch-static-remote-debug-3.14.patch

diff --git a/cpython-unix/build-cpython.sh b/cpython-unix/build-cpython.sh
index 2296f2bf..ce88e6c7 100755
--- a/cpython-unix/build-cpython.sh
+++ b/cpython-unix/build-cpython.sh
@@ -90,12 +90,6 @@ else
     patch -p1 -i ${ROOT}/patch-xopen-source-ios-legacy.patch
 fi
 
-# See https://github.com/python/cpython/pull/135146
-# TODO(zanieb): Drop in 3.14b3
-if [ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_14}" ]; then
-    patch -p1 -i ${ROOT}/patch-static-remote-debug-3.14.patch
-fi
-
 # LIBTOOL_CRUFT is unused and breaks cross-compiling on macOS. Nuke it.
 # Submitted upstream at https://github.com/python/cpython/pull/101048.
 if [ -n "${PYTHON_MEETS_MAXIMUM_VERSION_3_11}" ]; then
@@ -485,7 +479,9 @@ if [ -n "${CPYTHON_OPTIMIZED}" ]; then
         fi
 
         # Respect CFLAGS during JIT compilation.
-        # Backports https://github.com/python/cpython/pull/134276
+        #
+        # Backports https://github.com/python/cpython/pull/134276 which we're trying to get released
+        # in 3.14, but is currently only in 3.15+.
         if [ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_14}" ]; then
             patch -p1 -i ${ROOT}/patch-jit-cflags-314.patch
         elif [ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_13}" ]; then
@@ -653,8 +649,19 @@ fi
 # We patched configure.ac above. Reflect those changes.
 autoconf
 
-# Ensure `CFLAGS` are propagated to JIT compilation for 3.13+
-CFLAGS=$CFLAGS CPPFLAGS=$CFLAGS CFLAGS_JIT=$CFLAGS LDFLAGS=$LDFLAGS \
+# Ensure `CFLAGS` are propagated to JIT compilation for 3.13+ (note this variable has no effect on
+# 3.12 and earlier)
+CFLAGS_JIT="${CFLAGS}"
+
+# In 3.14+, the JIT compiler on x86-64 Linux uses a model that conflicts with `-fPIC`, so strip it
+# from the flags. See:
+# - https://github.com/python/cpython/issues/135690
+# - https://github.com/python/cpython/pull/130097
+if [[ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_14}" && "${TARGET_TRIPLE}" == x86_64* ]]; then
+    CFLAGS_JIT="${CFLAGS_JIT//-fPIC/}"
+fi
+
+CFLAGS=$CFLAGS CPPFLAGS=$CFLAGS CFLAGS_JIT=$CFLAGS_JIT LDFLAGS=$LDFLAGS \
     ./configure ${CONFIGURE_FLAGS}
 
 # Supplement produced Makefile with our modifications.
diff --git a/cpython-unix/patch-static-remote-debug-3.14.patch b/cpython-unix/patch-static-remote-debug-3.14.patch
deleted file mode 100644
index 1c359c3d..00000000
--- a/cpython-unix/patch-static-remote-debug-3.14.patch
+++ /dev/null
@@ -1,22 +0,0 @@
-diff --git a/Python/remote_debug.h b/Python/remote_debug.h
-index 6cbf1c8deaa..ab494ea71da 100644
---- a/Python/remote_debug.h
-+++ b/Python/remote_debug.h
-@@ -131,7 +131,7 @@ _Py_RemoteDebug_FreePageCache(proc_handle_t *handle)
-     }
- }
- 
--void
-+static void
- _Py_RemoteDebug_ClearCache(proc_handle_t *handle)
- {
-     for (int i = 0; i < MAX_PAGES; i++) {
-@@ -989,7 +989,7 @@ _Py_RemoteDebug_ReadRemoteMemory(proc_handle_t *handle, uintptr_t remote_address
- #endif
- }
- 
--int
-+static int
- _Py_RemoteDebug_PagedReadRemoteMemory(proc_handle_t *handle,
-                                       uintptr_t addr,
-                                       size_t size,
diff --git a/pythonbuild/downloads.py b/pythonbuild/downloads.py
index f59afd82..3e7adc82 100644
--- a/pythonbuild/downloads.py
+++ b/pythonbuild/downloads.py
@@ -82,10 +82,10 @@
         "python_tag": "cp313",
     },
     "cpython-3.14": {
-        "url": "https://www.python.org/ftp/python/3.14.0/Python-3.14.0b2.tar.xz",
-        "size": 23579860,
-        "sha256": "7ac9e84844bbc0a5a8f1f79a37a68b3b8caf2a58b4aa5999c49227cb36e70ea6",
-        "version": "3.14.0b2",
+        "url": "https://www.python.org/ftp/python/3.14.0/Python-3.14.0b3.tar.xz",
+        "size": 23626928,
+        "sha256": "c6f48bf51f01f50d87007a445dd7afe4a4c7a87ab482570be924c1ddfd0d3682",
+        "version": "3.14.0b3",
         "licenses": ["Python-2.0", "CNRI-Python"],
         "license_file": "LICENSE.cpython.txt",
         "python_tag": "cp314",

From 97c36a3df31e7a9130f769992eb928f410605c11 Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Fri, 27 Jun 2025 22:12:26 -0500
Subject: [PATCH 118/157] Add ARM64 Windows builds for Python 3.11+ (#387)

Picking up https://github.com/indygreg/python-build-standalone/pull/93

---------

Co-authored-by: Adrian Antkowiak <adiantek@gmail.com>
---
 .github/workflows/windows.yml |   1 +
 ci-runners.yaml               |   5 ++
 ci-targets.yaml               |  18 +++++
 cpython-windows/build.py      | 129 ++++++++++++++++++++++++++--------
 src/validation.rs             |  26 +++++--
 5 files changed, 143 insertions(+), 36 deletions(-)

diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml
index a7535c68..ad8bbfe3 100644
--- a/.github/workflows/windows.yml
+++ b/.github/workflows/windows.yml
@@ -92,6 +92,7 @@ jobs:
           fi
 
   build:
+    timeout-minutes: 60
     needs:
       - generate-matrix
       - pythonbuild
diff --git a/ci-runners.yaml b/ci-runners.yaml
index e8d9f5a0..43ff9414 100644
--- a/ci-runners.yaml
+++ b/ci-runners.yaml
@@ -40,3 +40,8 @@ windows-latest:
   arch: x86_64
   platform: windows
   free: true
+
+windows-11-arm:
+  arch: aarch64
+  platform: windows
+  free: false
diff --git a/ci-targets.yaml b/ci-targets.yaml
index 70078e87..c7b4bd12 100644
--- a/ci-targets.yaml
+++ b/ci-targets.yaml
@@ -384,3 +384,21 @@ windows:
       - options:
           - freethreaded+pgo
         minimum-python-version: "3.13"
+
+  aarch64-pc-windows-msvc:
+    arch: aarch64
+    vcvars: vcvarsamd64_arm64.bat
+    python_versions:
+      # On 3.9 / 3.10, `_tkinter` is failing to be included in the build
+      # - "3.9"
+      # - "3.10"
+      - "3.11"
+      - "3.12"
+      - "3.13"
+      - "3.14"
+    build_options:
+      - pgo
+    build_options_conditional:
+      - options:
+          - freethreaded+pgo
+        minimum-python-version: "3.13"
diff --git a/cpython-windows/build.py b/cpython-windows/build.py
index 15b0a44d..0df651e1 100644
--- a/cpython-windows/build.py
+++ b/cpython-windows/build.py
@@ -370,7 +370,7 @@ def hack_props(
 
     mpdecimal_version = DOWNLOADS["mpdecimal"]["version"]
 
-    if meets_python_minimum_version(python_version, "3.14"):
+    if meets_python_minimum_version(python_version, "3.14") or arch == "arm64":
         tcltk_commit = DOWNLOADS["tk-windows-bin"]["git_commit"]
     else:
         tcltk_commit = DOWNLOADS["tk-windows-bin-8612"]["git_commit"]
@@ -464,6 +464,8 @@ def hack_props(
         suffix = b"-x64"
     elif arch == "win32":
         suffix = b""
+    elif arch == "arm64":
+        suffix = b""
     else:
         raise Exception("unhandled architecture: %s" % arch)
 
@@ -505,6 +507,7 @@ def hack_project_files(
     build_directory: str,
     python_version: str,
     zlib_entry: str,
+    arch: str,
 ):
     """Hacks Visual Studio project files to work with our build."""
 
@@ -518,6 +521,17 @@ def hack_project_files(
         zlib_entry,
     )
 
+    # `--include-tcltk` is forced off on arm64, undo that
+    # See https://github.com/python/cpython/pull/132650
+    try:
+        static_replace_in_file(
+            cpython_source_path / "PC" / "layout" / "main.py",
+            rb'if ns.arch in ("arm32", "arm64"):',
+            rb'if ns.arch == "arm32":',
+        )
+    except NoSearchStringError:
+        pass
+
     # Our SQLite directory is named weirdly. This throws off version detection
     # in the project file. Replace the parsing logic with a static string.
     sqlite3_version = DOWNLOADS["sqlite"]["actual_version"].encode("ascii")
@@ -603,14 +617,18 @@ def hack_project_files(
     # have a standalone zlib DLL, so we remove references to it. For Python
     # 3.14+, we're using tk-windows-bin 8.6.14 which includes a prebuilt zlib
     # DLL, so we skip this patch there.
-    if meets_python_minimum_version(
-        python_version, "3.12"
-    ) and meets_python_maximum_version(python_version, "3.13"):
-        static_replace_in_file(
-            pcbuild_path / "_tkinter.vcxproj",
-            rb'<_TclTkDLL Include="$(tcltkdir)\bin\$(tclZlibDllName)" />',
-            rb"",
-        )
+    # On arm64, we use the new version of tk-windows-bin for all versions.
+    if meets_python_minimum_version(python_version, "3.12") and (
+        meets_python_maximum_version(python_version, "3.13") or arch == "arm64"
+    ):
+        try:
+            static_replace_in_file(
+                pcbuild_path / "_tkinter.vcxproj",
+                rb'<_TclTkDLL Include="$(tcltkdir)\bin\$(tclZlibDllName)" />',
+                rb"",
+            )
+        except NoSearchStringError:
+            pass
 
     # We don't need to produce python_uwp.exe and its *w variant. Or the
     # python3.dll, pyshellext, or pylauncher.
@@ -730,9 +748,11 @@ def build_openssl_for_arch(
     elif arch == "amd64":
         configure = "VC-WIN64A"
         prefix = "64"
+    elif arch == "arm64":
+        configure = "VC-WIN64-ARM"
+        prefix = "arm64"
     else:
-        print("invalid architecture: %s" % arch)
-        sys.exit(1)
+        raise Exception("unhandled architecture: %s" % arch)
 
     # The official CPython OpenSSL builds hack ms/uplink.c to change the
     # ``GetModuleHandle(NULL)`` invocation to load things from _ssl.pyd
@@ -780,6 +800,12 @@ def build_openssl_for_arch(
         log("copying %s to %s" % (source, dest))
         shutil.copyfile(source, dest)
 
+    # Copy `applink.c` to the include directory.
+    source_applink = source_root / "ms" / "applink.c"
+    dest_applink = install_root / "include" / "openssl" / "applink.c"
+    log("copying %s to %s" % (source_applink, dest_applink))
+    shutil.copyfile(source_applink, dest_applink)
+
 
 def build_openssl(
     entry: str,
@@ -801,6 +827,7 @@ def build_openssl(
 
         root_32 = td / "x86"
         root_64 = td / "x64"
+        root_arm64 = td / "arm64"
 
         if arch == "x86":
             root_32.mkdir()
@@ -824,13 +851,28 @@ def build_openssl(
                 root_64,
                 jom_archive=jom_archive,
             )
+        elif arch == "arm64":
+            root_arm64.mkdir()
+            build_openssl_for_arch(
+                perl_path,
+                "arm64",
+                openssl_archive,
+                openssl_version,
+                nasm_archive,
+                root_arm64,
+                jom_archive=jom_archive,
+            )
         else:
-            raise ValueError("unhandled arch: %s" % arch)
+            raise Exception("unhandled architecture: %s" % arch)
 
         install = td / "out"
 
         if arch == "x86":
             shutil.copytree(root_32 / "install" / "32", install / "openssl" / "win32")
+        elif arch == "arm64":
+            shutil.copytree(
+                root_arm64 / "install" / "arm64", install / "openssl" / "arm64"
+            )
         else:
             shutil.copytree(root_64 / "install" / "64", install / "openssl" / "amd64")
 
@@ -901,9 +943,14 @@ def build_libffi(
         if arch == "x86":
             args.append("-x86")
             artifacts_path = ffi_source_path / "i686-pc-cygwin"
-        else:
+        elif arch == "arm64":
+            args.append("-arm64")
+            artifacts_path = ffi_source_path / "aarch64-w64-cygwin"
+        elif arch == "amd64":
             args.append("-x64")
             artifacts_path = ffi_source_path / "x86_64-w64-cygwin"
+        else:
+            raise Exception("unhandled architecture: %s" % arch)
 
         subprocess.run(args, env=env, check=True)
 
@@ -1069,8 +1116,10 @@ def find_additional_dependencies(project: pathlib.Path):
         abi_platform = "win_amd64"
     elif arch == "win32":
         abi_platform = "win32"
+    elif arch == "arm64":
+        abi_platform = "win_arm64"
     else:
-        raise ValueError("unhandled arch: %s" % arch)
+        raise Exception("unhandled architecture: %s" % arch)
 
     if freethreaded:
         abi_tag = ".cp%st-%s" % (python_majmin, abi_platform)
@@ -1171,8 +1220,8 @@ def find_additional_dependencies(project: pathlib.Path):
                 if name == "zlib":
                     name = zlib_entry
 
-                # On 3.14+, we use the latest tcl/tk version
-                if ext == "_tkinter" and python_majmin == "314":
+                # On 3.14+ and aarch64, we use the latest tcl/tk version
+                if ext == "_tkinter" and (python_majmin == "314" or arch == "arm64"):
                     name = name.replace("-8612", "")
 
                 download_entry = DOWNLOADS[name]
@@ -1258,16 +1307,18 @@ def build_cpython(
     setuptools_wheel = download_entry("setuptools", BUILD)
     pip_wheel = download_entry("pip", BUILD)
 
-    # On CPython 3.14+, we use the latest tcl/tk version which has additional runtime
-    # dependencies, so we are conservative and use the old version elsewhere.
-    if meets_python_minimum_version(python_version, "3.14"):
-        tk_bin_archive = download_entry(
-            "tk-windows-bin", BUILD, local_name="tk-windows-bin.tar.gz"
-        )
-    else:
-        tk_bin_archive = download_entry(
-            "tk-windows-bin-8612", BUILD, local_name="tk-windows-bin.tar.gz"
-        )
+    # On CPython 3.14+, we use the latest tcl/tk version which has additional
+    # runtime dependencies, so we are conservative and use the old version
+    # elsewhere. The old version isn't built for arm64, so we use the new
+    # version there too
+    tk_bin_entry = (
+        "tk-windows-bin"
+        if meets_python_minimum_version(python_version, "3.14") or arch == "arm64"
+        else "tk-windows-bin-8612"
+    )
+    tk_bin_archive = download_entry(
+        tk_bin_entry, BUILD, local_name="tk-windows-bin.tar.gz"
+    )
 
     # On CPython 3.14+, zstd is included
     if meets_python_minimum_version(python_version, "3.14"):
@@ -1297,8 +1348,11 @@ def build_cpython(
     elif arch == "x86":
         build_platform = "win32"
         build_directory = "win32"
+    elif arch == "arm64":
+        build_platform = "arm64"
+        build_directory = "arm64"
     else:
-        raise ValueError("unhandled arch: %s" % arch)
+        raise Exception("unhandled architecture: %s" % arch)
 
     tempdir_opts = (
         {"ignore_cleanup_errors": True} if sys.version_info >= (3, 12) else {}
@@ -1332,7 +1386,7 @@ def build_cpython(
 
         # We need all the OpenSSL library files in the same directory to appease
         # install rules.
-        openssl_arch = {"amd64": "amd64", "x86": "win32"}[arch]
+        openssl_arch = {"amd64": "amd64", "x86": "win32", "arm64": "arm64"}[arch]
         openssl_root = td / "openssl" / openssl_arch
         openssl_bin_path = openssl_root / "bin"
         openssl_lib_path = openssl_root / "lib"
@@ -1346,6 +1400,17 @@ def build_cpython(
             log("copying %s to %s" % (source, dest))
             shutil.copyfile(source, dest)
 
+        # Delete the tk nmake helper, it's not needed and links msvc
+        tcltk_commit: str = DOWNLOADS[tk_bin_entry]["git_commit"]
+        tcltk_path = td / ("cpython-bin-deps-%s" % tcltk_commit)
+        (
+            tcltk_path
+            / build_directory
+            / "lib"
+            / "nmake"
+            / "x86_64-w64-mingw32-nmakehlp.exe"
+        ).unlink()
+
         cpython_source_path = td / ("Python-%s" % python_version)
         pcbuild_path = cpython_source_path / "PCbuild"
 
@@ -1368,6 +1433,7 @@ def build_cpython(
             build_directory,
             python_version=python_version,
             zlib_entry=zlib_entry,
+            arch=arch,
         )
 
         if pgo:
@@ -1790,9 +1856,14 @@ def main() -> None:
         if os.environ.get("Platform") == "x86":
             target_triple = "i686-pc-windows-msvc"
             arch = "x86"
-        else:
+        elif os.environ.get("Platform") == "arm64":
+            target_triple = "aarch64-pc-windows-msvc"
+            arch = "arm64"
+        elif os.environ.get("Platform") == "x64":
             target_triple = "x86_64-pc-windows-msvc"
             arch = "amd64"
+        else:
+            raise Exception("unhandled architecture: %s" % os.environ.get("Platform"))
 
         # TODO need better dependency checking.
 
diff --git a/src/validation.rs b/src/validation.rs
index 19aace00..9084754b 100644
--- a/src/validation.rs
+++ b/src/validation.rs
@@ -18,7 +18,7 @@ use {
             macho::{LoadCommandVariant, MachHeader, Nlist},
             pe::{ImageNtHeaders, PeFile, PeFile32, PeFile64},
         },
-        Endianness, FileKind, Object, SectionIndex, SymbolScope,
+        Architecture, Endianness, FileKind, Object, SectionIndex, SymbolScope,
     },
     once_cell::sync::Lazy,
     std::{
@@ -33,6 +33,7 @@ use {
 const RECOGNIZED_TRIPLES: &[&str] = &[
     "aarch64-apple-darwin",
     "aarch64-apple-ios",
+    "aarch64-pc-windows-msvc",
     "aarch64-unknown-linux-gnu",
     "armv7-unknown-linux-gnueabi",
     "armv7-unknown-linux-gnueabihf",
@@ -117,11 +118,13 @@ const PE_ALLOWED_LIBRARIES: &[&str] = &[
     "libcrypto-1_1.dll",
     "libcrypto-1_1-x64.dll",
     "libcrypto-3.dll",
+    "libcrypto-3-arm64.dll",
     "libcrypto-3-x64.dll",
     "libffi-8.dll",
     "libssl-1_1.dll",
     "libssl-1_1-x64.dll",
     "libssl-3.dll",
+    "libssl-3-arm64.dll",
     "libssl-3-x64.dll",
     "python3.dll",
     "python39.dll",
@@ -137,8 +140,14 @@ const PE_ALLOWED_LIBRARIES: &[&str] = &[
     "tk86t.dll",
 ];
 
-// CPython 3.14 uses tcl/tk 8.6.14+ which includes a bundled zlib and dynamically links to msvcrt.
-const PE_ALLOWED_LIBRARIES_314: &[&str] = &["msvcrt.dll", "zlib1.dll"];
+// CPython 3.14 and ARM64 use a newer version of tcl/tk (8.6.14+) which includes a bundled zlib that
+// dynamically links some system libraries
+const PE_ALLOWED_LIBRARIES_314: &[&str] = &[
+    "zlib1.dll",
+    "api-ms-win-crt-private-l1-1-0.dll", // zlib loads this library on arm64, 3.14+
+    "msvcrt.dll",                        // zlib loads this library
+];
+const PE_ALLOWED_LIBRARIES_ARM64: &[&str] = &["msvcrt.dll", "zlib1.dll"];
 
 static GLIBC_MAX_VERSION_BY_TRIPLE: Lazy<HashMap<&'static str, version_compare::Version<'static>>> =
     Lazy::new(|| {
@@ -496,6 +505,7 @@ static PLATFORM_TAG_BY_TRIPLE: Lazy<HashMap<&'static str, &'static str>> = Lazy:
     [
         ("aarch64-apple-darwin", "macosx-11.0-arm64"),
         ("aarch64-apple-ios", "iOS-aarch64"),
+        ("aarch64-pc-windows-msvc", "win-arm64"),
         ("aarch64-unknown-linux-gnu", "linux-aarch64"),
         ("armv7-unknown-linux-gnueabi", "linux-arm"),
         ("armv7-unknown-linux-gnueabihf", "linux-arm"),
@@ -1375,15 +1385,17 @@ fn validate_pe<'data, Pe: ImageNtHeaders>(
             let lib = String::from_utf8(lib.to_vec())?;
 
             match python_major_minor {
-                "3.9" | "3.10" | "3.11" | "3.12" | "3.13" => {}
+                "3.11" | "3.12" | "3.13" if pe.architecture() == Architecture::Aarch64 => {
+                    if PE_ALLOWED_LIBRARIES_ARM64.contains(&lib.as_str()) {
+                        continue;
+                    }
+                }
                 "3.14" => {
                     if PE_ALLOWED_LIBRARIES_314.contains(&lib.as_str()) {
                         continue;
                     }
                 }
-                _ => {
-                    panic!("unhandled Python version: {}", python_major_minor);
-                }
+                _ => {}
             }
 
             if !PE_ALLOWED_LIBRARIES.contains(&lib.as_str()) {

From 240b6392a544070b5e0ab3c4b8c5c620a880186e Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Sat, 28 Jun 2025 09:33:48 -0500
Subject: [PATCH 119/157] Gate `x86_64-w64-mingw32-nmakehlp.exe` removal to
 builds where it is present (#671)

Fixes
https://github.com/astral-sh/python-build-standalone/actions/runs/15939854940/job/44966313482
---
 cpython-windows/build.py | 19 ++++++++++---------
 1 file changed, 10 insertions(+), 9 deletions(-)

diff --git a/cpython-windows/build.py b/cpython-windows/build.py
index 0df651e1..3b0c3b41 100644
--- a/cpython-windows/build.py
+++ b/cpython-windows/build.py
@@ -1401,15 +1401,16 @@ def build_cpython(
             shutil.copyfile(source, dest)
 
         # Delete the tk nmake helper, it's not needed and links msvc
-        tcltk_commit: str = DOWNLOADS[tk_bin_entry]["git_commit"]
-        tcltk_path = td / ("cpython-bin-deps-%s" % tcltk_commit)
-        (
-            tcltk_path
-            / build_directory
-            / "lib"
-            / "nmake"
-            / "x86_64-w64-mingw32-nmakehlp.exe"
-        ).unlink()
+        if tk_bin_entry == "tk-windows-bin":
+            tcltk_commit: str = DOWNLOADS[tk_bin_entry]["git_commit"]
+            tcltk_path = td / ("cpython-bin-deps-%s" % tcltk_commit)
+            (
+                tcltk_path
+                / build_directory
+                / "lib"
+                / "nmake"
+                / "x86_64-w64-mingw32-nmakehlp.exe"
+            ).unlink()
 
         cpython_source_path = td / ("Python-%s" % python_version)
         pcbuild_path = cpython_source_path / "PCbuild"

From 526189db29aac2ab097fbbb0b28b589a21247c2d Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Sat, 28 Jun 2025 11:22:07 -0500
Subject: [PATCH 120/157] Generate the Docker CI matrix (#672)

I think this will be a useful precursor to
https://github.com/astral-sh/python-build-standalone/pull/670
---
 .github/workflows/linux.yml   |  43 ++++++------
 .github/workflows/macos.yml   |   8 ++-
 .github/workflows/windows.yml |   8 ++-
 ci-matrix.py                  | 126 +++++++++++++++++++++++++---------
 4 files changed, 126 insertions(+), 59 deletions(-)

diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml
index 3b70b5f8..6f73a952 100644
--- a/.github/workflows/linux.yml
+++ b/.github/workflows/linux.yml
@@ -54,14 +54,9 @@ jobs:
       - generate-matrix
     strategy:
       fail-fast: false
-      matrix:
-        image:
-          - build
-          - build.cross
-          - build.cross-riscv64
-          - gcc
-    name: ${{ matrix.image }}
-    runs-on: depot-ubuntu-22.04
+      matrix: ${{ fromJson(needs.generate-matrix.outputs.docker-build-matrix) }}
+    name: ${{ matrix.name }}
+    runs-on: ${{ matrix.runner }}
     permissions:
       packages: write
     steps:
@@ -95,37 +90,38 @@ jobs:
         uses: docker/build-push-action@v5
         with:
           context: .
-          file: build/${{ matrix.image }}.Dockerfile
+          file: build/${{ matrix.name }}.Dockerfile
           labels: org.opencontainers.image.source=https://github.com/${{ env.REPO_NAME }}
           # Cache from/to the current branch of the current repo as the primary cache key.
           # Cache from the default branch of the current repo so branches can have cache hits.
           # Cache from the default branch of the canonical repo so forks can have cache hits.
           # Ignore errors on cache writes so CI of forks works without a valid GHCR config.
           cache-from: |
-            type=registry,ref=ghcr.io/${{ env.REPO_NAME }}:${{ matrix.image }}-${{ env.GIT_REF_NAME }}
-            type=registry,ref=ghcr.io/${{ env.REPO_NAME }}:${{ matrix.image }}-main
-            type=registry,ref=ghcr.io/astral-sh/python-build-standalone:${{ matrix.image }}-main
+            type=registry,ref=ghcr.io/${{ env.REPO_NAME }}:${{ matrix.name }}-${{ env.GIT_REF_NAME }}
+            type=registry,ref=ghcr.io/${{ env.REPO_NAME }}:${{ matrix.name }}-main
+            type=registry,ref=ghcr.io/astral-sh/python-build-standalone:${{ matrix.name }}-main
           cache-to: |
-            type=registry,ref=ghcr.io/${{ env.REPO_NAME }}:${{ matrix.image }}-${{ env.GIT_REF_NAME }},ignore-error=true
+            type=registry,ref=ghcr.io/${{ env.REPO_NAME }}:${{ matrix.name }}-${{ env.GIT_REF_NAME }},ignore-error=true
           outputs: |
-            type=docker,dest=build/image-${{ matrix.image }}.tar
+            type=docker,dest=build/image-${{ matrix.name }}.tar
 
       - name: Compress Image
         run: |
-          echo ${{ steps.build-image.outputs.imageid }} > build/image-${{ matrix.image }}
+          echo ${{ steps.build-image.outputs.imageid }} > build/image-${{ matrix.name }}
           zstd -v -T0 -6 --rm build/image-*.tar
 
       - name: Upload Docker Image
         uses: actions/upload-artifact@v4
         with:
-          name: image-${{ matrix.image }}
+          name: image-${{ matrix.name }}
           path: build/image-*
 
   generate-matrix:
     runs-on: ubuntu-latest
     outputs:
-      matrix-0: ${{ steps.set-matrix.outputs.matrix-0 }}
-      matrix-1: ${{ steps.set-matrix.outputs.matrix-1 }}
+      python-build-matrix-0: ${{ steps.set-matrix.outputs.python-build-matrix-0 }}
+      python-build-matrix-1: ${{ steps.set-matrix.outputs.python-build-matrix-1 }}
+      docker-build-matrix: ${{ steps.set-matrix.outputs.docker-build-matrix }}
       any_builds: ${{ steps.set-matrix.outputs.any_builds }}
       pythonbuild_changed: ${{ steps.check-pythonbuild.outputs.changed }}
     steps:
@@ -152,13 +148,14 @@ jobs:
             --max-shards 2 \
             > matrix.json
 
-          echo "matrix-0=$(jq -c '.["0"]' matrix.json)" >> $GITHUB_OUTPUT
-          echo "matrix-1=$(jq -c '.["1"]' matrix.json)" >> $GITHUB_OUTPUT
+          echo "python-build-matrix-0=$(jq -c '."python-build"["0"]' matrix.json)" >> $GITHUB_OUTPUT
+          echo "python-build-matrix-1=$(jq -c '."python-build"["1"]' matrix.json)" >> $GITHUB_OUTPUT
+          echo "docker-build-matrix=$(jq -c '."docker-build"' matrix.json)" >> $GITHUB_OUTPUT
 
           # Display the matrix for debugging too
           cat matrix.json | jq
 
-          if jq -e '.["0"].include | length > 0' matrix.json > /dev/null; then
+          if jq -e '."python-build"["0"].include | length > 0' matrix.json > /dev/null; then
             # Build matrix has entries
             echo "any_builds=true" >> $GITHUB_OUTPUT
           else
@@ -189,7 +186,7 @@ jobs:
       attestations: write
     runs-on: ${{ matrix.runner }}
     strategy:
-      matrix: ${{ fromJson(needs.generate-matrix.outputs.matrix-0) }}
+      matrix: ${{ fromJson(needs.generate-matrix.outputs.python-build-matrix-0) }}
       fail-fast: false
     name: ${{ matrix.target_triple }} / ${{ matrix.python }} / ${{ matrix.build_options }}
     steps:
@@ -289,7 +286,7 @@ jobs:
       attestations: write
     runs-on: ${{ matrix.runner }}
     strategy:
-      matrix: ${{ fromJson(needs.generate-matrix.outputs.matrix-1) }}
+      matrix: ${{ fromJson(needs.generate-matrix.outputs.python-build-matrix-1) }}
       fail-fast: false
     name: ${{ matrix.target_triple }} / ${{ matrix.python }} / ${{ matrix.build_options }}
     steps:
diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml
index af9a80f0..918323d4 100644
--- a/.github/workflows/macos.yml
+++ b/.github/workflows/macos.yml
@@ -67,11 +67,15 @@ jobs:
       - name: Generate build matrix
         id: set-matrix
         run: |
-          uv run ci-matrix.py --platform darwin --labels '${{ steps.get-labels.outputs.labels }}' > matrix.json && echo "matrix=$(cat matrix.json)" >> $GITHUB_OUTPUT
+          uv run ci-matrix.py --platform darwin --labels '${{ steps.get-labels.outputs.labels }}' > matrix.json
+          
+          # Extract python-build matrix
+          echo "matrix=$(jq -c '."python-build"' matrix.json)" >> $GITHUB_OUTPUT
+          
           # Display the matrix for debugging too
           cat matrix.json | jq
 
-          if jq -e '.include | length > 0' matrix.json > /dev/null; then
+          if jq -e '."python-build".include | length > 0' matrix.json > /dev/null; then
             # Build matrix has entries
             echo "any_builds=true" >> $GITHUB_OUTPUT
           else
diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml
index ad8bbfe3..0e03dbaf 100644
--- a/.github/workflows/windows.yml
+++ b/.github/workflows/windows.yml
@@ -67,11 +67,15 @@ jobs:
       - name: Generate build matrix
         id: set-matrix
         run: |
-          uv run ci-matrix.py --platform windows --labels '${{ steps.get-labels.outputs.labels }}' > matrix.json && echo "matrix=$(cat matrix.json)" >> $GITHUB_OUTPUT
+          uv run ci-matrix.py --platform windows --labels '${{ steps.get-labels.outputs.labels }}' > matrix.json
+          
+          # Extract python-build matrix
+          echo "matrix=$(jq -c '."python-build"' matrix.json)" >> $GITHUB_OUTPUT
+          
           # Display the matrix for debugging too
           cat matrix.json | jq
 
-          if jq -e '.include | length > 0' matrix.json > /dev/null; then
+          if jq -e '."python-build".include | length > 0' matrix.json > /dev/null; then
             # Build matrix has entries
             echo "any_builds=true" >> $GITHUB_OUTPUT
           else
diff --git a/ci-matrix.py b/ci-matrix.py
index c9bcccee..8543a582 100644
--- a/ci-matrix.py
+++ b/ci-matrix.py
@@ -19,6 +19,14 @@
 CI_EXTRA_SKIP_LABELS = ["documentation"]
 CI_MATRIX_SIZE_LIMIT = 256  # The maximum size of a matrix in GitHub Actions
 
+# Docker images for building toolchains and dependencies
+DOCKER_BUILD_IMAGES = [
+    {"name": "build", "arch": "x86_64"},
+    {"name": "build.cross", "arch": "x86_64"},
+    {"name": "build.cross-riscv64", "arch": "x86_64"},
+    {"name": "gcc", "arch": "x86_64"},
+]
+
 
 def meets_conditional_version(version: str, min_version: str) -> bool:
     return Version(version) >= Version(min_version)
@@ -89,12 +97,36 @@ def should_include_entry(entry: dict[str, str], filters: dict[str, set[str]]) ->
     return True
 
 
-def generate_matrix_entries(
+def generate_docker_matrix_entries(
+    runners: dict[str, Any],
+    platform_filter: Optional[str] = None,
+) -> list[dict[str, str]]:
+    """Generate matrix entries for docker image builds."""
+    if platform_filter and platform_filter != "linux":
+        return []
+
+    matrix_entries = []
+    for image in DOCKER_BUILD_IMAGES:
+        # Find appropriate runner for Linux platform with the specified architecture
+        runner = find_runner(runners, "linux", image["arch"])
+
+        entry = {
+            "name": image["name"],
+            "arch": image["arch"],
+            "runner": runner,
+        }
+        matrix_entries.append(entry)
+
+    return matrix_entries
+
+
+def generate_python_build_matrix_entries(
     config: dict[str, Any],
     runners: dict[str, Any],
     platform_filter: Optional[str] = None,
     label_filters: Optional[dict[str, set[str]]] = None,
 ) -> list[dict[str, str]]:
+    """Generate matrix entries for python builds."""
     matrix_entries = []
 
     for platform, platform_config in config.items():
@@ -102,13 +134,13 @@ def generate_matrix_entries(
             continue
 
         for target_triple, target_config in platform_config.items():
-            add_matrix_entries_for_config(
+            add_python_build_entries_for_config(
                 matrix_entries,
                 target_triple,
                 target_config,
                 platform,
                 runners,
-                label_filters.get("directives", set()),
+                label_filters.get("directives", set()) if label_filters else set(),
             )
 
     # Apply label filters if present
@@ -144,7 +176,7 @@ def find_runner(runners: dict[str, Any], platform: str, arch: str) -> str:
     raise RuntimeError(f"No runner found for platform {platform!r} and arch {arch!r}")
 
 
-def add_matrix_entries_for_config(
+def add_python_build_entries_for_config(
     matrix_entries: list[dict[str, str]],
     target_triple: str,
     config: dict[str, Any],
@@ -152,6 +184,7 @@ def add_matrix_entries_for_config(
     runners: dict[str, Any],
     directives: set[str],
 ) -> None:
+    """Add python build matrix entries for a specific target configuration."""
     python_versions = config["python_versions"]
     build_options = config["build_options"]
     arch = config["arch"]
@@ -233,6 +266,12 @@ def parse_args() -> argparse.Namespace:
         action="store_true",
         help="If only free runners should be used.",
     )
+    parser.add_argument(
+        "--matrix-type",
+        choices=["python-build", "docker-build", "all"],
+        default="all",
+        help="Which matrix types to generate (default: all)",
+    )
     return parser.parse_args()
 
 
@@ -254,36 +293,59 @@ def main() -> None:
             if runner_config.get("free")
         }
 
-    entries = generate_matrix_entries(
-        config,
-        runners,
-        args.platform,
-        labels,
-    )
-
-    if args.max_shards:
-        matrix = {}
-        shards = (len(entries) // CI_MATRIX_SIZE_LIMIT) + 1
-        if shards > args.max_shards:
-            print(
-                f"error: matrix of size {len(entries)} requires {shards} shards, but the maximum is {args.max_shards}; consider increasing `--max-shards`",
-                file=sys.stderr,
-            )
-            sys.exit(1)
-        for shard in range(args.max_shards):
-            shard_entries = entries[
-                shard * CI_MATRIX_SIZE_LIMIT : (shard + 1) * CI_MATRIX_SIZE_LIMIT
-            ]
-            matrix[str(shard)] = {"include": shard_entries}
-    else:
-        if len(entries) > CI_MATRIX_SIZE_LIMIT:
-            print(
-                f"warning: matrix of size {len(entries)} exceeds limit of {CI_MATRIX_SIZE_LIMIT} but sharding is not enabled; consider setting `--max-shards`",
-                file=sys.stderr,
+    result = {}
+
+    # Generate python-build matrix if requested
+    python_entries = []
+    if args.matrix_type in ["python-build", "all"]:
+        python_entries = generate_python_build_matrix_entries(
+            config,
+            runners,
+            args.platform,
+            labels,
+        )
+
+        if args.max_shards:
+            python_build_matrix = {}
+            shards = (len(python_entries) // CI_MATRIX_SIZE_LIMIT) + 1
+            if shards > args.max_shards:
+                print(
+                    f"error: python-build matrix of size {len(python_entries)} requires {shards} shards, but the maximum is {args.max_shards}; consider increasing `--max-shards`",
+                    file=sys.stderr,
+                )
+                sys.exit(1)
+            for shard in range(args.max_shards):
+                shard_entries = python_entries[
+                    shard * CI_MATRIX_SIZE_LIMIT : (shard + 1) * CI_MATRIX_SIZE_LIMIT
+                ]
+                python_build_matrix[str(shard)] = {"include": shard_entries}
+            result["python-build"] = python_build_matrix
+        else:
+            if len(python_entries) > CI_MATRIX_SIZE_LIMIT:
+                print(
+                    f"warning: python-build matrix of size {len(python_entries)} exceeds limit of {CI_MATRIX_SIZE_LIMIT} but sharding is not enabled; consider setting `--max-shards`",
+                    file=sys.stderr,
+                )
+            result["python-build"] = {"include": python_entries}
+
+    # Generate docker-build matrix if requested
+    # Only include docker builds if there are Linux python builds
+    if args.matrix_type in ["docker-build", "all"]:
+        # Check if we have any Linux python builds
+        has_linux_builds = any(
+            entry.get("platform") == "linux" for entry in python_entries
+        )
+
+        # If no platform filter or explicitly requesting docker-build only, include docker builds
+        # Otherwise, only include if there are Linux python builds
+        if args.matrix_type == "docker-build" or has_linux_builds:
+            docker_entries = generate_docker_matrix_entries(
+                runners,
+                args.platform,
             )
-        matrix = {"include": entries}
+            result["docker-build"] = {"include": docker_entries}
 
-    print(json.dumps(matrix))
+    print(json.dumps(result))
 
 
 if __name__ == "__main__":

From 449d3e7a2b03a311884b40ed90f98bfc90bee01e Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Sat, 28 Jun 2025 11:53:04 -0500
Subject: [PATCH 121/157] Generate the matrix for building the `pythonbuild`
 crate (#673)

As in #672 this seems helpful for #670
---
 .github/workflows/linux.yml   |  49 ++++++++--------
 .github/workflows/macos.yml   |  44 ++++++++-------
 .github/workflows/windows.yml |  44 ++++++++-------
 ci-matrix.py                  | 102 +++++++++++++++++++++++++++++-----
 4 files changed, 162 insertions(+), 77 deletions(-)

diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml
index 6f73a952..8ae87e76 100644
--- a/.github/workflows/linux.yml
+++ b/.github/workflows/linux.yml
@@ -13,11 +13,14 @@ env:
   FORCE_COLOR: 1
 
 jobs:
-  pythonbuild:
-    if: ${{ needs.generate-matrix.outputs.pythonbuild_changed == 'true' || needs.generate-matrix.outputs.any_builds == 'true' || github.ref == 'refs/heads/main' }}
+  crate-build:
     needs:
       - generate-matrix
-    runs-on: depot-ubuntu-22.04
+    runs-on: ${{ matrix.runner }}
+    strategy:
+      matrix: ${{ fromJson(needs.generate-matrix.outputs.crate-build-matrix) }}
+      fail-fast: false
+    name: crate / ${{ matrix.arch }}
     steps:
       - name: Install System Dependencies
         run: |
@@ -45,7 +48,7 @@ jobs:
       - name: Upload pythonbuild Executable
         uses: actions/upload-artifact@v4
         with:
-          name: pythonbuild
+          name: ${{ matrix.crate_artifact_name }}
           path: target/release/pythonbuild
 
   image:
@@ -55,7 +58,7 @@ jobs:
     strategy:
       fail-fast: false
       matrix: ${{ fromJson(needs.generate-matrix.outputs.docker-build-matrix) }}
-    name: ${{ matrix.name }}
+    name: image / ${{ matrix.name }}
     runs-on: ${{ matrix.runner }}
     permissions:
       packages: write
@@ -122,8 +125,8 @@ jobs:
       python-build-matrix-0: ${{ steps.set-matrix.outputs.python-build-matrix-0 }}
       python-build-matrix-1: ${{ steps.set-matrix.outputs.python-build-matrix-1 }}
       docker-build-matrix: ${{ steps.set-matrix.outputs.docker-build-matrix }}
+      crate-build-matrix: ${{ steps.set-matrix.outputs.crate-build-matrix }}
       any_builds: ${{ steps.set-matrix.outputs.any_builds }}
-      pythonbuild_changed: ${{ steps.check-pythonbuild.outputs.changed }}
     steps:
       - uses: actions/checkout@v4
         with:
@@ -139,6 +142,18 @@ jobs:
           LABELS=$(echo '${{ toJson(github.event.pull_request.labels.*.name) }}' | jq -r 'join(",")')
           echo "labels=$LABELS" >> $GITHUB_OUTPUT
 
+      - name: Check if the `pythonbuild` crate changed
+        id: check-pythonbuild
+        env:
+          BASE_REF: ${{ github.event.pull_request.base.ref || 'main' }}
+        run: |
+          merge_base=$(git merge-base HEAD "origin/${BASE_REF}")
+          if git diff --quiet "${merge_base}...HEAD" -- ':src/*.rs'; then
+              echo "changed=false" >> "$GITHUB_OUTPUT"
+          else
+              echo "changed=true" >> "$GITHUB_OUTPUT"
+          fi
+
       - name: Generate build matrix
         id: set-matrix
         run: |
@@ -146,11 +161,13 @@ jobs:
             --platform linux \
             --labels '${{ steps.get-labels.outputs.labels }}' \
             --max-shards 2 \
+            ${{ (steps.check-pythonbuild.outputs.changed == 'true' || github.ref == 'refs/heads/main') && '--force-crate-build' || '' }} \
             > matrix.json
 
           echo "python-build-matrix-0=$(jq -c '."python-build"["0"]' matrix.json)" >> $GITHUB_OUTPUT
           echo "python-build-matrix-1=$(jq -c '."python-build"["1"]' matrix.json)" >> $GITHUB_OUTPUT
           echo "docker-build-matrix=$(jq -c '."docker-build"' matrix.json)" >> $GITHUB_OUTPUT
+          echo "crate-build-matrix=$(jq -c '."crate-build"' matrix.json)" >> $GITHUB_OUTPUT
 
           # Display the matrix for debugging too
           cat matrix.json | jq
@@ -163,22 +180,10 @@ jobs:
             echo "any_builds=false" >> $GITHUB_OUTPUT
           fi
 
-      - name: Check if the `pythonbuild` crate changed
-        id: check-pythonbuild
-        env:
-          BASE_REF: ${{ github.event.pull_request.base.ref || 'main' }}
-        run: |
-          merge_base=$(git merge-base HEAD "origin/${BASE_REF}")
-          if git diff --quiet "${merge_base}...HEAD" -- ':src/*.rs'; then
-              echo "changed=false" >> "$GITHUB_OUTPUT"
-          else
-              echo "changed=true" >> "$GITHUB_OUTPUT"
-          fi
-
   build-0:
     needs:
       - generate-matrix
-      - pythonbuild
+      - crate-build
       - image
     # Permissions used for actions/attest-build-provenance
     permissions:
@@ -202,7 +207,7 @@ jobs:
       - name: Download pythonbuild
         uses: actions/download-artifact@v4
         with:
-          name: pythonbuild
+          name: ${{ matrix.crate_artifact_name }}
           path: build
 
       - name: Download images
@@ -278,7 +283,7 @@ jobs:
   build-1:
     needs:
       - generate-matrix
-      - pythonbuild
+      - crate-build
       - image
     # Permissions used for actions/attest-build-provenance
     permissions:
@@ -302,7 +307,7 @@ jobs:
       - name: Download pythonbuild
         uses: actions/download-artifact@v4
         with:
-          name: pythonbuild
+          name: ${{ matrix.crate_artifact_name }}
           path: build
 
       - name: Download images
diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml
index 918323d4..1199b398 100644
--- a/.github/workflows/macos.yml
+++ b/.github/workflows/macos.yml
@@ -13,11 +13,14 @@ env:
   FORCE_COLOR: 1
 
 jobs:
-  pythonbuild:
-    if: ${{ needs.generate-matrix.outputs.pythonbuild_changed == 'true' || needs.generate-matrix.outputs.any_builds == 'true' || github.ref == 'refs/heads/main' }}
+  crate-build:
     needs:
       - generate-matrix
-    runs-on: depot-macos-latest
+    runs-on: ${{ matrix.runner }}
+    strategy:
+      matrix: ${{ fromJson(needs.generate-matrix.outputs.crate-build-matrix) }}
+      fail-fast: false
+    name: crate / ${{ matrix.arch }}
     steps:
       - uses: actions/checkout@v4
 
@@ -40,15 +43,15 @@ jobs:
       - name: Upload pythonbuild Executable
         uses: actions/upload-artifact@v4
         with:
-          name: pythonbuild
+          name: ${{ matrix.crate_artifact_name }}
           path: target/release/pythonbuild
 
   generate-matrix:
     runs-on: ubuntu-latest
     outputs:
       matrix: ${{ steps.set-matrix.outputs.matrix }}
+      crate-build-matrix: ${{ steps.set-matrix.outputs.crate-build-matrix }}
       any_builds: ${{ steps.set-matrix.outputs.any_builds }}
-      pythonbuild_changed: ${{ steps.check-pythonbuild.outputs.changed }}
     steps:
       - uses: actions/checkout@v4
         with:
@@ -64,13 +67,26 @@ jobs:
           LABELS=$(echo '${{ toJson(github.event.pull_request.labels.*.name) }}' | jq -r 'join(",")')
           echo "labels=$LABELS" >> $GITHUB_OUTPUT
 
+      - name: Check if the `pythonbuild` crate changed
+        id: check-pythonbuild
+        env:
+          BASE_REF: ${{ github.event.pull_request.base.ref || 'main' }}
+        run: |
+          merge_base=$(git merge-base HEAD "origin/${BASE_REF}")
+          if git diff --quiet "${merge_base}...HEAD" -- ':src/*.rs'; then
+              echo "changed=false" >> "$GITHUB_OUTPUT"
+          else
+              echo "changed=true" >> "$GITHUB_OUTPUT"
+          fi
+
       - name: Generate build matrix
         id: set-matrix
         run: |
-          uv run ci-matrix.py --platform darwin --labels '${{ steps.get-labels.outputs.labels }}' > matrix.json
+          uv run ci-matrix.py --platform darwin --labels '${{ steps.get-labels.outputs.labels }}' ${{ (steps.check-pythonbuild.outputs.changed == 'true' || github.ref == 'refs/heads/main') && '--force-crate-build' || '' }} > matrix.json
           
           # Extract python-build matrix
           echo "matrix=$(jq -c '."python-build"' matrix.json)" >> $GITHUB_OUTPUT
+          echo "crate-build-matrix=$(jq -c '."crate-build"' matrix.json)" >> $GITHUB_OUTPUT
           
           # Display the matrix for debugging too
           cat matrix.json | jq
@@ -83,22 +99,10 @@ jobs:
             echo "any_builds=false" >> $GITHUB_OUTPUT
           fi
 
-      - name: Check if the `pythonbuild` crate changed
-        id: check-pythonbuild
-        env:
-          BASE_REF: ${{ github.event.pull_request.base.ref || 'main' }}
-        run: |
-          merge_base=$(git merge-base HEAD "origin/${BASE_REF}")
-          if git diff --quiet "${merge_base}...HEAD" -- ':src/*.rs'; then
-              echo "changed=false" >> "$GITHUB_OUTPUT"
-          else
-              echo "changed=true" >> "$GITHUB_OUTPUT"
-          fi
-
   build:
     needs:
       - generate-matrix
-      - pythonbuild
+      - crate-build
     # Permissions used for actions/attest-build-provenance
     permissions:
       id-token: write
@@ -121,7 +125,7 @@ jobs:
       - name: Download pythonbuild
         uses: actions/download-artifact@v4
         with:
-          name: pythonbuild
+          name: ${{ matrix.crate_artifact_name }}
           path: build
 
       - name: Build
diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml
index 0e03dbaf..e285fac3 100644
--- a/.github/workflows/windows.yml
+++ b/.github/workflows/windows.yml
@@ -13,11 +13,14 @@ env:
   FORCE_COLOR: 1
 
 jobs:
-  pythonbuild:
-    if: ${{ needs.generate-matrix.outputs.pythonbuild_changed == 'true' || needs.generate-matrix.outputs.any_builds == 'true' || github.ref == 'refs/heads/main' }}
+  crate-build:
     needs:
       - generate-matrix
-    runs-on: 'windows-2022'
+    runs-on: ${{ matrix.runner }}
+    strategy:
+      matrix: ${{ fromJson(needs.generate-matrix.outputs.crate-build-matrix) }}
+      fail-fast: false
+    name: crate / ${{ matrix.arch }}
     steps:
       - uses: actions/checkout@v4
 
@@ -40,15 +43,15 @@ jobs:
       - name: Upload executable
         uses: actions/upload-artifact@v4
         with:
-          name: pythonbuild
+          name: ${{ matrix.crate_artifact_name }}
           path: target/release/pythonbuild.exe
 
   generate-matrix:
     runs-on: ubuntu-latest
     outputs:
       matrix: ${{ steps.set-matrix.outputs.matrix }}
+      crate-build-matrix: ${{ steps.set-matrix.outputs.crate-build-matrix }}
       any_builds: ${{ steps.set-matrix.outputs.any_builds }}
-      pythonbuild_changed: ${{ steps.check-pythonbuild.outputs.changed }}
     steps:
       - uses: actions/checkout@v4
         with:
@@ -64,13 +67,26 @@ jobs:
           LABELS=$(echo '${{ toJson(github.event.pull_request.labels.*.name) }}' | jq -r 'join(",")')
           echo "labels=$LABELS" >> $GITHUB_OUTPUT
 
+      - name: Check if the `pythonbuild` crate changed
+        id: check-pythonbuild
+        env:
+          BASE_REF: ${{ github.event.pull_request.base.ref || 'main' }}
+        run: |
+          merge_base=$(git merge-base HEAD "origin/${BASE_REF}")
+          if git diff --quiet "${merge_base}...HEAD" -- ':src/*.rs'; then
+              echo "changed=false" >> "$GITHUB_OUTPUT"
+          else
+              echo "changed=true" >> "$GITHUB_OUTPUT"
+          fi
+
       - name: Generate build matrix
         id: set-matrix
         run: |
-          uv run ci-matrix.py --platform windows --labels '${{ steps.get-labels.outputs.labels }}' > matrix.json
+          uv run ci-matrix.py --platform windows --labels '${{ steps.get-labels.outputs.labels }}' ${{ (steps.check-pythonbuild.outputs.changed == 'true' || github.ref == 'refs/heads/main') && '--force-crate-build' || '' }} > matrix.json
           
           # Extract python-build matrix
           echo "matrix=$(jq -c '."python-build"' matrix.json)" >> $GITHUB_OUTPUT
+          echo "crate-build-matrix=$(jq -c '."crate-build"' matrix.json)" >> $GITHUB_OUTPUT
           
           # Display the matrix for debugging too
           cat matrix.json | jq
@@ -83,23 +99,11 @@ jobs:
             echo "any_builds=false" >> $GITHUB_OUTPUT
           fi
 
-      - name: Check if the `pythonbuild` crate changed
-        id: check-pythonbuild
-        env:
-          BASE_REF: ${{ github.event.pull_request.base.ref || 'main' }}
-        run: |
-          merge_base=$(git merge-base HEAD "origin/${BASE_REF}")
-          if git diff --quiet "${merge_base}...HEAD" -- ':src/*.rs'; then
-              echo "changed=false" >> "$GITHUB_OUTPUT"
-          else
-              echo "changed=true" >> "$GITHUB_OUTPUT"
-          fi
-
   build:
     timeout-minutes: 60
     needs:
       - generate-matrix
-      - pythonbuild
+      - crate-build
     # Permissions used for actions/attest-build-provenance
     permissions:
       id-token: write
@@ -127,7 +131,7 @@ jobs:
       - name: Download pythonbuild Executable
         uses: actions/download-artifact@v4
         with:
-          name: pythonbuild
+          name: ${{ matrix.crate_artifact_name }}
 
       # We need to do this before we activate the VC++ environment or else binary packages
       # don't get compiled properly.
diff --git a/ci-matrix.py b/ci-matrix.py
index 8543a582..96059a96 100644
--- a/ci-matrix.py
+++ b/ci-matrix.py
@@ -19,6 +19,7 @@
 CI_EXTRA_SKIP_LABELS = ["documentation"]
 CI_MATRIX_SIZE_LIMIT = 256  # The maximum size of a matrix in GitHub Actions
 
+
 # Docker images for building toolchains and dependencies
 DOCKER_BUILD_IMAGES = [
     {"name": "build", "arch": "x86_64"},
@@ -28,6 +29,10 @@
 ]
 
 
+def crate_artifact_name(platform: str, arch: str) -> str:
+    return f"crate-{platform}-{arch}"
+
+
 def meets_conditional_version(version: str, min_version: str) -> bool:
     return Version(version) >= Version(min_version)
 
@@ -108,7 +113,7 @@ def generate_docker_matrix_entries(
     matrix_entries = []
     for image in DOCKER_BUILD_IMAGES:
         # Find appropriate runner for Linux platform with the specified architecture
-        runner = find_runner(runners, "linux", image["arch"])
+        runner = find_runner(runners, "linux", image["arch"], False)
 
         entry = {
             "name": image["name"],
@@ -120,6 +125,51 @@ def generate_docker_matrix_entries(
     return matrix_entries
 
 
+def generate_crate_build_matrix_entries(
+    python_entries: list[dict[str, str]],
+    runners: dict[str, Any],
+    config: dict[str, Any],
+    force_crate_build: bool = False,
+    platform_filter: Optional[str] = None,
+) -> list[dict[str, str]]:
+    """Generate matrix entries for crate builds based on python build matrix."""
+    needed_builds = set()
+    for entry in python_entries:
+        # The crate build will need to match the runner's architecture
+        runner = runners[entry["runner"]]
+        needed_builds.add((entry["platform"], runner["arch"]))
+
+    # If forcing crate build, also include all possible native builds
+    if force_crate_build:
+        for platform, platform_config in config.items():
+            # Filter by platform if specified
+            if platform_filter and platform != platform_filter:
+                continue
+
+            for target_config in platform_config.values():
+                # Only include if native (run: true means native)
+                if not target_config.get("run"):
+                    continue
+
+                arch = target_config["arch"]
+                needed_builds.add((platform, arch))
+
+    # Create matrix entries for each needed build
+    return [
+        {
+            "platform": platform,
+            "arch": arch,
+            "runner": find_runner(runners, platform, arch, True),
+            "crate_artifact_name": crate_artifact_name(
+                platform,
+                arch,
+            ),
+        }
+        for platform, arch in needed_builds
+        if not platform_filter or platform == platform_filter
+    ]
+
+
 def generate_python_build_matrix_entries(
     config: dict[str, Any],
     runners: dict[str, Any],
@@ -154,10 +204,12 @@ def generate_python_build_matrix_entries(
     return matrix_entries
 
 
-def find_runner(runners: dict[str, Any], platform: str, arch: str) -> str:
+def find_runner(runners: dict[str, Any], platform: str, arch: str, free: bool) -> str:
     # Find a matching platform first
     match_platform = [
-        runner for runner in runners if runners[runner]["platform"] == platform
+        runner
+        for runner in runners
+        if runners[runner]["platform"] == platform and runners[runner]["free"] == free
     ]
 
     # Then, find a matching architecture
@@ -173,7 +225,9 @@ def find_runner(runners: dict[str, Any], platform: str, arch: str) -> str:
     if match_platform:
         return match_platform[0]
 
-    raise RuntimeError(f"No runner found for platform {platform!r} and arch {arch!r}")
+    raise RuntimeError(
+        f"No runner found for platform {platform!r} and arch {arch!r} with free={free}"
+    )
 
 
 def add_python_build_entries_for_config(
@@ -188,7 +242,7 @@ def add_python_build_entries_for_config(
     python_versions = config["python_versions"]
     build_options = config["build_options"]
     arch = config["arch"]
-    runner = find_runner(runners, platform, arch)
+    runner = find_runner(runners, platform, arch, False)
 
     # Create base entry that will be used for all variants
     base_entry = {
@@ -199,6 +253,8 @@ def add_python_build_entries_for_config(
         # If `run` is in the config, use that — otherwise, default to if the
         # runner architecture matches the build architecture
         "run": str(config.get("run", runners[runner]["arch"] == arch)).lower(),
+        # Use the crate artifact built for the runner's architecture
+        "crate_artifact_name": crate_artifact_name(platform, runners[runner]["arch"]),
     }
 
     # Add optional fields if they exist
@@ -266,9 +322,14 @@ def parse_args() -> argparse.Namespace:
         action="store_true",
         help="If only free runners should be used.",
     )
+    parser.add_argument(
+        "--force-crate-build",
+        action="store_true",
+        help="Force crate builds to be included even without python builds.",
+    )
     parser.add_argument(
         "--matrix-type",
-        choices=["python-build", "docker-build", "all"],
+        choices=["python-build", "docker-build", "crate-build", "all"],
         default="all",
         help="Which matrix types to generate (default: all)",
     )
@@ -295,16 +356,16 @@ def main() -> None:
 
     result = {}
 
-    # Generate python-build matrix if requested
-    python_entries = []
-    if args.matrix_type in ["python-build", "all"]:
-        python_entries = generate_python_build_matrix_entries(
-            config,
-            runners,
-            args.platform,
-            labels,
-        )
+    # Generate python build entries
+    python_entries = generate_python_build_matrix_entries(
+        config,
+        runners,
+        args.platform,
+        labels,
+    )
 
+    # Output python-build matrix if requested
+    if args.matrix_type in ["python-build", "all"]:
         if args.max_shards:
             python_build_matrix = {}
             shards = (len(python_entries) // CI_MATRIX_SIZE_LIMIT) + 1
@@ -345,6 +406,17 @@ def main() -> None:
             )
             result["docker-build"] = {"include": docker_entries}
 
+    # Generate crate-build matrix if requested
+    if args.matrix_type in ["crate-build", "all"]:
+        crate_entries = generate_crate_build_matrix_entries(
+            python_entries,
+            runners,
+            config,
+            args.force_crate_build,
+            args.platform,
+        )
+        result["crate-build"] = {"include": crate_entries}
+
     print(json.dumps(result))
 
 

From e17faa9e098156baeeca3ae0c2249c460fa37bb2 Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Sat, 28 Jun 2025 14:04:24 -0500
Subject: [PATCH 122/157] Update the crate build runner logic (#674)

Using the free GitHub runners for Linux breaks those builds :)
---
 ci-matrix.py | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/ci-matrix.py b/ci-matrix.py
index 96059a96..cfccdd5e 100644
--- a/ci-matrix.py
+++ b/ci-matrix.py
@@ -159,7 +159,13 @@ def generate_crate_build_matrix_entries(
         {
             "platform": platform,
             "arch": arch,
-            "runner": find_runner(runners, platform, arch, True),
+            # Use the GitHub runner for Windows, because the Depot one is
+            # missing a Rust toolchain. On Linux, it's important that the the
+            # `python-build` runner matches the `crate-build` runner because of
+            # GLIBC version mismatches.
+            "runner": find_runner(
+                runners, platform, arch, True if platform == "windows" else False
+            ),
             "crate_artifact_name": crate_artifact_name(
                 platform,
                 arch,

From b233563209eb92c9e93d284418ee8d7eefcef4a7 Mon Sep 17 00:00:00 2001
From: Dustin Rodrigues <dust.rod@gmail.com>
Date: Sun, 29 Jun 2025 11:59:01 -0400
Subject: [PATCH 123/157] use raw string literal for regex (#675)

Uses a raw string literal for the regex to avoid
```
python-build-standalone/pythonbuild/cpython.py:675: SyntaxWarning: invalid escape sequence '\{'
  RE_INITTAB_ENTRY = re.compile('\{"([^"]+)", ([^\}]+)\},')
```
---
 pythonbuild/cpython.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/pythonbuild/cpython.py b/pythonbuild/cpython.py
index f339037c..c52f7ce6 100644
--- a/pythonbuild/cpython.py
+++ b/pythonbuild/cpython.py
@@ -672,7 +672,7 @@ def derive_setup_local(
     }
 
 
-RE_INITTAB_ENTRY = re.compile('\{"([^"]+)", ([^\}]+)\},')
+RE_INITTAB_ENTRY = re.compile(r'\{"([^"]+)", ([^\}]+)\},')
 
 
 def parse_config_c(s: str):

From 14f33e81921e8f2bf20a8e58212a8f81eed2f1ba Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Mon, 30 Jun 2025 15:43:24 -0500
Subject: [PATCH 124/157] Include aarch64 Window artifacts in releases (#679)

---
 src/release.rs | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/src/release.rs b/src/release.rs
index 60e46c99..d4f890ee 100644
--- a/src/release.rs
+++ b/src/release.rs
@@ -129,6 +129,18 @@ pub static RELEASE_TRIPLES: Lazy<BTreeMap<&'static str, TripleRelease>> = Lazy::
             }],
         },
     );
+    h.insert(
+        "aarch64-pc-windows-msvc",
+        TripleRelease {
+            suffixes: vec!["pgo"],
+            install_only_suffix: "pgo",
+            python_version_requirement: Some(VersionSpecifier::from_str(">=3.11").unwrap()),
+            conditional_suffixes: vec![ConditionalSuffixes {
+                python_version_requirement: VersionSpecifier::from_str(">=3.13").unwrap(),
+                suffixes: vec!["freethreaded+pgo"],
+            }],
+        },
+    );
 
     // Linux.
     let linux_suffixes_pgo = vec!["debug", "pgo+lto"];

From c646c36b062051ebf5d211dc86763e5bd72599e2 Mon Sep 17 00:00:00 2001
From: Gregory Szorc <gregory.szorc@gmail.com>
Date: Fri, 16 May 2025 19:13:29 -0700
Subject: [PATCH 125/157] xtrans 1.5.0 -> 1.6.0

This seems to "just work." Let's stay modern.
---
 pythonbuild/downloads.py | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/pythonbuild/downloads.py b/pythonbuild/downloads.py
index 3e7adc82..0367faa8 100644
--- a/pythonbuild/downloads.py
+++ b/pythonbuild/downloads.py
@@ -392,10 +392,10 @@
         "version": "2019.1",
     },
     "xtrans": {
-        "url": "https://www.x.org/archive/individual/lib/xtrans-1.5.0.tar.gz",
-        "size": 230197,
-        "sha256": "a806f8a92f879dcd0146f3f1153fdffe845f2fc0df9b1a26c19312b7b0a29c86",
-        "version": "1.5.0",
+        "url": "https://www.x.org/archive/individual/lib/xtrans-1.6.0.tar.gz",
+        "size": 239113,
+        "sha256": "936b74c60b19c317c3f3cb1b114575032528dbdaf428740483200ea874c2ca0a",
+        "version": "1.6.0",
     },
     # IMPORTANT: xz 5.6 has a backdoor. Be extremely cautious before taking any xz
     # upgrade since it isn't clear which versions are safe.

From dd0b436c269fc10f7b2781b699387d3f19bdd645 Mon Sep 17 00:00:00 2001
From: Gregory Szorc <gregory.szorc@gmail.com>
Date: Fri, 16 May 2025 19:14:46 -0700
Subject: [PATCH 126/157] x11-util-macros 1.20.1 -> 1.20.2

---
 pythonbuild/downloads.py | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/pythonbuild/downloads.py b/pythonbuild/downloads.py
index 0367faa8..3d888e88 100644
--- a/pythonbuild/downloads.py
+++ b/pythonbuild/downloads.py
@@ -372,10 +372,10 @@
         "license_file": "LICENSE.libuuid.txt",
     },
     "x11-util-macros": {
-        "url": "https://www.x.org/archive/individual/util/util-macros-1.20.1.tar.gz",
-        "size": 105481,
-        "sha256": "b373f72887b1394ce2193180a60cb0d1fb8b17bc96ddd770cfd7a808cb489a15",
-        "version": "1.20.1",
+        "url": "https://www.x.org/archive/individual/util/util-macros-1.20.2.tar.gz",
+        "size": 105410,
+        "sha256": "f642f8964d81acdf06653fdf9dbc210c43ce4bd308bd644a8d573148d0ced76b",
+        "version": "1.20.2",
     },
     "xcb-proto": {
         "url": "https://xcb.freedesktop.org/dist/xcb-proto-1.17.0.tar.xz",

From d8ef90ad326e0e8b7074ba097df5a414288ff3c6 Mon Sep 17 00:00:00 2001
From: Gregory Szorc <gregory.szorc@gmail.com>
Date: Fri, 16 May 2025 19:18:59 -0700
Subject: [PATCH 127/157] xorgproto 2019.1 -> 2024.1

I think deletion of the legacy proto packages a few commits ago fixed up
the build failures the deleted comment alluded to.
---
 pythonbuild/downloads.py | 10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/pythonbuild/downloads.py b/pythonbuild/downloads.py
index 3d888e88..c1cae140 100644
--- a/pythonbuild/downloads.py
+++ b/pythonbuild/downloads.py
@@ -383,13 +383,11 @@
         "sha256": "2c1bacd2110f4799f74de6ebb714b94cf6f80fb112316b1219480fd22562148c",
         "version": "1.17.0",
     },
-    # Newer versions from at least 2023 have build failures for reasons we haven't
-    # fully investigated.
     "xorgproto": {
-        "url": "https://www.x.org/archive/individual/proto/xorgproto-2019.1.tar.gz",
-        "size": 1119813,
-        "sha256": "38ad1d8316515785d53c5162b4b7022918e03c11d72a5bd9df0a176607f42bca",
-        "version": "2019.1",
+        "url": "https://www.x.org/archive/individual/proto/xorgproto-2024.1.tar.gz",
+        "size": 1115486,
+        "sha256": "4f6b9b4faf91e5df8265b71843a91fc73dc895be6210c84117a996545df296ce",
+        "version": "2024.1",
     },
     "xtrans": {
         "url": "https://www.x.org/archive/individual/lib/xtrans-1.6.0.tar.gz",

From 21cf744dda2d0e19329950a81a07d9067179f976 Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Sat, 28 Jun 2025 14:04:53 -0500
Subject: [PATCH 128/157] Enable native builds on Linux aarch64

I just published an LLVM 20 toolchain for aarch64. The toolchain
has support for PGO and BOLT.

This commit switches the Linux aarch64 builds to be performed natively
on aarch64 machines. PGO and BOLT are enabled on the builds, hopefully
making them a bit faster.
---
 .github/workflows/linux.yml           | 18 +++----
 ci-matrix.py                          |  2 +
 ci-runners.yaml                       |  9 ++--
 ci-targets.yaml                       |  6 +--
 cpython-unix/Makefile                 | 12 ++---
 cpython-unix/base.debian9.Dockerfile  | 38 ++++++++++++++
 cpython-unix/build-binutils.sh        |  8 ++-
 cpython-unix/build-main.py            |  1 +
 cpython-unix/build.debian9.Dockerfile | 16 ++++++
 cpython-unix/build.py                 | 74 +++++++++++++++++----------
 cpython-unix/gcc.debian9.Dockerfile   | 14 +++++
 cpython-unix/targets.yml              | 21 ++++++--
 pythonbuild/docker.py                 | 17 ++++--
 pythonbuild/downloads.py              |  7 +++
 pythonbuild/utils.py                  | 14 +++++
 15 files changed, 195 insertions(+), 62 deletions(-)
 create mode 100644 cpython-unix/base.debian9.Dockerfile
 create mode 100644 cpython-unix/build.debian9.Dockerfile
 create mode 100644 cpython-unix/gcc.debian9.Dockerfile

diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml
index 8ae87e76..d4602fbe 100644
--- a/.github/workflows/linux.yml
+++ b/.github/workflows/linux.yml
@@ -2,7 +2,7 @@ name: linux
 
 on:
   push:
-    branches: [main]
+    branches: [ main ]
   pull_request:
 
 concurrency:
@@ -58,7 +58,7 @@ jobs:
     strategy:
       fail-fast: false
       matrix: ${{ fromJson(needs.generate-matrix.outputs.docker-build-matrix) }}
-    name: image / ${{ matrix.name }}
+    name: image / ${{ matrix.arch }} / ${{ matrix.name }}
     runs-on: ${{ matrix.runner }}
     permissions:
       packages: write
@@ -100,23 +100,23 @@ jobs:
           # Cache from the default branch of the canonical repo so forks can have cache hits.
           # Ignore errors on cache writes so CI of forks works without a valid GHCR config.
           cache-from: |
-            type=registry,ref=ghcr.io/${{ env.REPO_NAME }}:${{ matrix.name }}-${{ env.GIT_REF_NAME }}
-            type=registry,ref=ghcr.io/${{ env.REPO_NAME }}:${{ matrix.name }}-main
-            type=registry,ref=ghcr.io/astral-sh/python-build-standalone:${{ matrix.name }}-main
+            type=registry,ref=ghcr.io/${{ env.REPO_NAME }}:${{ matrix.name }}-linux_${{ matrix.arch }}-${{ env.GIT_REF_NAME }}
+            type=registry,ref=ghcr.io/${{ env.REPO_NAME }}:${{ matrix.name }}-linux_${{ matrix.arch }}-main
+            type=registry,ref=ghcr.io/astral-sh/python-build-standalone:${{ matrix.name }}-linux_${{ matrix.arch }}-main
           cache-to: |
-            type=registry,ref=ghcr.io/${{ env.REPO_NAME }}:${{ matrix.name }}-${{ env.GIT_REF_NAME }},ignore-error=true
+            type=registry,ref=ghcr.io/${{ env.REPO_NAME }}:${{ matrix.name }}-linux_${{ matrix.arch }}-${{ env.GIT_REF_NAME }},ignore-error=true
           outputs: |
-            type=docker,dest=build/image-${{ matrix.name }}.tar
+            type=docker,dest=build/image-${{ matrix.name }}.linux_${{ matrix.arch }}.tar
 
       - name: Compress Image
         run: |
-          echo ${{ steps.build-image.outputs.imageid }} > build/image-${{ matrix.name }}
+          echo ${{ steps.build-image.outputs.imageid }} > build/image-${{ matrix.name }}.linux_${{ matrix.arch }}
           zstd -v -T0 -6 --rm build/image-*.tar
 
       - name: Upload Docker Image
         uses: actions/upload-artifact@v4
         with:
-          name: image-${{ matrix.name }}
+          name: image-${{ matrix.name }}-linux_${{ matrix.arch }}
           path: build/image-*
 
   generate-matrix:
diff --git a/ci-matrix.py b/ci-matrix.py
index cfccdd5e..91cfa953 100644
--- a/ci-matrix.py
+++ b/ci-matrix.py
@@ -25,7 +25,9 @@
     {"name": "build", "arch": "x86_64"},
     {"name": "build.cross", "arch": "x86_64"},
     {"name": "build.cross-riscv64", "arch": "x86_64"},
+    {"name": "build.debian9", "arch": "aarch64"},
     {"name": "gcc", "arch": "x86_64"},
+    {"name": "gcc.debian9", "arch": "aarch64"},
 ]
 
 
diff --git a/ci-runners.yaml b/ci-runners.yaml
index 43ff9414..dae6aabc 100644
--- a/ci-runners.yaml
+++ b/ci-runners.yaml
@@ -5,11 +5,10 @@ depot-ubuntu-22.04:
   platform: linux
   free: false
 
-# TODO: Enable this runner to perform native builds for aarch64
-# depot-ubuntu-22.04-arm:
-#   arch: aarch64
-#   platform: linux
-#   free: false
+depot-ubuntu-22.04-arm:
+  arch: aarch64
+  platform: linux
+  free: false
 
 depot-macos-latest:
   arch: x86_64
diff --git a/ci-targets.yaml b/ci-targets.yaml
index c7b4bd12..c59d5b7f 100644
--- a/ci-targets.yaml
+++ b/ci-targets.yaml
@@ -50,13 +50,11 @@ linux:
       - "3.14"
     build_options:
       - debug
-      - noopt
-      - lto
+      - pgo+lto
     build_options_conditional:
       - options:
           - freethreaded+debug
-          - freethreaded+noopt
-          - freethreaded+lto
+          - freethreaded+pgo+lto
         minimum-python-version: "3.13"
 
   armv7-unknown-linux-gnueabi:
diff --git a/cpython-unix/Makefile b/cpython-unix/Makefile
index 4cacaff3..6e4b0070 100644
--- a/cpython-unix/Makefile
+++ b/cpython-unix/Makefile
@@ -66,7 +66,7 @@ TOOLCHAIN_DEPENDS := \
 
 PYTHON_DEP_DEPENDS := \
     $(OUTDIR)/targets/$(TARGET_TRIPLE) \
-    $(if $(PYBUILD_NO_DOCKER),,$(OUTDIR)/image-$(DOCKER_IMAGE_BUILD).tar) \
+    $(if $(PYBUILD_NO_DOCKER),,$(OUTDIR)/image-$(DOCKER_IMAGE_BUILD).$(HOST_PLATFORM).tar) \
     $(TOOLCHAIN_DEPENDS) \
     $(NULL)
 
@@ -75,18 +75,18 @@ HOST_PYTHON_DEPENDS := $(OUTDIR)/cpython-$(PYTHON_MAJOR_VERSION)-$(CPYTHON_$(PYT
 default: $(OUTDIR)/cpython-$(CPYTHON_$(PYTHON_MAJOR_VERSION)_VERSION)-$(PACKAGE_SUFFIX).tar
 
 ifndef PYBUILD_NO_DOCKER
-$(OUTDIR)/image-%.tar: $(OUTDIR)/%.Dockerfile
+$(OUTDIR)/image-%.$(HOST_PLATFORM).tar: $(OUTDIR)/%.Dockerfile
 	$(RUN_BUILD) --toolchain image-$*
 endif
 
-$(OUTDIR)/binutils-$(BINUTILS_VERSION)-$(HOST_PLATFORM).tar: $(OUTDIR)/image-gcc.tar $(HERE)/build-binutils.sh
-	$(RUN_BUILD) --toolchain binutils
+$(OUTDIR)/binutils-$(BINUTILS_VERSION)-$(HOST_PLATFORM).tar: $(HERE)/build-binutils.sh
+	$(RUN_BUILD) --toolchain --docker-image $(DOCKER_IMAGE_GCC) binutils
 
 $(OUTDIR)/$(CLANG_FILENAME):
 	$(RUN_BUILD) --toolchain clang --target-triple $(TARGET_TRIPLE)
 
 $(OUTDIR)/musl-$(MUSL_VERSION)-$(HOST_PLATFORM).tar: $(BASE_TOOLCHAIN_DEPENDS) $(HERE)/build-musl.sh
-	$(RUN_BUILD) --toolchain musl
+	$(RUN_BUILD) --toolchain musl --docker-image $(DOCKER_IMAGE_GCC)
 
 ifeq ($(HOST_PLATFORM),linux_x86_64)
     TOOLCHAIN_TARGET := $(OUTDIR)/musl-$(MUSL_VERSION)-$(HOST_PLATFORM).tar
@@ -125,7 +125,7 @@ $(OUTDIR)/libffi-3.3-$(LIBFFI_3.3_VERSION)-$(PACKAGE_SUFFIX).tar: $(PYTHON_DEP_D
 $(OUTDIR)/libffi-$(LIBFFI_VERSION)-$(PACKAGE_SUFFIX).tar: $(PYTHON_DEP_DEPENDS) $(HERE)/build-libffi.sh
 	$(RUN_BUILD) --docker-image $(DOCKER_IMAGE_BUILD) libffi
 
-$(OUTDIR)/libpthread-stubs-$(LIBPTHREAD_STUBS_VERSION)-$(PACKAGE_SUFFIX).tar: $(PYTHON_DEP_DEPENDS) $(HERE)/build-libpthread-stubs.sh $(OUTDIR)/image-$(DOCKER_IMAGE_BUILD).tar
+$(OUTDIR)/libpthread-stubs-$(LIBPTHREAD_STUBS_VERSION)-$(PACKAGE_SUFFIX).tar: $(PYTHON_DEP_DEPENDS) $(HERE)/build-libpthread-stubs.sh $(OUTDIR)/image-$(DOCKER_IMAGE_BUILD).$(HOST_PLATFORM).tar
 	$(RUN_BUILD) --docker-image $(DOCKER_IMAGE_BUILD) libpthread-stubs
 
 LIBX11_DEPENDS = \
diff --git a/cpython-unix/base.debian9.Dockerfile b/cpython-unix/base.debian9.Dockerfile
new file mode 100644
index 00000000..1b47b35a
--- /dev/null
+++ b/cpython-unix/base.debian9.Dockerfile
@@ -0,0 +1,38 @@
+# Debian Stretch.
+FROM debian@sha256:c5c5200ff1e9c73ffbf188b4a67eb1c91531b644856b4aefe86a58d2f0cb05be
+MAINTAINER Gregory Szorc <gregory.szorc@gmail.com>
+
+RUN groupadd -g 1000 build && \
+    useradd -u 1000 -g 1000 -d /build -s /bin/bash -m build && \
+    mkdir /tools && \
+    chown -R build:build /build /tools
+
+ENV HOME=/build \
+    SHELL=/bin/bash \
+    USER=build \
+    LOGNAME=build \
+    HOSTNAME=builder \
+    DEBIAN_FRONTEND=noninteractive
+
+CMD ["/bin/bash", "--login"]
+WORKDIR '/build'
+
+RUN for s in debian_stretch debian_stretch-updates debian-security_stretch/updates; do \
+      echo "deb http://snapshot.debian.org/archive/${s%_*}/20230423T032736Z/ ${s#*_} main"; \
+    done > /etc/apt/sources.list && \
+    ( echo 'quiet "true";'; \
+      echo 'APT::Get::Assume-Yes "true";'; \
+      echo 'APT::Install-Recommends "false";'; \
+      echo 'Acquire::Check-Valid-Until "false";'; \
+      echo 'Acquire::Retries "5";'; \
+    ) > /etc/apt/apt.conf.d/99cpython-portable
+
+# apt iterates all available file descriptors up to rlim_max and calls
+# fcntl(fd, F_SETFD, FD_CLOEXEC). This can result in millions of system calls
+# (we've seen 1B in the wild) and cause operations to take seconds to minutes.
+# Setting a fd limit mitigates.
+#
+# Attempts at enforcing the limit globally via /etc/security/limits.conf and
+# /root/.bashrc were not successful. Possibly because container image builds
+# don't perform a login or use a shell the way we expect.
+RUN ulimit -n 10000 && apt-get update
diff --git a/cpython-unix/build-binutils.sh b/cpython-unix/build-binutils.sh
index c52e8238..2bb89364 100755
--- a/cpython-unix/build-binutils.sh
+++ b/cpython-unix/build-binutils.sh
@@ -11,9 +11,15 @@ tar -xf binutils-${BINUTILS_VERSION}.tar.xz
 mkdir binutils-objdir
 pushd binutils-objdir
 
+if [ "$(uname -m)" = "x86_64" ]; then
+  triple="x86_64-unknown-linux-gnu"
+else
+  triple="aarch64-unknown-linux-gnu"
+fi
+
 # gprofng requires a bison newer than what we have. So just disable it.
 ../binutils-${BINUTILS_VERSION}/configure \
-    --build=x86_64-unknown-linux-gnu \
+    --build=${triple} \
     --prefix=/tools/host \
     --enable-plugins \
     --enable-gprofng=no \
diff --git a/cpython-unix/build-main.py b/cpython-unix/build-main.py
index a353daf2..7a7d08b1 100755
--- a/cpython-unix/build-main.py
+++ b/cpython-unix/build-main.py
@@ -95,6 +95,7 @@ def main():
             "toolchain-image-build",
             "toolchain-image-build.cross",
             "toolchain-image-build.cross-riscv64",
+            "toolchain-image-build.debian9",
             "toolchain-image-gcc",
             "toolchain-image-xcb",
             "toolchain-image-xcb.cross",
diff --git a/cpython-unix/build.debian9.Dockerfile b/cpython-unix/build.debian9.Dockerfile
new file mode 100644
index 00000000..1f7c91b6
--- /dev/null
+++ b/cpython-unix/build.debian9.Dockerfile
@@ -0,0 +1,16 @@
+{% include 'base.debian9.Dockerfile' %}
+
+RUN ulimit -n 10000 && apt-get install \
+    bzip2 \
+    file \
+    libc6-dev \
+    libffi-dev \
+    make \
+    patch \
+    perl \
+    pkg-config \
+    tar \
+    xz-utils \
+    unzip \
+    zip \
+    zlib1g-dev
diff --git a/cpython-unix/build.py b/cpython-unix/build.py
index 6f98e990..01d39b2a 100755
--- a/cpython-unix/build.py
+++ b/cpython-unix/build.py
@@ -88,14 +88,21 @@ def add_target_env(env, build_platform, target_triple, build_env):
     extra_host_cflags = []
     extra_host_ldflags = []
 
-    if build_platform == "linux_x86_64":
-        env["BUILD_TRIPLE"] = "x86_64-unknown-linux-gnu"
+    if build_platform.startswith("linux_"):
+        machine = platform.machine()
 
-        env["TARGET_TRIPLE"] = (
-            target_triple.replace("x86_64_v2-", "x86_64-")
-            .replace("x86_64_v3-", "x86_64-")
-            .replace("x86_64_v4-", "x86_64-")
-        )
+        if machine == "aarch64":
+            env["BUILD_TRIPLE"] = "aarch64-unknown-linux-gnu"
+            env["TARGET_TRIPLE"] = target_triple
+        elif machine == "x86_64":
+            env["BUILD_TRIPLE"] = "x86_64-unknown-linux-gnu"
+            env["TARGET_TRIPLE"] = (
+                target_triple.replace("x86_64_v2-", "x86_64-")
+                .replace("x86_64_v3-", "x86_64-")
+                .replace("x86_64_v4-", "x86_64-")
+            )
+        else:
+            raise Exception("unhandled Linux machine value: %s" % machine)
 
         # This will make x86_64_v2, etc count as cross-compiling. This is
         # semantically correct, since the current machine may not support
@@ -105,7 +112,7 @@ def add_target_env(env, build_platform, target_triple, build_env):
         ):
             env["CROSS_COMPILING"] = "1"
 
-    if build_platform.startswith("macos_"):
+    elif build_platform.startswith("macos_"):
         machine = platform.machine()
 
         if machine == "arm64":
@@ -188,6 +195,8 @@ def add_target_env(env, build_platform, target_triple, build_env):
 
         extra_host_cflags.extend(["-isysroot", host_sdk_path])
         extra_host_ldflags.extend(["-isysroot", host_sdk_path])
+    else:
+        raise Exception("unhandled build platform: %s" % build_platform)
 
     env["EXTRA_HOST_CFLAGS"] = " ".join(extra_host_cflags)
     env["EXTRA_HOST_LDFLAGS"] = " ".join(extra_host_ldflags)
@@ -496,10 +505,14 @@ def python_build_info(
 
     binary_suffix = ""
 
-    if platform == "linux_x86_64":
+    if platform in ("linux_x86_64", "linux_aarch64"):
+        arch = platform.removeprefix("linux_")
+
         bi["core"]["static_lib"] = (
-            "install/lib/python{version}/config-{version}{binary_suffix}-x86_64-linux-gnu/libpython{version}{binary_suffix}.a".format(
-                version=version, binary_suffix=binary_suffix
+            "install/lib/python{version}/config-{version}{binary_suffix}-{arch}-linux-gnu/libpython{version}{binary_suffix}.a".format(
+                version=version,
+                binary_suffix=binary_suffix,
+                arch=arch,
             )
         )
 
@@ -579,7 +592,10 @@ def python_build_info(
         if lib.startswith("-l"):
             lib = lib[2:]
 
-            if platform == "linux_x86_64" and lib not in linux_allowed_system_libraries:
+            if (
+                platform in ("linux_x86_64", "linux_aarch64")
+                and lib not in linux_allowed_system_libraries
+            ):
                 raise Exception("unexpected library in LIBS (%s): %s" % (libs, lib))
             elif (
                 platform.startswith("macos_")
@@ -851,7 +867,7 @@ def build_cpython(
         extension_module_loading = ["builtin"]
         crt_features = []
 
-        if host_platform == "linux_x86_64":
+        if host_platform in ("linux_x86_64", "linux_aarch64"):
             if "static" in parsed_build_options:
                 crt_features.append("static")
             else:
@@ -1080,10 +1096,14 @@ def main():
             with image_path.open("rb") as fh:
                 image_data = fh.read()
 
-            build_docker_image(client, image_data, BUILD, image_name)
+            build_docker_image(client, image_data, BUILD, image_name, host_platform)
 
         elif action == "binutils":
-            build_binutils(client, get_image(client, ROOT, BUILD, "gcc"), host_platform)
+            build_binutils(
+                client,
+                get_image(client, ROOT, BUILD, docker_image, host_platform),
+                host_platform,
+            )
 
         elif action == "clang":
             materialize_clang(host_platform, target_triple)
@@ -1091,7 +1111,7 @@ def main():
         elif action == "musl":
             build_musl(
                 client,
-                get_image(client, ROOT, BUILD, "gcc"),
+                get_image(client, ROOT, BUILD, docker_image, host_platform),
                 host_platform,
                 target_triple,
                 build_options,
@@ -1101,7 +1121,7 @@ def main():
             simple_build(
                 settings,
                 client,
-                get_image(client, ROOT, BUILD, docker_image),
+                get_image(client, ROOT, BUILD, docker_image, host_platform),
                 action,
                 host_platform=host_platform,
                 target_triple=target_triple,
@@ -1115,7 +1135,7 @@ def main():
             build_libedit(
                 settings,
                 client,
-                get_image(client, ROOT, BUILD, docker_image),
+                get_image(client, ROOT, BUILD, docker_image, host_platform),
                 host_platform=host_platform,
                 target_triple=target_triple,
                 build_options=build_options,
@@ -1149,7 +1169,7 @@ def main():
             simple_build(
                 settings,
                 client,
-                get_image(client, ROOT, BUILD, docker_image),
+                get_image(client, ROOT, BUILD, docker_image, host_platform),
                 action,
                 host_platform=host_platform,
                 target_triple=target_triple,
@@ -1162,7 +1182,7 @@ def main():
             simple_build(
                 settings,
                 client,
-                get_image(client, ROOT, BUILD, docker_image),
+                get_image(client, ROOT, BUILD, docker_image, host_platform),
                 action,
                 host_platform=host_platform,
                 target_triple=target_triple,
@@ -1182,7 +1202,7 @@ def main():
             simple_build(
                 settings,
                 client,
-                get_image(client, ROOT, BUILD, docker_image),
+                get_image(client, ROOT, BUILD, docker_image, host_platform),
                 action,
                 host_platform=host_platform,
                 target_triple=target_triple,
@@ -1195,7 +1215,7 @@ def main():
             simple_build(
                 settings,
                 client,
-                get_image(client, ROOT, BUILD, docker_image),
+                get_image(client, ROOT, BUILD, docker_image, host_platform),
                 action,
                 host_platform=host_platform,
                 target_triple=target_triple,
@@ -1208,7 +1228,7 @@ def main():
             simple_build(
                 settings,
                 client,
-                get_image(client, ROOT, BUILD, docker_image),
+                get_image(client, ROOT, BUILD, docker_image, host_platform),
                 action,
                 host_platform=host_platform,
                 target_triple=target_triple,
@@ -1222,7 +1242,7 @@ def main():
             build_tix(
                 settings,
                 client,
-                get_image(client, ROOT, BUILD, docker_image),
+                get_image(client, ROOT, BUILD, docker_image, host_platform),
                 host_platform=host_platform,
                 target_triple=target_triple,
                 build_options=build_options,
@@ -1243,7 +1263,7 @@ def main():
             simple_build(
                 settings,
                 client,
-                get_image(client, ROOT, BUILD, docker_image),
+                get_image(client, ROOT, BUILD, docker_image, host_platform),
                 action,
                 host_platform=host_platform,
                 target_triple=target_triple,
@@ -1256,7 +1276,7 @@ def main():
         elif action.startswith("cpython-") and action.endswith("-host"):
             build_cpython_host(
                 client,
-                get_image(client, ROOT, BUILD, docker_image),
+                get_image(client, ROOT, BUILD, docker_image, host_platform),
                 action[:-5],
                 host_platform=host_platform,
                 target_triple=target_triple,
@@ -1275,7 +1295,7 @@ def main():
             build_cpython(
                 settings,
                 client,
-                get_image(client, ROOT, BUILD, docker_image),
+                get_image(client, ROOT, BUILD, docker_image, host_platform),
                 host_platform=host_platform,
                 target_triple=target_triple,
                 build_options=build_options,
diff --git a/cpython-unix/gcc.debian9.Dockerfile b/cpython-unix/gcc.debian9.Dockerfile
new file mode 100644
index 00000000..92d764e8
--- /dev/null
+++ b/cpython-unix/gcc.debian9.Dockerfile
@@ -0,0 +1,14 @@
+{% include 'base.debian9.Dockerfile' %}
+RUN ulimit -n 10000 && apt-get install \
+      autoconf \
+      automake \
+      bison \
+      build-essential \
+      gawk \
+      gcc \
+      libtool \
+      make \
+      tar \
+      texinfo \
+      xz-utils \
+      unzip
diff --git a/cpython-unix/targets.yml b/cpython-unix/targets.yml
index 1b47dba4..95ef58b2 100644
--- a/cpython-unix/targets.yml
+++ b/cpython-unix/targets.yml
@@ -156,6 +156,7 @@ aarch64-apple-ios:
 aarch64-unknown-linux-gnu:
   host_platforms:
     - linux_x86_64
+    - linux_aarch64
   pythons_supported:
     - '3.9'
     - '3.10'
@@ -163,11 +164,16 @@ aarch64-unknown-linux-gnu:
     - '3.12'
     - '3.13'
     - '3.14'
-  docker_image_suffix: .cross
-  host_cc: /usr/bin/x86_64-linux-gnu-gcc
-  host_cxx: /usr/bin/x86_64-linux-gnu-g++
-  target_cc: /usr/bin/aarch64-linux-gnu-gcc
-  target_cxx: /usr/bin/aarch64-linux-gnu-g++
+  docker_image_suffix: .debian9
+  needs_toolchain: true
+  host_cc: clang
+  host_cxx: clang++
+  target_cc: clang
+  target_cxx: clang++
+  target_cflags:
+    - '-fvisibility=hidden'
+    # Needed to prevent BOLT from crashing.
+    - '-fdebug-default-version=4'
   needs:
     - autoconf
     - bdb
@@ -193,6 +199,11 @@ aarch64-unknown-linux-gnu:
     - xz
     - zlib
   openssl_target: linux-aarch64
+  # Blocked on:
+  #   BOLT-ERROR: Cannot relax adr in non-simple function
+  #   trampoline_code_table/1. Use --strict option to override
+  # See https://github.com/llvm/llvm-project/issues/146541
+  # bolt_capable: true
 
 arm64-apple-tvos:
   host_platforms:
diff --git a/pythonbuild/docker.py b/pythonbuild/docker.py
index 4269b2bd..0be78e4f 100644
--- a/pythonbuild/docker.py
+++ b/pythonbuild/docker.py
@@ -29,8 +29,10 @@ def write_dockerfiles(source_dir: pathlib.Path, dest_dir: pathlib.Path):
         write_if_different(dest_dir / f, data.encode("utf-8"))
 
 
-def build_docker_image(client, image_data: bytes, image_dir: pathlib.Path, name):
-    image_path = image_dir / ("image-%s" % name)
+def build_docker_image(
+    client, image_data: bytes, image_dir: pathlib.Path, name, host_platform
+):
+    image_path = image_dir / f"image-{name}.{host_platform}"
 
     return ensure_docker_image(client, io.BytesIO(image_data), image_path=image_path)
 
@@ -66,11 +68,14 @@ def ensure_docker_image(client, fh, image_path=None):
     return image
 
 
-def get_image(client, source_dir: pathlib.Path, image_dir: pathlib.Path, name):
+def get_image(
+    client, source_dir: pathlib.Path, image_dir: pathlib.Path, name, host_platform
+):
     if client is None:
         return None
 
-    image_path = image_dir / ("image-%s" % name)
+    image_name = f"image-{name}.{host_platform}"
+    image_path = image_dir / image_name
     tar_path = image_path.with_suffix(".tar")
 
     with image_path.open("r") as fh:
@@ -88,7 +93,9 @@ def get_image(client, source_dir: pathlib.Path, image_dir: pathlib.Path, name):
             return image_id
 
         else:
-            return build_docker_image(client, str(source_dir).encode(), image_dir, name)
+            return build_docker_image(
+                client, str(source_dir).encode(), image_dir, name, host_platform
+            )
 
 
 def copy_file_to_container(path, container, container_path, archive_path=None):
diff --git a/pythonbuild/downloads.py b/pythonbuild/downloads.py
index c1cae140..24a9917e 100644
--- a/pythonbuild/downloads.py
+++ b/pythonbuild/downloads.py
@@ -172,6 +172,13 @@
         "version": "14.0.3+20220508",
     },
     # Remember to update LLVM_URL in src/release.rs whenever upgrading.
+    "llvm-20-aarch64-linux": {
+        "url": "https://github.com/indygreg/toolchain-tools/releases/download/toolchain-bootstrap%2F20250511/llvm-20.1.4+20250511-gnu_only-aarch64-unknown-linux-gnu.tar.zst",
+        "size": 255946687,
+        "sha256": "e70753f294b8f83fffbaf07af36857c27ceaef0291cb10f724ada6af11b0a5bc",
+        "version": "20.1.4+20250511",
+    },
+    # Remember to update LLVM_URL in src/release.rs whenever upgrading.
     "llvm-20-x86_64-linux": {
         "url": "https://github.com/indygreg/toolchain-tools/releases/download/toolchain-bootstrap%2F20250511/llvm-20.1.4+20250511-gnu_only-x86_64-unknown-linux-gnu.tar.zst",
         "size": 299883811,
diff --git a/pythonbuild/utils.py b/pythonbuild/utils.py
index a8132ca8..0edc11d7 100644
--- a/pythonbuild/utils.py
+++ b/pythonbuild/utils.py
@@ -39,6 +39,8 @@ def current_host_platform() -> str:
     if sys.platform == "linux":
         if machine == "x86_64":
             return "linux_x86_64"
+        elif machine == "aarch64":
+            return "linux_aarch64"
         else:
             raise Exception(f"unsupported Linux host platform: {machine}")
     elif sys.platform == "darwin":
@@ -57,6 +59,8 @@ def default_target_triple() -> str:
     host = current_host_platform()
     if host == "linux_x86_64":
         return "x86_64-unknown-linux-gnu"
+    elif host == "linux_aarch64":
+        return "aarch64-unknown-linux-gnu"
     elif host == "macos_arm64":
         return "aarch64-apple-darwin"
     elif host == "macos_x86_64":
@@ -84,6 +88,8 @@ def supported_targets(yaml_path: pathlib.Path):
         for host_platform in settings["host_platforms"]:
             if sys.platform == "linux" and host_platform == "linux_x86_64":
                 targets.add(target)
+            elif sys.platform == "linux" and host_platform == "linux_aarch64":
+                targets.add(target)
             elif sys.platform == "darwin" and host_platform.startswith("macos_"):
                 targets.add(target)
 
@@ -194,7 +200,13 @@ def write_triples_makefiles(
 
             image_suffix = settings.get("docker_image_suffix", "")
 
+            # On cross builds, we can just use the bare `gcc` image
+            gcc_image_suffix = (
+                image_suffix if not image_suffix.startswith(".cross") else ""
+            )
+
             lines.append("DOCKER_IMAGE_BUILD := build%s\n" % image_suffix)
+            lines.append("DOCKER_IMAGE_GCC := gcc%s\n" % gcc_image_suffix)
 
             entry = clang_toolchain(host_platform, triple)
             lines.append(
@@ -470,6 +482,8 @@ def clang_toolchain(host_platform: str, target_triple: str) -> str:
             return "llvm-14-x86_64-linux"
         else:
             return "llvm-20-x86_64-linux"
+    elif host_platform == "linux_aarch64":
+        return "llvm-20-aarch64-linux"
     elif host_platform == "macos_arm64":
         return "llvm-aarch64-macos"
     elif host_platform == "macos_x86_64":

From 9bb8bcbeab73b8a962aba962c00f469cbe2cb9b3 Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Wed, 2 Jul 2025 12:30:14 -0500
Subject: [PATCH 129/157] Update wanted release targets for
 `aarch64-unknown-linux-gnu` (#681)

Following #670
---
 src/release.rs | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/release.rs b/src/release.rs
index d4f890ee..0b67888d 100644
--- a/src/release.rs
+++ b/src/release.rs
@@ -168,12 +168,12 @@ pub static RELEASE_TRIPLES: Lazy<BTreeMap<&'static str, TripleRelease>> = Lazy::
     h.insert(
         "aarch64-unknown-linux-gnu",
         TripleRelease {
-            suffixes: linux_suffixes_nopgo.clone(),
-            install_only_suffix: "lto",
+            suffixes: linux_suffixes_pgo.clone(),
+            install_only_suffix: "pgo+lto",
             python_version_requirement: None,
             conditional_suffixes: vec![ConditionalSuffixes {
                 python_version_requirement: VersionSpecifier::from_str(">=3.13").unwrap(),
-                suffixes: linux_suffixes_nopgo_freethreaded.clone(),
+                suffixes: linux_suffixes_pgo_freethreaded.clone(),
             }],
         },
     );

From aaf602236d4cf3e2bd207dfd8f9d45cd0870d58d Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Sat, 5 Jul 2025 11:23:20 -0500
Subject: [PATCH 130/157] Add zstd support for Python 3.14+ on Unix (#682)

This task was deferred from the initial Python 3.14 support. There's
already support on Windows.
---
 cpython-unix/Makefile              |  4 ++
 cpython-unix/build-cpython.sh      |  2 +-
 cpython-unix/build-zstd.sh         | 63 ++++++++++++++++++++++++++++++
 cpython-unix/build.py              |  1 +
 cpython-unix/extension-modules.yml |  7 ++--
 cpython-unix/targets.yml           | 24 ++++++++++++
 src/validation.rs                  |  4 +-
 7 files changed, 98 insertions(+), 7 deletions(-)
 create mode 100755 cpython-unix/build-zstd.sh

diff --git a/cpython-unix/Makefile b/cpython-unix/Makefile
index 6e4b0070..dcb239aa 100644
--- a/cpython-unix/Makefile
+++ b/cpython-unix/Makefile
@@ -236,6 +236,9 @@ $(OUTDIR)/xz-$(XZ_VERSION)-$(PACKAGE_SUFFIX).tar: $(PYTHON_DEP_DEPENDS) $(HERE)/
 $(OUTDIR)/zlib-$(ZLIB_VERSION)-$(PACKAGE_SUFFIX).tar: $(PYTHON_DEP_DEPENDS) $(HERE)/build-zlib.sh
 	$(RUN_BUILD) --docker-image $(DOCKER_IMAGE_BUILD) zlib
 
+$(OUTDIR)/zstd-$(ZSTD_VERSION)-$(PACKAGE_SUFFIX).tar: $(PYTHON_DEP_DEPENDS) $(HERE)/build-zstd.sh
+	$(RUN_BUILD) --docker-image $(DOCKER_IMAGE_BUILD) zstd
+
 PYTHON_HOST_DEPENDS := \
   $(PYTHON_DEP_DEPENDS) \
   $(HERE)/build-cpython-host.sh \
@@ -272,6 +275,7 @@ PYTHON_DEPENDS_$(1) := \
     $$(if $$(NEED_UUID),$$(OUTDIR)/uuid-$$(UUID_VERSION)-$$(PACKAGE_SUFFIX).tar) \
     $$(if $$(NEED_XZ),$$(OUTDIR)/xz-$$(XZ_VERSION)-$$(PACKAGE_SUFFIX).tar) \
     $$(if $$(NEED_ZLIB),$$(OUTDIR)/zlib-$$(ZLIB_VERSION)-$$(PACKAGE_SUFFIX).tar) \
+    $$(if $$(NEED_ZSTD),$$(OUTDIR)/zstd-$$(ZSTD_VERSION)-$$(PACKAGE_SUFFIX).tar) \
     $$(NULL)
 
 ALL_PYTHON_DEPENDS_$(1) = \
diff --git a/cpython-unix/build-cpython.sh b/cpython-unix/build-cpython.sh
index ce88e6c7..4a85ba73 100755
--- a/cpython-unix/build-cpython.sh
+++ b/cpython-unix/build-cpython.sh
@@ -1213,7 +1213,7 @@ ${BUILD_PYTHON} ${ROOT}/fix_shebangs.py ${ROOT}/out/python/install
 # downstream consumers.
 OBJECT_DIRS="Objects Parser Parser/lexer Parser/pegen Parser/tokenizer Programs Python Python/deepfreeze"
 OBJECT_DIRS="${OBJECT_DIRS} Modules"
-for ext in _blake2 cjkcodecs _ctypes _ctypes/darwin _decimal _expat _hacl _io _multiprocessing _sha3 _sqlite _sre _testinternalcapi _xxtestfuzz ; do
+for ext in _blake2 cjkcodecs _ctypes _ctypes/darwin _decimal _expat _hacl _io _multiprocessing _sha3 _sqlite _sre _testinternalcapi _xxtestfuzz _zstd; do
     OBJECT_DIRS="${OBJECT_DIRS} Modules/${ext}"
 done
 
diff --git a/cpython-unix/build-zstd.sh b/cpython-unix/build-zstd.sh
new file mode 100755
index 00000000..e81ef781
--- /dev/null
+++ b/cpython-unix/build-zstd.sh
@@ -0,0 +1,63 @@
+#!/usr/bin/env bash
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at https://mozilla.org/MPL/2.0/.
+
+set -ex
+
+ROOT=`pwd`
+
+export PATH=${TOOLS_PATH}/${TOOLCHAIN}/bin:${TOOLS_PATH}/host/bin:$PATH
+export PREFIX="/tools/deps"
+
+tar -xf zstd-${ZSTD_VERSION}.tar.gz
+
+pushd cpython-source-deps-zstd-${ZSTD_VERSION}/lib
+
+if [ "${CC}" = "musl-clang" ]; then
+    # In order to build the library with SSE2, BMI, and AVX2 intrinstics, we need musl-clang to find
+    # headers that provide access to the intrinsics, as they are not provided by musl. These are
+    # part of the include files that are part of clang. But musl-clang eliminates them from the
+    # default include path. So copy them into place.
+    for h in ${TOOLS_PATH}/${TOOLCHAIN}/lib/clang/*/include/*intrin.h ${TOOLS_PATH}/${TOOLCHAIN}/lib/clang/*/include/{__wmmintrin_aes.h,__wmmintrin_pclmul.h,emmintrin.h,immintrin.h,mm_malloc.h}; do
+        filename=$(basename "$h")
+        if [ -e "${TOOLS_PATH}/host/include/${filename}" ]; then
+            echo "warning: ${filename} already exists"
+        fi
+        cp "$h" ${TOOLS_PATH}/host/include/
+    done
+    EXTRA_TARGET_CFLAGS="${EXTRA_TARGET_CFLAGS} -I${TOOLS_PATH}/host/include/"
+
+    # `qsort_r` is only available in musl 1.2.3+ but we use 1.2.2. The zstd source provides a
+    # fallback implementation, but they do not have a `configure`-style detection of whether
+    # `qsort_r` is actually available so we patch it to include a check for glibc.
+    patch -p1 <<EOF
+diff --git a/dictBuilder/cover.c b/dictBuilder/cover.c
+index 5e6e8bc..6ca72a1 100644
+--- a/dictBuilder/cover.c
++++ b/dictBuilder/cover.c
+@@ -241,7 +241,7 @@ typedef struct {
+   unsigned d;
+ } COVER_ctx_t;
+ 
+-#if !defined(_GNU_SOURCE) && !defined(__APPLE__) && !defined(_MSC_VER)
++#if !(defined(_GNU_SOURCE) && defined(__GLIBC__)) && !defined(__APPLE__) && !defined(_MSC_VER)
+ /* C90 only offers qsort() that needs a global context. */
+ static COVER_ctx_t *g_coverCtx = NULL;
+ #endif
+@@ -328,7 +328,7 @@ static void stableSort(COVER_ctx_t *ctx) {
+     qsort_r(ctx->suffix, ctx->suffixSize, sizeof(U32),
+             ctx,
+             (ctx->d <= 8 ? &COVER_strict_cmp8 : &COVER_strict_cmp));
+-#elif defined(_GNU_SOURCE)
++#elif defined(_GNU_SOURCE) && defined(__GLIBC__)
+     qsort_r(ctx->suffix, ctx->suffixSize, sizeof(U32),
+             (ctx->d <= 8 ? &COVER_strict_cmp8 : &COVER_strict_cmp),
+             ctx);
+EOF
+fi
+
+CFLAGS="${EXTRA_TARGET_CFLAGS} -fPIC" LDFLAGS="${EXTRA_TARGET_LDFLAGS}" make -j ${NUM_CPUS} libzstd.a
+make -j ${NUM_CPUS} install-static DESTDIR=${ROOT}/out
+make -j ${NUM_CPUS} install-includes DESTDIR=${ROOT}/out
+make -j ${NUM_CPUS} install-pc DESTDIR=${ROOT}/out
diff --git a/cpython-unix/build.py b/cpython-unix/build.py
index 01d39b2a..b35d1721 100755
--- a/cpython-unix/build.py
+++ b/cpython-unix/build.py
@@ -1163,6 +1163,7 @@ def main():
             "xtrans",
             "xz",
             "zlib",
+            "zstd",
         ):
             tools_path = "host" if action in ("m4", "patchelf") else "deps"
 
diff --git a/cpython-unix/extension-modules.yml b/cpython-unix/extension-modules.yml
index 3d69f049..4b834563 100644
--- a/cpython-unix/extension-modules.yml
+++ b/cpython-unix/extension-modules.yml
@@ -772,15 +772,14 @@ _xxtestfuzz:
     - _xxtestfuzz/fuzzer.c
 
 _zstd:
-  # Disable on all targets until we add a zstd library
-  disabled-targets:
-    - .*
   minimum-python-version: '3.14'
   sources:
     - _zstd/_zstdmodule.c
-    - _zstd/zdict.c
+    - _zstd/zstddict.c
     - _zstd/compressor.c
     - _zstd/decompressor.c
+  links:
+    - zstd
 
 _zoneinfo:
   minimum-python-version: "3.9"
diff --git a/cpython-unix/targets.yml b/cpython-unix/targets.yml
index 95ef58b2..33db80c8 100644
--- a/cpython-unix/targets.yml
+++ b/cpython-unix/targets.yml
@@ -108,6 +108,7 @@ aarch64-apple-darwin:
     - tk
     - uuid
     - xz
+    - zstd
   openssl_target: darwin64-arm64-cc
 
 aarch64-apple-ios:
@@ -151,6 +152,7 @@ aarch64-apple-ios:
     - openssl-3.0
     - sqlite
     - xz
+    - zstd
   openssl_target: ios64-cross
 
 aarch64-unknown-linux-gnu:
@@ -198,6 +200,7 @@ aarch64-unknown-linux-gnu:
     - xorgproto
     - xz
     - zlib
+    - zstd
   openssl_target: linux-aarch64
   # Blocked on:
   #   BOLT-ERROR: Cannot relax adr in non-simple function
@@ -245,6 +248,7 @@ arm64-apple-tvos:
     - openssl-3.0
     - sqlite
     - xz
+    - zstd
   openssl_target: todo
 
 armv7-unknown-linux-gnueabi:
@@ -286,6 +290,7 @@ armv7-unknown-linux-gnueabi:
     - xorgproto
     - xz
     - zlib
+    - zstd
   openssl_target: linux-armv4
 
 armv7-unknown-linux-gnueabihf:
@@ -327,6 +332,7 @@ armv7-unknown-linux-gnueabihf:
     - xorgproto
     - xz
     - zlib
+    - zstd
   openssl_target: linux-armv4
 
 mips-unknown-linux-gnu:
@@ -368,6 +374,7 @@ mips-unknown-linux-gnu:
     - xorgproto
     - xz
     - zlib
+    - zstd
   openssl_target: linux-mips32
 
 mipsel-unknown-linux-gnu:
@@ -409,6 +416,7 @@ mipsel-unknown-linux-gnu:
     - xorgproto
     - xz
     - zlib
+    - zstd
   openssl_target: linux-mips32
 
 ppc64le-unknown-linux-gnu:
@@ -450,6 +458,7 @@ ppc64le-unknown-linux-gnu:
     - xorgproto
     - xz
     - zlib
+    - zstd
   openssl_target: linux-ppc64le
 
 riscv64-unknown-linux-gnu:
@@ -491,6 +500,7 @@ riscv64-unknown-linux-gnu:
     - xorgproto
     - xz
     - zlib
+    - zstd
   openssl_target: linux64-riscv64
 
 s390x-unknown-linux-gnu:
@@ -532,6 +542,7 @@ s390x-unknown-linux-gnu:
     - xorgproto
     - xz
     - zlib
+    - zstd
   openssl_target: linux64-s390x
 
 thumb7k-apple-watchos:
@@ -574,6 +585,7 @@ thumb7k-apple-watchos:
     - openssl-3.0
     - sqlite
     - xz
+    - zstd
   openssl_target: todo
 
 # Intel macOS.
@@ -629,6 +641,7 @@ x86_64-apple-darwin:
     - tk
     - uuid
     - xz
+    - zstd
   openssl_target: darwin64-x86_64-cc
 
 x86_64-apple-ios:
@@ -672,6 +685,7 @@ x86_64-apple-ios:
     - openssl-3.0
     - sqlite
     - xz
+    - zstd
   openssl_target: darwin64-x86_64-cc
 
 x86_64-apple-tvos:
@@ -714,6 +728,7 @@ x86_64-apple-tvos:
     - openssl-3.0
     - sqlite
     - xz
+    - zstd
   openssl_target: todo
 
 x86_64-apple-watchos:
@@ -756,6 +771,7 @@ x86_64-apple-watchos:
     - openssl-3.0
     - sqlite
     - xz
+    - zstd
   openssl_target: todo
 
 x86_64-unknown-linux-gnu:
@@ -801,6 +817,7 @@ x86_64-unknown-linux-gnu:
     - xorgproto
     - xz
     - zlib
+    - zstd
   openssl_target: linux-x86_64
   bolt_capable: true
 
@@ -848,6 +865,7 @@ x86_64_v2-unknown-linux-gnu:
     - xorgproto
     - xz
     - zlib
+    - zstd
   openssl_target: linux-x86_64
   bolt_capable: true
 
@@ -895,6 +913,7 @@ x86_64_v3-unknown-linux-gnu:
     - xorgproto
     - xz
     - zlib
+    - zstd
   openssl_target: linux-x86_64
   bolt_capable: true
 
@@ -942,6 +961,7 @@ x86_64_v4-unknown-linux-gnu:
     - xorgproto
     - xz
     - zlib
+    - zstd
   openssl_target: linux-x86_64
   bolt_capable: true
 
@@ -987,6 +1007,7 @@ x86_64-unknown-linux-musl:
     - xorgproto
     - xz
     - zlib
+    - zstd
   openssl_target: linux-x86_64
 
 x86_64_v2-unknown-linux-musl:
@@ -1032,6 +1053,7 @@ x86_64_v2-unknown-linux-musl:
     - xorgproto
     - xz
     - zlib
+    - zstd
   openssl_target: linux-x86_64
 
 x86_64_v3-unknown-linux-musl:
@@ -1077,6 +1099,7 @@ x86_64_v3-unknown-linux-musl:
     - xorgproto
     - xz
     - zlib
+    - zstd
   openssl_target: linux-x86_64
 
 x86_64_v4-unknown-linux-musl:
@@ -1122,4 +1145,5 @@ x86_64_v4-unknown-linux-musl:
     - xorgproto
     - xz
     - zlib
+    - zstd
   openssl_target: linux-x86_64
diff --git a/src/validation.rs b/src/validation.rs
index 9084754b..5ab71708 100644
--- a/src/validation.rs
+++ b/src/validation.rs
@@ -778,6 +778,7 @@ const GLOBAL_EXTENSIONS_PYTHON_3_14: &[&str] = &[
     "_zoneinfo",
     "_hmac",
     "_types",
+    "_zstd",
 ];
 
 const GLOBAL_EXTENSIONS_MACOS: &[&str] = &["_scproxy"];
@@ -813,8 +814,7 @@ const GLOBAL_EXTENSIONS_WINDOWS: &[&str] = &[
     "winsound",
 ];
 
-// TODO(zanieb): Move `_zstd` to non-Windows specific once we add support on Unix.
-const GLOBAL_EXTENSIONS_WINDOWS_3_14: &[&str] = &["_wmi", "_zstd"];
+const GLOBAL_EXTENSIONS_WINDOWS_3_14: &[&str] = &["_wmi"];
 
 const GLOBAL_EXTENSIONS_WINDOWS_PRE_3_13: &[&str] = &["_msi"];
 

From ec8ee638adb2f1c579a0b4f7a87e73a2949cb204 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Sun, 6 Jul 2025 11:06:27 -0500
Subject: [PATCH 131/157] Bump urllib3 from 2.4.0 to 2.5.0 (#665)

[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=urllib3&package-manager=pip&previous-version=2.4.0&new-version=2.5.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/astral-sh/python-build-standalone/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
 requirements.win.txt | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/requirements.win.txt b/requirements.win.txt
index d37a96ff..b9b9a814 100644
--- a/requirements.win.txt
+++ b/requirements.win.txt
@@ -431,9 +431,9 @@ typing-extensions==4.13.2 \
     --hash=sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c \
     --hash=sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef
     # via -r requirements.in
-urllib3==2.4.0 \
-    --hash=sha256:414bc6535b787febd7567804cc015fee39daab8ad86268f1310a9250697de466 \
-    --hash=sha256:4e16665048960a0900c702d4a66415956a584919c03361cac9f1df5c5dd7e813
+urllib3==2.5.0 \
+    --hash=sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760 \
+    --hash=sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc
     # via
     #   docker
     #   requests

From 9b796d4a5ca2af49761c8e5156fc110b9a70fb53 Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Mon, 7 Jul 2025 15:19:14 -0500
Subject: [PATCH 132/157] Bump SQLite to `3.49.1.0` (#667)

Closes https://github.com/astral-sh/python-build-standalone/issues/666
---
 cpython-unix/build-sqlite.sh | 15 +++++++++++----
 pythonbuild/downloads.py     | 10 +++++-----
 src/verify_distribution.py   |  2 +-
 3 files changed, 17 insertions(+), 10 deletions(-)

diff --git a/cpython-unix/build-sqlite.sh b/cpython-unix/build-sqlite.sh
index b045bb88..e01e3077 100755
--- a/cpython-unix/build-sqlite.sh
+++ b/cpython-unix/build-sqlite.sh
@@ -14,7 +14,7 @@ pushd sqlite-autoconf-${SQLITE_VERSION}
 
 
 CONFIGURE_FLAGS="--build=${BUILD_TRIPLE} --host=${TARGET_TRIPLE}"
-CONFIGURE_FLAGS="${CONFIGURE_FLAGS} --prefix /tools/deps --disable-shared"
+CONFIGURE_FLAGS="${CONFIGURE_FLAGS} --prefix=/tools/deps --disable-shared"
 
 if [ "${TARGET_TRIPLE}" = "aarch64-apple-ios" ]; then
     CONFIGURE_FLAGS="${CONFIGURE_FLAGS} ac_cv_search_system=no"
@@ -22,7 +22,14 @@ elif [ "${TARGET_TRIPLE}" = "x86_64-apple-ios" ]; then
     CONFIGURE_FLAGS="${CONFIGURE_FLAGS} ac_cv_search_system=no"
 fi
 
-CFLAGS="${EXTRA_TARGET_CFLAGS} -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_FTS3_PARENTHESIS -DSQLITE_ENABLE_FTS3_TOKENIZER -fPIC" CPPFLAGS="${EXTRA_TARGET_CFLAGS} -fPIC" LDFLAGS="${EXTRA_TARGET_LDFLAGS}" ./configure ${CONFIGURE_FLAGS}
+# The SQLite autosetup looks for the C++ compiler if the variable is set and will fail if it's not
+# found, even if it's not needed. We don't actually have a C++ compiler in some builds, so ensure
+# it's not looked for.
+unset CXX
 
-make -j ${NUM_CPUS}
-make -j ${NUM_CPUS} install DESTDIR=${ROOT}/out
+CC_FOR_BUILD="${HOST_CC}" CFLAGS="${EXTRA_TARGET_CFLAGS} -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_FTS3_PARENTHESIS -DSQLITE_ENABLE_FTS3_TOKENIZER -fPIC" CPPFLAGS="${EXTRA_TARGET_CFLAGS} -fPIC" LDFLAGS="${EXTRA_TARGET_LDFLAGS}" ./configure ${CONFIGURE_FLAGS}
+
+make -j ${NUM_CPUS} libsqlite3.a
+make install-lib DESTDIR=${ROOT}/out
+make install-headers DESTDIR=${ROOT}/out
+make install-pc DESTDIR=${ROOT}/out
diff --git a/pythonbuild/downloads.py b/pythonbuild/downloads.py
index 24a9917e..a208ce56 100644
--- a/pythonbuild/downloads.py
+++ b/pythonbuild/downloads.py
@@ -295,11 +295,11 @@
     },
     # Remember to update verify_distribution.py when version changed.
     "sqlite": {
-        "url": "https://www.sqlite.org/2024/sqlite-autoconf-3470100.tar.gz",
-        "size": 3328564,
-        "sha256": "416a6f45bf2cacd494b208fdee1beda509abda951d5f47bc4f2792126f01b452",
-        "version": "3470100",
-        "actual_version": "3.47.1.0",
+        "url": "https://www.sqlite.org/2025/sqlite-autoconf-3490100.tar.gz",
+        "size": 3226385,
+        "sha256": "106642d8ccb36c5f7323b64e4152e9b719f7c0215acf5bfeac3d5e7f97b59254",
+        "version": "3490100",
+        "actual_version": "3.49.1.0",
         "library_names": ["sqlite3"],
         "licenses": [],
         "license_file": "LICENSE.sqlite.txt",
diff --git a/src/verify_distribution.py b/src/verify_distribution.py
index 2131d7aa..1ac2381f 100644
--- a/src/verify_distribution.py
+++ b/src/verify_distribution.py
@@ -114,7 +114,7 @@ def test_hashlib(self):
     def test_sqlite(self):
         import sqlite3
 
-        self.assertEqual(sqlite3.sqlite_version_info, (3, 47, 1))
+        self.assertEqual(sqlite3.sqlite_version_info, (3, 49, 1))
 
         # Optional SQLite3 features are enabled.
         conn = sqlite3.connect(":memory:")

From 625ad3072a441c1dec616b23cc0d8ea95db04e79 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 7 Jul 2025 15:19:24 -0500
Subject: [PATCH 133/157] Bump the python group across 1 directory with 6
 updates (#688)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Bumps the python group with 6 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [certifi](https://github.com/certifi/python-certifi) | `2025.4.26` |
`2025.6.15` |
| [pyyaml](https://github.com/yaml/pyyaml) | `6.0.1` | `6.0.2` |
| [rpds-py](https://github.com/crate-py/rpds) | `0.25.1` | `0.26.0` |
| [typing-extensions](https://github.com/python/typing_extensions) |
`4.13.2` | `4.14.1` |
| [mypy](https://github.com/python/mypy) | `1.16.0` | `1.16.1` |
| [ruff](https://github.com/astral-sh/ruff) | `0.11.13` | `0.12.2` |


Updates `certifi` from 2025.4.26 to 2025.6.15
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/certifi/python-certifi/commit/e767d5938eddddf804216cec93a55c85129c5f2d"><code>e767d59</code></a>
2025.06.15 (<a
href="https://redirect.github.com/certifi/python-certifi/issues/357">#357</a>)</li>
<li><a
href="https://github.com/certifi/python-certifi/commit/3e7076557d66b598fcca462e422dc988f09a6802"><code>3e70765</code></a>
Bump actions/setup-python from 5.5.0 to 5.6.0</li>
<li><a
href="https://github.com/certifi/python-certifi/commit/9afd2ff407b8a0638988c952a6636b8dd623af7c"><code>9afd2ff</code></a>
Bump actions/download-artifact from 4.2.1 to 4.3.0</li>
<li><a
href="https://github.com/certifi/python-certifi/commit/d7c816cbc9cf621b3ddc8cd7fa7eda3f36982620"><code>d7c816c</code></a>
remove code that's no longer required that 3.7 is our minimum (<a
href="https://redirect.github.com/certifi/python-certifi/issues/351">#351</a>)</li>
<li><a
href="https://github.com/certifi/python-certifi/commit/189961379209973abd0dd6304297f03e2359e1b9"><code>1899613</code></a>
Declare setuptools as the build backend in pyproject.toml (<a
href="https://redirect.github.com/certifi/python-certifi/issues/350">#350</a>)</li>
<li><a
href="https://github.com/certifi/python-certifi/commit/c8741423d67e1025c0bdad5225ded05cf962f207"><code>c874142</code></a>
update CI for ubuntu 20.04 deprecation (<a
href="https://redirect.github.com/certifi/python-certifi/issues/348">#348</a>)</li>
<li>See full diff in <a
href="https://github.com/certifi/python-certifi/compare/2025.04.26...2025.06.15">compare
view</a></li>
</ul>
</details>
<br />

Updates `pyyaml` from 6.0.1 to 6.0.2
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/yaml/pyyaml/releases">pyyaml's
releases</a>.</em></p>
<blockquote>
<h2>6.0.2</h2>
<h2>What's Changed</h2>
<ul>
<li>Support for Cython 3.x and Python 3.13.</li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/yaml/pyyaml/compare/6.0.1...6.0.2">https://github.com/yaml/pyyaml/compare/6.0.1...6.0.2</a></p>
<h2>6.0.2rc1</h2>
<ul>
<li>Support for extension build with Cython 3.x</li>
<li>Support for Python 3.13</li>
<li>Added PyPI wheels for musllinux on aarch64</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/yaml/pyyaml/blob/main/CHANGES">pyyaml's
changelog</a>.</em></p>
<blockquote>
<p>6.0.2 (2024-08-06)</p>
<ul>
<li><a
href="https://redirect.github.com/yaml/pyyaml/pull/808">yaml/pyyaml#808</a>
-- Support for Cython 3.x and Python 3.13</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/yaml/pyyaml/commit/41309b0bcb4559edb1d691d47199035ef539d785"><code>41309b0</code></a>
Release 6.0.2 (<a
href="https://redirect.github.com/yaml/pyyaml/issues/819">#819</a>)</li>
<li><a
href="https://github.com/yaml/pyyaml/commit/dd9f0e1236775dcce682c91823e009556ce2a271"><code>dd9f0e1</code></a>
6.0.2rc1 (<a
href="https://redirect.github.com/yaml/pyyaml/issues/809">#809</a>)</li>
<li><a
href="https://github.com/yaml/pyyaml/commit/f5527a26d518b3e9c66f9211e0af00c83f09a97e"><code>f5527a2</code></a>
disable CI trigger on PR edits</li>
<li><a
href="https://github.com/yaml/pyyaml/commit/b4d80a742142004490d2da7691d534923820b81c"><code>b4d80a7</code></a>
Python 3.12 + musllinux_1_1_x86_64 wheel support</li>
<li>See full diff in <a
href="https://github.com/yaml/pyyaml/compare/6.0.1...6.0.2">compare
view</a></li>
</ul>
</details>
<br />

Updates `rpds-py` from 0.25.1 to 0.26.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/crate-py/rpds/releases">rpds-py's
releases</a>.</em></p>
<blockquote>
<h2>v0.26.0</h2>
<!-- raw HTML omitted -->
<h2>What's Changed</h2>
<ul>
<li>Build CPython 3.14 wheels by <a
href="https://github.com/edgarrmondragon"><code>@​edgarrmondragon</code></a>
in <a
href="https://redirect.github.com/crate-py/rpds/pull/134">crate-py/rpds#134</a></li>
<li>Require maturin&gt;=1.9.0 to ensure support for PEP 639 by <a
href="https://github.com/edgarrmondragon"><code>@​edgarrmondragon</code></a>
in <a
href="https://redirect.github.com/crate-py/rpds/pull/146">crate-py/rpds#146</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/crate-py/rpds/compare/v0.25.1...v0.26.0">https://github.com/crate-py/rpds/compare/v0.25.1...v0.26.0</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/crate-py/rpds/commit/ff9278f7e718760bb052cd4c130bbdeca8d27b20"><code>ff9278f</code></a>
Tag a release.</li>
<li><a
href="https://github.com/crate-py/rpds/commit/d2f69ef82b23135fedc8b42bda743f9c53af607d"><code>d2f69ef</code></a>
Update requirements.</li>
<li><a
href="https://github.com/crate-py/rpds/commit/58ee607148940533f212893ac886f7e82b3c35bb"><code>58ee607</code></a>
Merge pull request <a
href="https://redirect.github.com/crate-py/rpds/issues/146">#146</a>
from edgarrmondragon/136-require-maturin-1.9-pep639</li>
<li><a
href="https://github.com/crate-py/rpds/commit/5433ab6aa936aa835d97bb204fd73d289525e331"><code>5433ab6</code></a>
Require maturin&gt;=1.9.0 to ensure support for PEP 639</li>
<li><a
href="https://github.com/crate-py/rpds/commit/7557e538fb8d14c4b534133b9ac48f3940e787b4"><code>7557e53</code></a>
Merge pull request <a
href="https://redirect.github.com/crate-py/rpds/issues/144">#144</a>
from crate-py/dependabot/github_actions/github/codeql...</li>
<li><a
href="https://github.com/crate-py/rpds/commit/d0963ae1a2b0bcc61702adb3249ae3b73bc32dda"><code>d0963ae</code></a>
Merge pull request <a
href="https://redirect.github.com/crate-py/rpds/issues/145">#145</a>
from crate-py/dependabot/github_actions/astral-sh/set...</li>
<li><a
href="https://github.com/crate-py/rpds/commit/513ec227cba30c93b4df9c820b4d54e7e6dcb318"><code>513ec22</code></a>
Bump astral-sh/setup-uv from 6.3.0 to 6.3.1</li>
<li><a
href="https://github.com/crate-py/rpds/commit/cbb4277105e08df8248c7e64ab99d5a51a1b4568"><code>cbb4277</code></a>
Bump github/codeql-action from 3.29.0 to 3.29.2</li>
<li><a
href="https://github.com/crate-py/rpds/commit/25123e9a2fed652d68ec490ac0481e543f3c77fd"><code>25123e9</code></a>
Merge pull request <a
href="https://redirect.github.com/crate-py/rpds/issues/143">#143</a>
from crate-py/dependabot/github_actions/PyO3/maturin-...</li>
<li><a
href="https://github.com/crate-py/rpds/commit/7a59bb7f1848a1ac0793bf77066a1381d33de20f"><code>7a59bb7</code></a>
Merge pull request <a
href="https://redirect.github.com/crate-py/rpds/issues/142">#142</a>
from crate-py/dependabot/github_actions/astral-sh/set...</li>
<li>Additional commits viewable in <a
href="https://github.com/crate-py/rpds/compare/v0.25.1...v0.26.0">compare
view</a></li>
</ul>
</details>
<br />

Updates `typing-extensions` from 4.13.2 to 4.14.1
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/python/typing_extensions/releases">typing-extensions's
releases</a>.</em></p>
<blockquote>
<h2>4.14.1</h2>
<h1>Release 4.14.1 (July 4, 2025)</h1>
<ul>
<li>Fix usage of <code>typing_extensions.TypedDict</code> nested inside
other types
(e.g., <code>typing.Type[typing_extensions.TypedDict]</code>). This is
not allowed by the
type system but worked on older versions, so we maintain support.</li>
</ul>
<h2>4.14.0</h2>
<p>This release adds several new features, including experimental
support for inline typed dictionaries (<a
href="https://peps.python.org/pep-0764/">PEP 764</a>) and sentinels (<a
href="https://peps.python.org/pep-0661/">PEP 661</a>), and support for
changes in Python 3.14. In addition, Python 3.8 is no longer
supported.</p>
<p>Changes since 4.14.0rc1:</p>
<ul>
<li>Remove <code>__or__</code> and <code>__ror__</code> methods from
<code>typing_extensions.Sentinel</code>
on Python versions &lt;3.10. PEP 604 was introduced in Python 3.10, and
<code>typing_extensions</code> does not generally attempt to backport
PEP-604 methods
to prior versions.</li>
<li>Further update <code>typing_extensions.evaluate_forward_ref</code>
with changes in Python 3.14.</li>
</ul>
<p>Changes included in 4.14.0rc1:</p>
<ul>
<li>Drop support for Python 3.8 (including PyPy-3.8). Patch by <a
href="https://github.com/Viicos">Victorien Plot</a>.</li>
<li>Do not attempt to re-export names that have been removed from
<code>typing</code>,
anticipating the removal of <code>typing.no_type_check_decorator</code>
in Python 3.15.
Patch by Jelle Zijlstra.</li>
<li>Update <code>typing_extensions.Format</code>,
<code>typing_extensions.evaluate_forward_ref</code>, and
<code>typing_extensions.TypedDict</code> to align
with changes in Python 3.14. Patches by Jelle Zijlstra.</li>
<li>Fix tests for Python 3.14 and 3.15. Patches by Jelle Zijlstra.</li>
</ul>
<p>New features:</p>
<ul>
<li>Add support for inline typed dictionaries (<a
href="https://peps.python.org/pep-0764/">PEP 764</a>).
Patch by <a href="https://github.com/Viicos">Victorien Plot</a>.</li>
<li>Add <code>typing_extensions.Reader</code> and
<code>typing_extensions.Writer</code>. Patch by
Sebastian Rittau.</li>
<li>Add support for sentinels (<a
href="https://peps.python.org/pep-0661/">PEP 661</a>). Patch by
<a href="https://github.com/Viicos">Victorien Plot</a>.</li>
</ul>
<h2>4.14.0rc1</h2>
<p>Major changes:</p>
<ul>
<li>Drop support for Python 3.8 (including PyPy-3.8). Patch by <a
href="https://github.com/Viicos">Victorien Plot</a>.</li>
<li>Do not attempt to re-export names that have been removed from
<code>typing</code>,
anticipating the removal of <code>typing.no_type_check_decorator</code>
in Python 3.15.
Patch by Jelle Zijlstra.</li>
<li>Update <code>typing_extensions.Format</code>,
<code>typing_extensions.evaluate_forward_ref</code>, and
<code>typing_extensions.TypedDict</code> to align
with changes in Python 3.14. Patches by Jelle Zijlstra.</li>
<li>Fix tests for Python 3.14 and 3.15. Patches by Jelle Zijlstra.</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/python/typing_extensions/blob/main/CHANGELOG.md">typing-extensions's
changelog</a>.</em></p>
<blockquote>
<h1>Release 4.14.1 (July 4, 2025)</h1>
<ul>
<li>Fix usage of <code>typing_extensions.TypedDict</code> nested inside
other types
(e.g., <code>typing.Type[typing_extensions.TypedDict]</code>). This is
not allowed by the
type system but worked on older versions, so we maintain support.</li>
</ul>
<h1>Release 4.14.0 (June 2, 2025)</h1>
<p>Changes since 4.14.0rc1:</p>
<ul>
<li>Remove <code>__or__</code> and <code>__ror__</code> methods from
<code>typing_extensions.Sentinel</code>
on Python versions &lt;3.10. PEP 604 was introduced in Python 3.10, and
<code>typing_extensions</code> does not generally attempt to backport
PEP-604 methods
to prior versions.</li>
<li>Further update <code>typing_extensions.evaluate_forward_ref</code>
with changes in Python 3.14.</li>
</ul>
<h1>Release 4.14.0rc1 (May 24, 2025)</h1>
<ul>
<li>Drop support for Python 3.8 (including PyPy-3.8). Patch by <a
href="https://github.com/Viicos">Victorien Plot</a>.</li>
<li>Do not attempt to re-export names that have been removed from
<code>typing</code>,
anticipating the removal of <code>typing.no_type_check_decorator</code>
in Python 3.15.
Patch by Jelle Zijlstra.</li>
<li>Update <code>typing_extensions.Format</code>,
<code>typing_extensions.evaluate_forward_ref</code>, and
<code>typing_extensions.TypedDict</code> to align
with changes in Python 3.14. Patches by Jelle Zijlstra.</li>
<li>Fix tests for Python 3.14 and 3.15. Patches by Jelle Zijlstra.</li>
</ul>
<p>New features:</p>
<ul>
<li>Add support for inline typed dictionaries (<a
href="https://peps.python.org/pep-0764/">PEP 764</a>).
Patch by <a href="https://github.com/Viicos">Victorien Plot</a>.</li>
<li>Add <code>typing_extensions.Reader</code> and
<code>typing_extensions.Writer</code>. Patch by
Sebastian Rittau.</li>
<li>Add support for sentinels (<a
href="https://peps.python.org/pep-0661/">PEP 661</a>). Patch by
<a href="https://github.com/Viicos">Victorien Plot</a>.</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/python/typing_extensions/commit/42027aba3558c9d9133a90bca17f6fecaecc48d8"><code>42027ab</code></a>
Prepare release 4.14.1 (<a
href="https://redirect.github.com/python/typing_extensions/issues/620">#620</a>)</li>
<li><a
href="https://github.com/python/typing_extensions/commit/59d2c20858ac527516ebad5a89c05af514dac94a"><code>59d2c20</code></a>
Fix off by one in pickle protocol tests (<a
href="https://redirect.github.com/python/typing_extensions/issues/618">#618</a>)</li>
<li><a
href="https://github.com/python/typing_extensions/commit/40e22ebb2ca5747eaa9405b152c43a294ac3af37"><code>40e22eb</code></a>
Do not use slots for <code>_TypedDictSpecialForm</code> (<a
href="https://redirect.github.com/python/typing_extensions/issues/616">#616</a>)</li>
<li><a
href="https://github.com/python/typing_extensions/commit/d17c456d367e88adee4a4e3bef48f81f7e2df473"><code>d17c456</code></a>
allow TypedDict as a type argument (<a
href="https://redirect.github.com/python/typing_extensions/issues/614">#614</a>)</li>
<li><a
href="https://github.com/python/typing_extensions/commit/b07d24525615ba9377e47aaf5a26650a2517b2c4"><code>b07d245</code></a>
Prepare release 4.14.0 (<a
href="https://redirect.github.com/python/typing_extensions/issues/612">#612</a>)</li>
<li><a
href="https://github.com/python/typing_extensions/commit/fcf5265b3040337db1cfd6b786648a8ed0aeb0bf"><code>fcf5265</code></a>
Backport evaluate_forward_ref() changes (<a
href="https://redirect.github.com/python/typing_extensions/issues/611">#611</a>)</li>
<li><a
href="https://github.com/python/typing_extensions/commit/fadc1edbcfd942074007875007870c1df6acd4d0"><code>fadc1ed</code></a>
Remove PEP-604 methods from <code>Sentinel</code> on Python &lt;3.10 (<a
href="https://redirect.github.com/python/typing_extensions/issues/605">#605</a>)</li>
<li><a
href="https://github.com/python/typing_extensions/commit/44de568f73a93f29e52c2fc2d5f149305a4a3bae"><code>44de568</code></a>
Add 3.14 to project classifiers and tox.ini (<a
href="https://redirect.github.com/python/typing_extensions/issues/604">#604</a>)</li>
<li><a
href="https://github.com/python/typing_extensions/commit/36cc47605804318bf40ee26d765de2070741c25c"><code>36cc476</code></a>
Prepare release 4.14.0rc1 (<a
href="https://redirect.github.com/python/typing_extensions/issues/603">#603</a>)</li>
<li><a
href="https://github.com/python/typing_extensions/commit/ec1876c65000ac86faade29552245178918a7a69"><code>ec1876c</code></a>
More fixes for 3.14 and 3.15 (<a
href="https://redirect.github.com/python/typing_extensions/issues/602">#602</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/python/typing_extensions/compare/4.13.2...4.14.1">compare
view</a></li>
</ul>
</details>
<br />

Updates `mypy` from 1.16.0 to 1.16.1
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/python/mypy/commit/68b8fa097d080c92d30a429bc74de8acd56caf85"><code>68b8fa0</code></a>
Bump version to 1.16.1</li>
<li><a
href="https://github.com/python/mypy/commit/e253eded9c887630f3f5404c4b9f73f13570476a"><code>e253ede</code></a>
Single underscore is not a sunder (<a
href="https://redirect.github.com/python/mypy/issues/19273">#19273</a>)</li>
<li><a
href="https://github.com/python/mypy/commit/9fb5ff66c51bd971d7a6b1260cc0ec9f1b82cc06"><code>9fb5ff6</code></a>
Fix properties with setters after deleters (<a
href="https://redirect.github.com/python/mypy/issues/19248">#19248</a>)</li>
<li><a
href="https://github.com/python/mypy/commit/c20fd7838338cd65d6c7c6e252eda85996cfc98e"><code>c20fd78</code></a>
Handle assignment of bound methods in class bodies (<a
href="https://redirect.github.com/python/mypy/issues/19233">#19233</a>)</li>
<li><a
href="https://github.com/python/mypy/commit/c86480ce51e4bb6db21f4b3f0b3ec8833aafc8ce"><code>c86480c</code></a>
Tighten metaclass <strong>call</strong> handling in protocols (<a
href="https://redirect.github.com/python/mypy/issues/19191">#19191</a>)</li>
<li><a
href="https://github.com/python/mypy/commit/cb3c6ec6a7aaa96a0e26768a946ac63ea14115f2"><code>cb3c6ec</code></a>
Fix crash on partial type used as context (<a
href="https://redirect.github.com/python/mypy/issues/19216">#19216</a>)</li>
<li><a
href="https://github.com/python/mypy/commit/c39f5e73c47182e51c5d8d488f7cc7301257c974"><code>c39f5e7</code></a>
[mypyc] Fixing condition for handling user-defined <strong>del</strong>
(<a
href="https://redirect.github.com/python/mypy/issues/19188">#19188</a>)</li>
<li><a
href="https://github.com/python/mypy/commit/0a4f28431faa18e59d35bc269cb0ea6c00810653"><code>0a4f284</code></a>
Fix crash on invalid property inside its own body (<a
href="https://redirect.github.com/python/mypy/issues/19208">#19208</a>)</li>
<li><a
href="https://github.com/python/mypy/commit/9b079f6592740a51c0e629728eeb0324ad85126f"><code>9b079f6</code></a>
Bump version to 1.16.1+dev</li>
<li>See full diff in <a
href="https://github.com/python/mypy/compare/v1.16.0...v1.16.1">compare
view</a></li>
</ul>
</details>
<br />

Updates `ruff` from 0.11.13 to 0.12.2
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/astral-sh/ruff/releases">ruff's
releases</a>.</em></p>
<blockquote>
<h2>0.12.2</h2>
<h2>Release Notes</h2>
<h3>Preview features</h3>
<ul>
<li>[<code>flake8-pyi</code>] Expand <code>Optional[A]</code> to <code>A
| None</code> (<code>PYI016</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/18572">#18572</a>)</li>
<li>[<code>pyupgrade</code>] Mark <code>UP008</code> fix safe if no
comments are in range (<a
href="https://redirect.github.com/astral-sh/ruff/pull/18683">#18683</a>)</li>
</ul>
<h3>Bug fixes</h3>
<ul>
<li>[<code>flake8-comprehensions</code>] Fix <code>C420</code> to
prepend whitespace when needed (<a
href="https://redirect.github.com/astral-sh/ruff/pull/18616">#18616</a>)</li>
<li>[<code>perflint</code>] Fix <code>PERF403</code> panic on attribute
or subscription loop variable (<a
href="https://redirect.github.com/astral-sh/ruff/pull/19042">#19042</a>)</li>
<li>[<code>pydocstyle</code>] Fix <code>D413</code> infinite loop for
parenthesized docstring (<a
href="https://redirect.github.com/astral-sh/ruff/pull/18930">#18930</a>)</li>
<li>[<code>pylint</code>] Fix <code>PLW0108</code> autofix introducing a
syntax error when the lambda's body contains an assignment expression
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/18678">#18678</a>)</li>
<li>[<code>refurb</code>] Fix false positive on empty tuples
(<code>FURB168</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/19058">#19058</a>)</li>
<li>[<code>ruff</code>] Allow more <code>field</code> calls from
<code>attrs</code> (<code>RUF009</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/19021">#19021</a>)</li>
<li>[<code>ruff</code>] Fix syntax error introduced for an empty string
followed by a u-prefixed string (<code>UP025</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/18899">#18899</a>)</li>
</ul>
<h3>Rule changes</h3>
<ul>
<li>[<code>flake8-executable</code>] Allow <code>uvx</code> in shebang
line (<code>EXE003</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/18967">#18967</a>)</li>
<li>[<code>pandas</code>] Avoid flagging <code>PD002</code> if
<code>pandas</code> is not imported (<a
href="https://redirect.github.com/astral-sh/ruff/pull/18963">#18963</a>)</li>
<li>[<code>pyupgrade</code>] Avoid PEP-604 unions with
<code>typing.NamedTuple</code> (<code>UP007</code>, <code>UP045</code>)
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/18682">#18682</a>)</li>
</ul>
<h3>Documentation</h3>
<ul>
<li>Document link between <code>import-outside-top-level
(PLC0415)</code> and
<code>lint.flake8-tidy-imports.banned-module-level-imports</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/18733">#18733</a>)</li>
<li>Fix description of the <code>format.skip-magic-trailing-comma</code>
example (<a
href="https://redirect.github.com/astral-sh/ruff/pull/19095">#19095</a>)</li>
<li>[<code>airflow</code>] Make <code>AIR302</code> example error
out-of-the-box (<a
href="https://redirect.github.com/astral-sh/ruff/pull/18988">#18988</a>)</li>
<li>[<code>airflow</code>] Make <code>AIR312</code> example error
out-of-the-box (<a
href="https://redirect.github.com/astral-sh/ruff/pull/18989">#18989</a>)</li>
<li>[<code>flake8-annotations</code>] Make <code>ANN401</code> example
error out-of-the-box (<a
href="https://redirect.github.com/astral-sh/ruff/pull/18974">#18974</a>)</li>
<li>[<code>flake8-async</code>] Make <code>ASYNC100</code> example error
out-of-the-box (<a
href="https://redirect.github.com/astral-sh/ruff/pull/18993">#18993</a>)</li>
<li>[<code>flake8-async</code>] Make <code>ASYNC105</code> example error
out-of-the-box (<a
href="https://redirect.github.com/astral-sh/ruff/pull/19002">#19002</a>)</li>
<li>[<code>flake8-async</code>] Make <code>ASYNC110</code> example error
out-of-the-box (<a
href="https://redirect.github.com/astral-sh/ruff/pull/18975">#18975</a>)</li>
<li>[<code>flake8-async</code>] Make <code>ASYNC210</code> example error
out-of-the-box (<a
href="https://redirect.github.com/astral-sh/ruff/pull/18977">#18977</a>)</li>
<li>[<code>flake8-async</code>] Make <code>ASYNC220</code>,
<code>ASYNC221</code>, and <code>ASYNC222</code> examples error
out-of-the-box (<a
href="https://redirect.github.com/astral-sh/ruff/pull/18978">#18978</a>)</li>
<li>[<code>flake8-async</code>] Make <code>ASYNC251</code> example error
out-of-the-box (<a
href="https://redirect.github.com/astral-sh/ruff/pull/18990">#18990</a>)</li>
<li>[<code>flake8-bandit</code>] Make <code>S201</code> example error
out-of-the-box (<a
href="https://redirect.github.com/astral-sh/ruff/pull/19017">#19017</a>)</li>
<li>[<code>flake8-bandit</code>] Make <code>S604</code> and
<code>S609</code> examples error out-of-the-box (<a
href="https://redirect.github.com/astral-sh/ruff/pull/19049">#19049</a>)</li>
<li>[<code>flake8-bugbear</code>] Make <code>B028</code> example error
out-of-the-box (<a
href="https://redirect.github.com/astral-sh/ruff/pull/19054">#19054</a>)</li>
<li>[<code>flake8-bugbear</code>] Make <code>B911</code> example error
out-of-the-box (<a
href="https://redirect.github.com/astral-sh/ruff/pull/19051">#19051</a>)</li>
<li>[<code>flake8-datetimez</code>] Make <code>DTZ011</code> example
error out-of-the-box (<a
href="https://redirect.github.com/astral-sh/ruff/pull/19055">#19055</a>)</li>
<li>[<code>flake8-datetimez</code>] Make <code>DTZ901</code> example
error out-of-the-box (<a
href="https://redirect.github.com/astral-sh/ruff/pull/19056">#19056</a>)</li>
<li>[<code>flake8-pyi</code>] Make <code>PYI032</code> example error
out-of-the-box (<a
href="https://redirect.github.com/astral-sh/ruff/pull/19061">#19061</a>)</li>
<li>[<code>flake8-pyi</code>] Make example error out-of-the-box
(<code>PYI014</code>, <code>PYI015</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/19097">#19097</a>)</li>
<li>[<code>flake8-pyi</code>] Make example error out-of-the-box
(<code>PYI042</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/19101">#19101</a>)</li>
<li>[<code>flake8-pyi</code>] Make example error out-of-the-box
(<code>PYI059</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/19080">#19080</a>)</li>
<li>[<code>flake8-pyi</code>] Make example error out-of-the-box
(<code>PYI062</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/19079">#19079</a>)</li>
<li>[<code>flake8-pytest-style</code>] Make example error out-of-the-box
(<code>PT023</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/19104">#19104</a>)</li>
<li>[<code>flake8-pytest-style</code>] Make example error out-of-the-box
(<code>PT030</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/19105">#19105</a>)</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md">ruff's
changelog</a>.</em></p>
<blockquote>
<h2>0.12.2</h2>
<h3>Preview features</h3>
<ul>
<li>[<code>flake8-pyi</code>] Expand <code>Optional[A]</code> to <code>A
| None</code> (<code>PYI016</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/18572">#18572</a>)</li>
<li>[<code>pyupgrade</code>] Mark <code>UP008</code> fix safe if no
comments are in range (<a
href="https://redirect.github.com/astral-sh/ruff/pull/18683">#18683</a>)</li>
</ul>
<h3>Bug fixes</h3>
<ul>
<li>[<code>flake8-comprehensions</code>] Fix <code>C420</code> to
prepend whitespace when needed (<a
href="https://redirect.github.com/astral-sh/ruff/pull/18616">#18616</a>)</li>
<li>[<code>perflint</code>] Fix <code>PERF403</code> panic on attribute
or subscription loop variable (<a
href="https://redirect.github.com/astral-sh/ruff/pull/19042">#19042</a>)</li>
<li>[<code>pydocstyle</code>] Fix <code>D413</code> infinite loop for
parenthesized docstring (<a
href="https://redirect.github.com/astral-sh/ruff/pull/18930">#18930</a>)</li>
<li>[<code>pylint</code>] Fix <code>PLW0108</code> autofix introducing a
syntax error when the lambda's body contains an assignment expression
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/18678">#18678</a>)</li>
<li>[<code>refurb</code>] Fix false positive on empty tuples
(<code>FURB168</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/19058">#19058</a>)</li>
<li>[<code>ruff</code>] Allow more <code>field</code> calls from
<code>attrs</code> (<code>RUF009</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/19021">#19021</a>)</li>
<li>[<code>ruff</code>] Fix syntax error introduced for an empty string
followed by a u-prefixed string (<code>UP025</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/18899">#18899</a>)</li>
</ul>
<h3>Rule changes</h3>
<ul>
<li>[<code>flake8-executable</code>] Allow <code>uvx</code> in shebang
line (<code>EXE003</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/18967">#18967</a>)</li>
<li>[<code>pandas</code>] Avoid flagging <code>PD002</code> if
<code>pandas</code> is not imported (<a
href="https://redirect.github.com/astral-sh/ruff/pull/18963">#18963</a>)</li>
<li>[<code>pyupgrade</code>] Avoid PEP-604 unions with
<code>typing.NamedTuple</code> (<code>UP007</code>, <code>UP045</code>)
(<a
href="https://redirect.github.com/astral-sh/ruff/pull/18682">#18682</a>)</li>
</ul>
<h3>Documentation</h3>
<ul>
<li>Document link between <code>import-outside-top-level
(PLC0415)</code> and
<code>lint.flake8-tidy-imports.banned-module-level-imports</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/18733">#18733</a>)</li>
<li>Fix description of the <code>format.skip-magic-trailing-comma</code>
example (<a
href="https://redirect.github.com/astral-sh/ruff/pull/19095">#19095</a>)</li>
<li>[<code>airflow</code>] Make <code>AIR302</code> example error
out-of-the-box (<a
href="https://redirect.github.com/astral-sh/ruff/pull/18988">#18988</a>)</li>
<li>[<code>airflow</code>] Make <code>AIR312</code> example error
out-of-the-box (<a
href="https://redirect.github.com/astral-sh/ruff/pull/18989">#18989</a>)</li>
<li>[<code>flake8-annotations</code>] Make <code>ANN401</code> example
error out-of-the-box (<a
href="https://redirect.github.com/astral-sh/ruff/pull/18974">#18974</a>)</li>
<li>[<code>flake8-async</code>] Make <code>ASYNC100</code> example error
out-of-the-box (<a
href="https://redirect.github.com/astral-sh/ruff/pull/18993">#18993</a>)</li>
<li>[<code>flake8-async</code>] Make <code>ASYNC105</code> example error
out-of-the-box (<a
href="https://redirect.github.com/astral-sh/ruff/pull/19002">#19002</a>)</li>
<li>[<code>flake8-async</code>] Make <code>ASYNC110</code> example error
out-of-the-box (<a
href="https://redirect.github.com/astral-sh/ruff/pull/18975">#18975</a>)</li>
<li>[<code>flake8-async</code>] Make <code>ASYNC210</code> example error
out-of-the-box (<a
href="https://redirect.github.com/astral-sh/ruff/pull/18977">#18977</a>)</li>
<li>[<code>flake8-async</code>] Make <code>ASYNC220</code>,
<code>ASYNC221</code>, and <code>ASYNC222</code> examples error
out-of-the-box (<a
href="https://redirect.github.com/astral-sh/ruff/pull/18978">#18978</a>)</li>
<li>[<code>flake8-async</code>] Make <code>ASYNC251</code> example error
out-of-the-box (<a
href="https://redirect.github.com/astral-sh/ruff/pull/18990">#18990</a>)</li>
<li>[<code>flake8-bandit</code>] Make <code>S201</code> example error
out-of-the-box (<a
href="https://redirect.github.com/astral-sh/ruff/pull/19017">#19017</a>)</li>
<li>[<code>flake8-bandit</code>] Make <code>S604</code> and
<code>S609</code> examples error out-of-the-box (<a
href="https://redirect.github.com/astral-sh/ruff/pull/19049">#19049</a>)</li>
<li>[<code>flake8-bugbear</code>] Make <code>B028</code> example error
out-of-the-box (<a
href="https://redirect.github.com/astral-sh/ruff/pull/19054">#19054</a>)</li>
<li>[<code>flake8-bugbear</code>] Make <code>B911</code> example error
out-of-the-box (<a
href="https://redirect.github.com/astral-sh/ruff/pull/19051">#19051</a>)</li>
<li>[<code>flake8-datetimez</code>] Make <code>DTZ011</code> example
error out-of-the-box (<a
href="https://redirect.github.com/astral-sh/ruff/pull/19055">#19055</a>)</li>
<li>[<code>flake8-datetimez</code>] Make <code>DTZ901</code> example
error out-of-the-box (<a
href="https://redirect.github.com/astral-sh/ruff/pull/19056">#19056</a>)</li>
<li>[<code>flake8-pyi</code>] Make <code>PYI032</code> example error
out-of-the-box (<a
href="https://redirect.github.com/astral-sh/ruff/pull/19061">#19061</a>)</li>
<li>[<code>flake8-pyi</code>] Make example error out-of-the-box
(<code>PYI014</code>, <code>PYI015</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/19097">#19097</a>)</li>
<li>[<code>flake8-pyi</code>] Make example error out-of-the-box
(<code>PYI042</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/19101">#19101</a>)</li>
<li>[<code>flake8-pyi</code>] Make example error out-of-the-box
(<code>PYI059</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/19080">#19080</a>)</li>
<li>[<code>flake8-pyi</code>] Make example error out-of-the-box
(<code>PYI062</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/19079">#19079</a>)</li>
<li>[<code>flake8-pytest-style</code>] Make example error out-of-the-box
(<code>PT023</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/19104">#19104</a>)</li>
<li>[<code>flake8-pytest-style</code>] Make example error out-of-the-box
(<code>PT030</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/19105">#19105</a>)</li>
<li>[<code>flake8-quotes</code>] Make example error out-of-the-box
(<code>Q003</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/19106">#19106</a>)</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/astral-sh/ruff/commit/9bee8376a17401f9736b45fdefffb62edc2f1668"><code>9bee837</code></a>
Bump 0.12.2 (<a
href="https://redirect.github.com/astral-sh/ruff/issues/19126">#19126</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/1c6717b149ddfbcd4aa0aee2e160320474392da9"><code>1c6717b</code></a>
Filter private symbols from stubs if they are internal types (<a
href="https://redirect.github.com/astral-sh/ruff/issues/19121">#19121</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/1b813cd5f1933ab05ba7b96ace798199429c0bd6"><code>1b813cd</code></a>
Fix description of the <code>format.skip-magic-trailing-comma</code>
example (<a
href="https://redirect.github.com/astral-sh/ruff/issues/19095">#19095</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/b00f68a23cedbd3a38fc25bac63638f0f11fc3f0"><code>b00f68a</code></a>
[<code>ruff</code>] Allow more <code>field</code> calls from
<code>attrs</code> (<code>RUF009</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/issues/19021">#19021</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/710c60f7135879b05f6c05a34085cd7af5c19e7f"><code>710c60f</code></a>
[<code>flake8-pytest-style</code>] Make example error out-of-the-box
(<code>PT023</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/issues/19104">#19104</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/811e25d16e22ca4ce124d9514232211c9a0b27a1"><code>811e25d</code></a>
[<code>flake8-pytest-style</code>] Make example error out-of-the-box
(<code>PT030</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/issues/19105">#19105</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/b78af2db4822dc55acbfb1024b30e69fe0262311"><code>b78af2d</code></a>
[<code>flake8-quotes</code>] Make example error out-of-the-box
(<code>Q003</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/issues/19106">#19106</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/4f36f0677f09b0ed1ba20f583b6f017c4f7d26c8"><code>4f36f06</code></a>
Document link between <code>import-outside-top-level (PLC0415)</code>
and `lint.flake8-t...</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/2589a2938ee58a1ff1b54a9558807ecb000ccca3"><code>2589a29</code></a>
[<code>flake8-simplify</code>] Make example error out-of-the-box
(<code>SIM113</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/issues/19109">#19109</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/26bb8f7b7189558520bb386867579768b5a17347"><code>26bb8f7</code></a>
[<code>flake8-simplify</code>] Make example error out-of-the-box
(<code>SIM401</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/issues/19110">#19110</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/astral-sh/ruff/compare/0.11.13...0.12.2">compare
view</a></li>
</ul>
</details>
<br />


Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
 requirements.dev.txt | 104 ++++++------
 requirements.win.txt | 381 +++++++++++++++++++++++--------------------
 2 files changed, 257 insertions(+), 228 deletions(-)

diff --git a/requirements.dev.txt b/requirements.dev.txt
index 68171eb5..0876769e 100644
--- a/requirements.dev.txt
+++ b/requirements.dev.txt
@@ -198,39 +198,39 @@ markupsafe==3.0.2 \
     # via
     #   -r requirements.txt
     #   jinja2
-mypy==1.16.0 \
-    --hash=sha256:021a68568082c5b36e977d54e8f1de978baf401a33884ffcea09bd8e88a98f4c \
-    --hash=sha256:089bedc02307c2548eb51f426e085546db1fa7dd87fbb7c9fa561575cf6eb1ff \
-    --hash=sha256:09a8da6a0ee9a9770b8ff61b39c0bb07971cda90e7297f4213741b48a0cc8d93 \
-    --hash=sha256:0b07e107affb9ee6ce1f342c07f51552d126c32cd62955f59a7db94a51ad12c0 \
-    --hash=sha256:15486beea80be24ff067d7d0ede673b001d0d684d0095803b3e6e17a886a2a92 \
-    --hash=sha256:29e1499864a3888bca5c1542f2d7232c6e586295183320caa95758fc84034031 \
-    --hash=sha256:2e7e0ad35275e02797323a5aa1be0b14a4d03ffdb2e5f2b0489fa07b89c67b21 \
-    --hash=sha256:4086883a73166631307fdd330c4a9080ce24913d4f4c5ec596c601b3a4bdd777 \
-    --hash=sha256:54066fed302d83bf5128632d05b4ec68412e1f03ef2c300434057d66866cea4b \
-    --hash=sha256:55f9076c6ce55dd3f8cd0c6fff26a008ca8e5131b89d5ba6d86bd3f47e736eeb \
-    --hash=sha256:6a2322896003ba66bbd1318c10d3afdfe24e78ef12ea10e2acd985e9d684a666 \
-    --hash=sha256:7909541fef256527e5ee9c0a7e2aeed78b6cda72ba44298d1334fe7881b05c5c \
-    --hash=sha256:82d056e6faa508501af333a6af192c700b33e15865bda49611e3d7d8358ebea2 \
-    --hash=sha256:84b94283f817e2aa6350a14b4a8fb2a35a53c286f97c9d30f53b63620e7af8ab \
-    --hash=sha256:936ccfdd749af4766be824268bfe22d1db9eb2f34a3ea1d00ffbe5b5265f5491 \
-    --hash=sha256:9f826aaa7ff8443bac6a494cf743f591488ea940dd360e7dd330e30dd772a5ab \
-    --hash=sha256:a5fcfdb7318c6a8dd127b14b1052743b83e97a970f0edb6c913211507a255e20 \
-    --hash=sha256:a7e32297a437cc915599e0578fa6bc68ae6a8dc059c9e009c628e1c47f91495d \
-    --hash=sha256:a9e056237c89f1587a3be1a3a70a06a698d25e2479b9a2f57325ddaaffc3567b \
-    --hash=sha256:afe420c9380ccec31e744e8baff0d406c846683681025db3531b32db56962d52 \
-    --hash=sha256:b4968f14f44c62e2ec4a038c8797a87315be8df7740dc3ee8d3bfe1c6bf5dba8 \
-    --hash=sha256:bd4e1ebe126152a7bbaa4daedd781c90c8f9643c79b9748caa270ad542f12bec \
-    --hash=sha256:c5436d11e89a3ad16ce8afe752f0f373ae9620841c50883dc96f8b8805620b13 \
-    --hash=sha256:c6fb60cbd85dc65d4d63d37cb5c86f4e3a301ec605f606ae3a9173e5cf34997b \
-    --hash=sha256:d045d33c284e10a038f5e29faca055b90eee87da3fc63b8889085744ebabb5a1 \
-    --hash=sha256:e71d6f0090c2256c713ed3d52711d01859c82608b5d68d4fa01a3fe30df95571 \
-    --hash=sha256:eb14a4a871bb8efb1e4a50360d4e3c8d6c601e7a31028a2c79f9bb659b63d730 \
-    --hash=sha256:eb5fbc8063cb4fde7787e4c0406aa63094a34a2daf4673f359a1fb64050e9cb2 \
-    --hash=sha256:f2622af30bf01d8fc36466231bdd203d120d7a599a6d88fb22bdcb9dbff84090 \
-    --hash=sha256:f2ed0e0847a80655afa2c121835b848ed101cc7b8d8d6ecc5205aedc732b1436 \
-    --hash=sha256:f56236114c425620875c7cf71700e3d60004858da856c6fc78998ffe767b73d3 \
-    --hash=sha256:feec38097f71797da0231997e0de3a58108c51845399669ebc532c815f93866b
+mypy==1.16.1 \
+    --hash=sha256:051e1677689c9d9578b9c7f4d206d763f9bbd95723cd1416fad50db49d52f359 \
+    --hash=sha256:08e850ea22adc4d8a4014651575567b0318ede51e8e9fe7a68f25391af699507 \
+    --hash=sha256:09aa4f91ada245f0a45dbc47e548fd94e0dd5a8433e0114917dc3b526912a30c \
+    --hash=sha256:0a7cfb0fe29fe5a9841b7c8ee6dffb52382c45acdf68f032145b75620acfbd6f \
+    --hash=sha256:0ab5eca37b50188163fa7c1b73c685ac66c4e9bdee4a85c9adac0e91d8895e15 \
+    --hash=sha256:1256688e284632382f8f3b9e2123df7d279f603c561f099758e66dd6ed4e8bd6 \
+    --hash=sha256:13c7cd5b1cb2909aa318a90fd1b7e31f17c50b242953e7dd58345b2a814f6383 \
+    --hash=sha256:1f0435cf920e287ff68af3d10a118a73f212deb2ce087619eb4e648116d1fe9b \
+    --hash=sha256:211287e98e05352a2e1d4e8759c5490925a7c784ddc84207f4714822f8cf99b6 \
+    --hash=sha256:22d76a63a42619bfb90122889b903519149879ddbf2ba4251834727944c8baca \
+    --hash=sha256:2c7ce0662b6b9dc8f4ed86eb7a5d505ee3298c04b40ec13b30e572c0e5ae17c4 \
+    --hash=sha256:352025753ef6a83cb9e7f2427319bb7875d1fdda8439d1e23de12ab164179574 \
+    --hash=sha256:44e7acddb3c48bd2713994d098729494117803616e116032af192871aed80b79 \
+    --hash=sha256:472e4e4c100062488ec643f6162dd0d5208e33e2f34544e1fc931372e806c0cc \
+    --hash=sha256:4f58ac32771341e38a853c5d0ec0dfe27e18e27da9cdb8bbc882d2249c71a3ee \
+    --hash=sha256:58e07fb958bc5d752a280da0e890c538f1515b79a65757bbdc54252ba82e0b40 \
+    --hash=sha256:5e198ab3f55924c03ead626ff424cad1732d0d391478dfbf7bb97b34602395da \
+    --hash=sha256:5fc2ac4027d0ef28d6ba69a0343737a23c4d1b83672bf38d1fe237bdc0643b37 \
+    --hash=sha256:66df38405fd8466ce3517eda1f6640611a0b8e70895e2a9462d1d4323c5eb4b9 \
+    --hash=sha256:6bd00a0a2094841c5e47e7374bb42b83d64c527a502e3334e1173a0c24437bab \
+    --hash=sha256:7fc688329af6a287567f45cc1cefb9db662defeb14625213a5b7da6e692e2069 \
+    --hash=sha256:86042bbf9f5a05ea000d3203cf87aa9d0ccf9a01f73f71c58979eb9249f46d72 \
+    --hash=sha256:87ff2c13d58bdc4bbe7dc0dedfe622c0f04e2cb2a492269f3b418df2de05c536 \
+    --hash=sha256:af4792433f09575d9eeca5c63d7d90ca4aeceda9d8355e136f80f8967639183d \
+    --hash=sha256:b4f0fed1022a63c6fec38f28b7fc77fca47fd490445c69d0a66266c59dd0b88a \
+    --hash=sha256:d5d2309511cc56c021b4b4e462907c2b12f669b2dbeb68300110ec27723971be \
+    --hash=sha256:ddc91eb318c8751c69ddb200a5937f1232ee8efb4e64e9f4bc475a33719de438 \
+    --hash=sha256:dedb6229b2c9086247e21a83c309754b9058b438704ad2f6807f0d8227f6ebdd \
+    --hash=sha256:ea16e2a7d2714277e349e24d19a782a663a34ed60864006e8585db08f8ad1782 \
+    --hash=sha256:ea7469ee5902c95542bea7ee545f7006508c65c8c54b06dc2c92676ce526f3ea \
+    --hash=sha256:f895078594d918f93337a505f8add9bd654d1a24962b4c6ed9390e12531eb31b \
+    --hash=sha256:ff9fa5b16e4c1364eb89a4d16bcda9987f05d39604e1e6c35378a2987c1aac2d
     # via -r requirements.dev.in
 mypy-extensions==1.0.0 \
     --hash=sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d \
@@ -417,25 +417,25 @@ rpds-py==0.22.3 \
     #   -r requirements.txt
     #   jsonschema
     #   referencing
-ruff==0.11.13 \
-    --hash=sha256:1808b3ed53e1a777c2ef733aca9051dc9bf7c99b26ece15cb59a0320fbdbd629 \
-    --hash=sha256:26816a218ca6ef02142343fd24c70f7cd8c5aa6c203bca284407adf675984432 \
-    --hash=sha256:26fa247dc68d1d4e72c179e08889a25ac0c7ba4d78aecfc835d49cbfd60bf514 \
-    --hash=sha256:29c3189895a8a6a657b7af4e97d330c8a3afd2c9c8f46c81e2fc5a31866517e3 \
-    --hash=sha256:4a9ddd3ec62a9a89578c85842b836e4ac832d4a2e0bfaad3b02243f930ceafcc \
-    --hash=sha256:4bdfbf1240533f40042ec00c9e09a3aade6f8c10b6414cf11b519488d2635d46 \
-    --hash=sha256:4ffbc82d70424b275b089166310448051afdc6e914fdab90e08df66c43bb5ca9 \
-    --hash=sha256:51c3f95abd9331dc5b87c47ac7f376db5616041173826dfd556cfe3d4977f492 \
-    --hash=sha256:53b15a9dfdce029c842e9a5aebc3855e9ab7771395979ff85b7c1dedb53ddc2b \
-    --hash=sha256:55e4bc3a77842da33c16d55b32c6cac1ec5fb0fbec9c8c513bdce76c4f922165 \
-    --hash=sha256:633bf2c6f35678c56ec73189ba6fa19ff1c5e4807a78bf60ef487b9dd272cc71 \
-    --hash=sha256:6c51f93029d54a910d3d24f7dd0bb909e31b6cd989a5e4ac513f4eb41629f0dc \
-    --hash=sha256:96c27935418e4e8e77a26bb05962817f28b8ef3843a6c6cc49d8783b5507f250 \
-    --hash=sha256:ab153241400789138d13f362c43f7edecc0edfffce2afa6a68434000ecd8f69a \
-    --hash=sha256:aef9c9ed1b5ca28bb15c7eac83b8670cf3b20b478195bd49c8d756ba0a36cf48 \
-    --hash=sha256:b4385285e9179d608ff1d2fb9922062663c658605819a6876d8beef0c30b7f3b \
-    --hash=sha256:d237a496e0778d719efb05058c64d28b757c77824e04ffe8796c7436e26712b7 \
-    --hash=sha256:d28ce58b5ecf0f43c1b71edffabe6ed7f245d5336b17805803312ec9bc665933
+ruff==0.12.2 \
+    --hash=sha256:093ea2b221df1d2b8e7ad92fc6ffdca40a2cb10d8564477a987b44fd4008a7be \
+    --hash=sha256:09e4cf27cc10f96b1708100fa851e0daf21767e9709e1649175355280e0d950e \
+    --hash=sha256:2a4a20aeed74671b2def096bdf2eac610c7d8ffcbf4fb0e627c06947a1d7078d \
+    --hash=sha256:369ffb69b70cd55b6c3fc453b9492d98aed98062db9fec828cdfd069555f5f1a \
+    --hash=sha256:3b8b94317cbc2ae4a2771af641739f933934b03555e51515e6e021c64441532d \
+    --hash=sha256:3eb3a6b2db4d6e2c77e682f0b988d4d61aff06860158fdb413118ca133d57922 \
+    --hash=sha256:45fc42c3bf1d30d2008023a0a9a0cfb06bf9835b147f11fe0679f21ae86d34b1 \
+    --hash=sha256:48d6c6bfb4761df68bc05ae630e24f506755e702d4fb08f08460be778c7ccb12 \
+    --hash=sha256:4987b8f4ceadf597c927beee65a5eaf994c6e2b631df963f86d8ad1bdea99342 \
+    --hash=sha256:6932323db80484dda89153da3d8e58164d01d6da86857c79f1961934354992da \
+    --hash=sha256:6aa7e623a3a11538108f61e859ebf016c4f14a7e6e4eba1980190cacb57714ce \
+    --hash=sha256:71a4c550195612f486c9d1f2b045a600aeba851b298c667807ae933478fcef04 \
+    --hash=sha256:73448de992d05517170fc37169cbca857dfeaeaa8c2b9be494d7bcb0d36c8f4b \
+    --hash=sha256:793d8859445ea47591272021a81391350205a4af65a9392401f418a95dfb75c9 \
+    --hash=sha256:8ae64755b22f4ff85e9c52d1f82644abd0b6b6b6deedceb74bd71f35c24044cc \
+    --hash=sha256:ce48f675c394c37e958bf229fb5c1e843e20945a6d962cf3ea20b7a107dcd9f4 \
+    --hash=sha256:d7b4f55cd6f325cb7621244f19c873c565a08aff5a4ba9c69aa7355f3f7afd3e \
+    --hash=sha256:dca8a3b6d6dc9810ed8f328d406516bf4d660c00caeaef36eb831cf4871b0639
     # via -r requirements.dev.in
 six==1.17.0 \
     --hash=sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274 \
diff --git a/requirements.win.txt b/requirements.win.txt
index b9b9a814..faa01357 100644
--- a/requirements.win.txt
+++ b/requirements.win.txt
@@ -6,9 +6,9 @@ attrs==25.3.0 \
     # via
     #   jsonschema
     #   referencing
-certifi==2025.4.26 \
-    --hash=sha256:0a816057ea3cdefcef70270d2c515e4506bbc954f417fa5ade2021213bb8f0c6 \
-    --hash=sha256:30350364dfe371162649852c63336a15c70c6510c2ad5015b21c2345311805f3
+certifi==2025.6.15 \
+    --hash=sha256:2e0c7ce7cb5d8f8634ca55d2ba7e6ec2689a2fd6537d8dec1296a477a4910057 \
+    --hash=sha256:d747aa5a8b9bbbb1bb8c22bb13e22bd1f18e9796defa16bab421f7f7a317323b
     # via requests
 charset-normalizer==3.4.2 \
     --hash=sha256:005fa3432484527f9732ebd315da8da8001593e2cf46a3d817669f062c3d9ed4 \
@@ -205,58 +205,60 @@ pywin32==310 \
     --hash=sha256:c3e78706e4229b915a0821941a84e7ef420bf2b77e08c9dae3c76fd03fd2ae3d \
     --hash=sha256:e308f831de771482b7cf692a1f308f8fca701b2d8f9dde6cc440c7da17e47b33
     # via docker
-pyyaml==6.0.1 \
-    --hash=sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5 \
-    --hash=sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc \
-    --hash=sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df \
-    --hash=sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741 \
-    --hash=sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206 \
-    --hash=sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27 \
-    --hash=sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595 \
-    --hash=sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62 \
-    --hash=sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98 \
-    --hash=sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696 \
-    --hash=sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290 \
-    --hash=sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9 \
-    --hash=sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d \
-    --hash=sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6 \
-    --hash=sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867 \
-    --hash=sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47 \
-    --hash=sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486 \
-    --hash=sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6 \
-    --hash=sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3 \
-    --hash=sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007 \
-    --hash=sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938 \
-    --hash=sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0 \
-    --hash=sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c \
-    --hash=sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735 \
-    --hash=sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d \
-    --hash=sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28 \
-    --hash=sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4 \
-    --hash=sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba \
-    --hash=sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8 \
-    --hash=sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef \
-    --hash=sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5 \
-    --hash=sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd \
-    --hash=sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3 \
-    --hash=sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0 \
-    --hash=sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515 \
-    --hash=sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c \
-    --hash=sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c \
-    --hash=sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924 \
-    --hash=sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34 \
-    --hash=sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43 \
-    --hash=sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859 \
-    --hash=sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673 \
-    --hash=sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54 \
-    --hash=sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a \
-    --hash=sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b \
-    --hash=sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab \
-    --hash=sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa \
-    --hash=sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c \
-    --hash=sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585 \
-    --hash=sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d \
-    --hash=sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f
+pyyaml==6.0.2 \
+    --hash=sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff \
+    --hash=sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48 \
+    --hash=sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086 \
+    --hash=sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e \
+    --hash=sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133 \
+    --hash=sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5 \
+    --hash=sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484 \
+    --hash=sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee \
+    --hash=sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5 \
+    --hash=sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68 \
+    --hash=sha256:24471b829b3bf607e04e88d79542a9d48bb037c2267d7927a874e6c205ca7e9a \
+    --hash=sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf \
+    --hash=sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99 \
+    --hash=sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8 \
+    --hash=sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85 \
+    --hash=sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19 \
+    --hash=sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc \
+    --hash=sha256:43fa96a3ca0d6b1812e01ced1044a003533c47f6ee8aca31724f78e93ccc089a \
+    --hash=sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1 \
+    --hash=sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317 \
+    --hash=sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c \
+    --hash=sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631 \
+    --hash=sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d \
+    --hash=sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652 \
+    --hash=sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5 \
+    --hash=sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e \
+    --hash=sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b \
+    --hash=sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8 \
+    --hash=sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476 \
+    --hash=sha256:82d09873e40955485746739bcb8b4586983670466c23382c19cffecbf1fd8706 \
+    --hash=sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563 \
+    --hash=sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237 \
+    --hash=sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b \
+    --hash=sha256:9056c1ecd25795207ad294bcf39f2db3d845767be0ea6e6a34d856f006006083 \
+    --hash=sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180 \
+    --hash=sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425 \
+    --hash=sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e \
+    --hash=sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f \
+    --hash=sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725 \
+    --hash=sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183 \
+    --hash=sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab \
+    --hash=sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774 \
+    --hash=sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725 \
+    --hash=sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e \
+    --hash=sha256:d7fded462629cfa4b685c5416b949ebad6cec74af5e2d42905d41e257e0869f5 \
+    --hash=sha256:d84a1718ee396f54f3a086ea0a66d8e552b2ab2017ef8b420e92edbc841c352d \
+    --hash=sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290 \
+    --hash=sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44 \
+    --hash=sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed \
+    --hash=sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4 \
+    --hash=sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba \
+    --hash=sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12 \
+    --hash=sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4
     # via -r requirements.in
 referencing==0.36.2 \
     --hash=sha256:df2e89862cd09deabbdba16944cc3f10feb6b3e6f18e902f7cc25609a34775aa \
@@ -268,124 +270,151 @@ requests==2.32.4 \
     --hash=sha256:27babd3cda2a6d50b30443204ee89830707d396671944c998b5975b031ac2b2c \
     --hash=sha256:27d0316682c8a29834d3264820024b62a36942083d52caf2f14c0591336d3422
     # via docker
-rpds-py==0.25.1 \
-    --hash=sha256:0317177b1e8691ab5879f4f33f4b6dc55ad3b344399e23df2e499de7b10a548d \
-    --hash=sha256:036ded36bedb727beeabc16dc1dad7cb154b3fa444e936a03b67a86dc6a5066e \
-    --hash=sha256:048893e902132fd6548a2e661fb38bf4896a89eea95ac5816cf443524a85556f \
-    --hash=sha256:0701942049095741a8aeb298a31b203e735d1c61f4423511d2b1a41dcd8a16da \
-    --hash=sha256:083a9513a33e0b92cf6e7a6366036c6bb43ea595332c1ab5c8ae329e4bcc0a9c \
-    --hash=sha256:09eab132f41bf792c7a0ea1578e55df3f3e7f61888e340779b06050a9a3f16e9 \
-    --hash=sha256:0e6a327af8ebf6baba1c10fadd04964c1965d375d318f4435d5f3f9651550f4a \
-    --hash=sha256:0eb90e94f43e5085623932b68840b6f379f26db7b5c2e6bcef3179bd83c9330f \
-    --hash=sha256:114a07e85f32b125404f28f2ed0ba431685151c037a26032b213c882f26eb908 \
-    --hash=sha256:115874ae5e2fdcfc16b2aedc95b5eef4aebe91b28e7e21951eda8a5dc0d3461b \
-    --hash=sha256:140f61d9bed7839446bdd44852e30195c8e520f81329b4201ceead4d64eb3a9f \
-    --hash=sha256:1521031351865e0181bc585147624d66b3b00a84109b57fcb7a779c3ec3772cd \
-    --hash=sha256:1c0c434a53714358532d13539272db75a5ed9df75a4a090a753ac7173ec14e11 \
-    --hash=sha256:1d1fadd539298e70cac2f2cb36f5b8a65f742b9b9f1014dd4ea1f7785e2470bf \
-    --hash=sha256:1de336a4b164c9188cb23f3703adb74a7623ab32d20090d0e9bf499a2203ad65 \
-    --hash=sha256:1ee3e26eb83d39b886d2cb6e06ea701bba82ef30a0de044d34626ede51ec98b0 \
-    --hash=sha256:245550f5a1ac98504147cba96ffec8fabc22b610742e9150138e5d60774686d7 \
-    --hash=sha256:2a40046a529cc15cef88ac5ab589f83f739e2d332cb4d7399072242400ed68c9 \
-    --hash=sha256:2c2cd1a4b0c2b8c5e31ffff50d09f39906fe351389ba143c195566056c13a7ea \
-    --hash=sha256:2cb9e5b5e26fc02c8a4345048cd9998c2aca7c2712bd1b36da0c72ee969a3523 \
-    --hash=sha256:33358883a4490287e67a2c391dfaea4d9359860281db3292b6886bf0be3d8692 \
-    --hash=sha256:35634369325906bcd01577da4c19e3b9541a15e99f31e91a02d010816b49bfda \
-    --hash=sha256:35a8d1a24b5936b35c5003313bc177403d8bdef0f8b24f28b1c4a255f94ea992 \
-    --hash=sha256:3af5b4cc10fa41e5bc64e5c198a1b2d2864337f8fcbb9a67e747e34002ce812b \
-    --hash=sha256:3bcce0edc1488906c2d4c75c94c70a0417e83920dd4c88fec1078c94843a6ce9 \
-    --hash=sha256:3c5b317ecbd8226887994852e85de562f7177add602514d4ac40f87de3ae45a8 \
-    --hash=sha256:3c6564c0947a7f52e4792983f8e6cf9bac140438ebf81f527a21d944f2fd0a40 \
-    --hash=sha256:3ebd879ab996537fc510a2be58c59915b5dd63bccb06d1ef514fee787e05984a \
-    --hash=sha256:3f0b1798cae2bbbc9b9db44ee068c556d4737911ad53a4e5093d09d04b3bbc24 \
-    --hash=sha256:401ca1c4a20cc0510d3435d89c069fe0a9ae2ee6495135ac46bdd49ec0495763 \
-    --hash=sha256:454601988aab2c6e8fd49e7634c65476b2b919647626208e376afcd22019eeb8 \
-    --hash=sha256:4593c4eae9b27d22df41cde518b4b9e4464d139e4322e2127daa9b5b981b76be \
-    --hash=sha256:45e484db65e5380804afbec784522de84fa95e6bb92ef1bd3325d33d13efaebd \
-    --hash=sha256:48d64155d02127c249695abb87d39f0faf410733428d499867606be138161d65 \
-    --hash=sha256:4fbb0dbba559959fcb5d0735a0f87cdbca9e95dac87982e9b95c0f8f7ad10255 \
-    --hash=sha256:4fd52d3455a0aa997734f3835cbc4c9f32571345143960e7d7ebfe7b5fbfa3b2 \
-    --hash=sha256:50f2c501a89c9a5f4e454b126193c5495b9fb441a75b298c60591d8a2eb92e1b \
-    --hash=sha256:58f77c60956501a4a627749a6dcb78dac522f249dd96b5c9f1c6af29bfacfb66 \
-    --hash=sha256:5a3ddb74b0985c4387719fc536faced33cadf2172769540c62e2a94b7b9be1c4 \
-    --hash=sha256:5c4a128527fe415d73cf1f70a9a688d06130d5810be69f3b553bf7b45e8acf79 \
-    --hash=sha256:5d473be2b13600b93a5675d78f59e63b51b1ba2d0476893415dfbb5477e65b31 \
-    --hash=sha256:5d9e40f32745db28c1ef7aad23f6fc458dc1e29945bd6781060f0d15628b8ddf \
-    --hash=sha256:5f048bbf18b1f9120685c6d6bb70cc1a52c8cc11bdd04e643d28d3be0baf666d \
-    --hash=sha256:605ffe7769e24b1800b4d024d24034405d9404f0bc2f55b6db3362cd34145a6f \
-    --hash=sha256:6099263f526efff9cf3883dfef505518730f7a7a93049b1d90d42e50a22b4793 \
-    --hash=sha256:659d87430a8c8c704d52d094f5ba6fa72ef13b4d385b7e542a08fc240cb4a559 \
-    --hash=sha256:666fa7b1bd0a3810a7f18f6d3a25ccd8866291fbbc3c9b912b917a6715874bb9 \
-    --hash=sha256:68f6f060f0bbdfb0245267da014d3a6da9be127fe3e8cc4a68c6f833f8a23bb1 \
-    --hash=sha256:6d273f136e912aa101a9274c3145dcbddbe4bac560e77e6d5b3c9f6e0ed06d34 \
-    --hash=sha256:6d50841c425d16faf3206ddbba44c21aa3310a0cebc3c1cdfc3e3f4f9f6f5728 \
-    --hash=sha256:771c16060ff4e79584dc48902a91ba79fd93eade3aa3a12d6d2a4aadaf7d542b \
-    --hash=sha256:785ffacd0ee61c3e60bdfde93baa6d7c10d86f15655bd706c89da08068dc5038 \
-    --hash=sha256:796ad874c89127c91970652a4ee8b00d56368b7e00d3477f4415fe78164c8000 \
-    --hash=sha256:79dc317a5f1c51fd9c6a0c4f48209c6b8526d0524a6904fc1076476e79b00f98 \
-    --hash=sha256:7c9409b47ba0650544b0bb3c188243b83654dfe55dcc173a86832314e1a6a35d \
-    --hash=sha256:7d779b325cc8238227c47fbc53964c8cc9a941d5dbae87aa007a1f08f2f77b23 \
-    --hash=sha256:816568614ecb22b18a010c7a12559c19f6fe993526af88e95a76d5a60b8b75fb \
-    --hash=sha256:8378fa4a940f3fb509c081e06cb7f7f2adae8cf46ef258b0e0ed7519facd573e \
-    --hash=sha256:85608eb70a659bf4c1142b2781083d4b7c0c4e2c90eff11856a9754e965b2540 \
-    --hash=sha256:85fc223d9c76cabe5d0bff82214459189720dc135db45f9f66aa7cffbf9ff6c1 \
-    --hash=sha256:88ec04afe0c59fa64e2f6ea0dd9657e04fc83e38de90f6de201954b4d4eb59bd \
-    --hash=sha256:8960b6dac09b62dac26e75d7e2c4a22efb835d827a7278c34f72b2b84fa160e3 \
-    --hash=sha256:89706d0683c73a26f76a5315d893c051324d771196ae8b13e6ffa1ffaf5e574f \
-    --hash=sha256:89c24300cd4a8e4a51e55c31a8ff3918e6651b241ee8876a42cc2b2a078533ba \
-    --hash=sha256:8c742af695f7525e559c16f1562cf2323db0e3f0fbdcabdf6865b095256b2d40 \
-    --hash=sha256:8dbd586bfa270c1103ece2109314dd423df1fa3d9719928b5d09e4840cec0d72 \
-    --hash=sha256:8eb8c84ecea987a2523e057c0d950bcb3f789696c0499290b8d7b3107a719d78 \
-    --hash=sha256:921954d7fbf3fccc7de8f717799304b14b6d9a45bbeec5a8d7408ccbf531faf5 \
-    --hash=sha256:9a46c2fb2545e21181445515960006e85d22025bd2fe6db23e76daec6eb689fe \
-    --hash=sha256:9c006f3aadeda131b438c3092124bd196b66312f0caa5823ef09585a669cf449 \
-    --hash=sha256:9ceca1cf097ed77e1a51f1dbc8d174d10cb5931c188a4505ff9f3e119dfe519b \
-    --hash=sha256:9e5fc7484fa7dce57e25063b0ec9638ff02a908304f861d81ea49273e43838c1 \
-    --hash=sha256:9f2f48ab00181600ee266a095fe815134eb456163f7d6699f525dee471f312cf \
-    --hash=sha256:9fca84a15333e925dd59ce01da0ffe2ffe0d6e5d29a9eeba2148916d1824948c \
-    --hash=sha256:a49e1d7a4978ed554f095430b89ecc23f42014a50ac385eb0c4d163ce213c325 \
-    --hash=sha256:a58d1ed49a94d4183483a3ce0af22f20318d4a1434acee255d683ad90bf78129 \
-    --hash=sha256:a61d0b2c7c9a0ae45732a77844917b427ff16ad5464b4d4f5e4adb955f582890 \
-    --hash=sha256:a714bf6e5e81b0e570d01f56e0c89c6375101b8463999ead3a93a5d2a4af91fa \
-    --hash=sha256:a7b74e92a3b212390bdce1d93da9f6488c3878c1d434c5e751cbc202c5e09500 \
-    --hash=sha256:a8bd2f19e312ce3e1d2c635618e8a8d8132892bb746a7cf74780a489f0f6cdcb \
-    --hash=sha256:b0be9965f93c222fb9b4cc254235b3b2b215796c03ef5ee64f995b1b69af0762 \
-    --hash=sha256:b24bf3cd93d5b6ecfbedec73b15f143596c88ee249fa98cefa9a9dc9d92c6f28 \
-    --hash=sha256:b5ffe453cde61f73fea9430223c81d29e2fbf412a6073951102146c84e19e34c \
-    --hash=sha256:bc120d1132cff853ff617754196d0ac0ae63befe7c8498bd67731ba368abe451 \
-    --hash=sha256:bd035756830c712b64725a76327ce80e82ed12ebab361d3a1cdc0f51ea21acb0 \
-    --hash=sha256:bffcf57826d77a4151962bf1701374e0fc87f536e56ec46f1abdd6a903354042 \
-    --hash=sha256:c2013ee878c76269c7b557a9a9c042335d732e89d482606990b70a839635feb7 \
-    --hash=sha256:c4feb9211d15d9160bc85fa72fed46432cdc143eb9cf6d5ca377335a921ac37b \
-    --hash=sha256:c8980cde3bb8575e7c956a530f2c217c1d6aac453474bf3ea0f9c89868b531b6 \
-    --hash=sha256:c98f126c4fc697b84c423e387337d5b07e4a61e9feac494362a59fd7a2d9ed80 \
-    --hash=sha256:ccc6f3ddef93243538be76f8e47045b4aad7a66a212cd3a0f23e34469473d36b \
-    --hash=sha256:ccfa689b9246c48947d31dd9d8b16d89a0ecc8e0e26ea5253068efb6c542b76e \
-    --hash=sha256:cda776f1967cb304816173b30994faaf2fd5bcb37e73118a47964a02c348e1bc \
-    --hash=sha256:ce4c8e485a3c59593f1a6f683cf0ea5ab1c1dc94d11eea5619e4fb5228b40fbd \
-    --hash=sha256:d3c10228d6cf6fe2b63d2e7985e94f6916fa46940df46b70449e9ff9297bd3d1 \
-    --hash=sha256:d4ca54b9cf9d80b4016a67a0193ebe0bcf29f6b0a96f09db942087e294d3d4c2 \
-    --hash=sha256:d4cb2b3ddc16710548801c6fcc0cfcdeeff9dafbc983f77265877793f2660309 \
-    --hash=sha256:d50e4864498a9ab639d6d8854b25e80642bd362ff104312d9770b05d66e5fb13 \
-    --hash=sha256:d74ec9bc0e2feb81d3f16946b005748119c0f52a153f6db6a29e8cd68636f295 \
-    --hash=sha256:d8222acdb51a22929c3b2ddb236b69c59c72af4019d2cba961e2f9add9b6e634 \
-    --hash=sha256:db58483f71c5db67d643857404da360dce3573031586034b7d59f245144cc192 \
-    --hash=sha256:dc3c1ff0abc91444cd20ec643d0f805df9a3661fcacf9c95000329f3ddf268a4 \
-    --hash=sha256:dd326a81afe332ede08eb39ab75b301d5676802cdffd3a8f287a5f0b694dc3f5 \
-    --hash=sha256:dec21e02e6cc932538b5203d3a8bd6aa1480c98c4914cb88eea064ecdbc6396a \
-    --hash=sha256:e1dafef8df605fdb46edcc0bf1573dea0d6d7b01ba87f85cd04dc855b2b4479e \
-    --hash=sha256:e2f6a2347d3440ae789505693a02836383426249d5293541cd712e07e7aecf54 \
-    --hash=sha256:e37caa8cdb3b7cf24786451a0bdb853f6347b8b92005eeb64225ae1db54d1c2b \
-    --hash=sha256:e43a005671a9ed5a650f3bc39e4dbccd6d4326b24fb5ea8be5f3a43a6f576c72 \
-    --hash=sha256:e5e2f7280d8d0d3ef06f3ec1b4fd598d386cc6f0721e54f09109a8132182fbfe \
-    --hash=sha256:e87798852ae0b37c88babb7f7bbbb3e3fecc562a1c340195b44c7e24d403e380 \
-    --hash=sha256:ee86d81551ec68a5c25373c5643d343150cc54672b5e9a0cafc93c1870a53954 \
-    --hash=sha256:f251bf23deb8332823aef1da169d5d89fa84c89f67bdfb566c49dea1fccfd50d \
-    --hash=sha256:f3d86373ff19ca0441ebeb696ef64cb58b8b5cbacffcda5a0ec2f3911732a194 \
-    --hash=sha256:f4ad628b5174d5315761b67f212774a32f5bad5e61396d38108bd801c0a8f5d9 \
-    --hash=sha256:f70316f760174ca04492b5ab01be631a8ae30cadab1d1081035136ba12738cfa \
-    --hash=sha256:f73ce1512e04fbe2bc97836e89830d6b4314c171587a99688082d090f934d20a \
-    --hash=sha256:ff7c23ba0a88cb7b104281a99476cccadf29de2a0ef5ce864959a52675b1ca83
+rpds-py==0.26.0 \
+    --hash=sha256:0919f38f5542c0a87e7b4afcafab6fd2c15386632d249e9a087498571250abe3 \
+    --hash=sha256:093d63b4b0f52d98ebae33b8c50900d3d67e0666094b1be7a12fffd7f65de74b \
+    --hash=sha256:0a0b60701f2300c81b2ac88a5fb893ccfa408e1c4a555a77f908a2596eb875a5 \
+    --hash=sha256:0c71c2f6bf36e61ee5c47b2b9b5d47e4d1baad6426bfed9eea3e858fc6ee8806 \
+    --hash=sha256:0dc23bbb3e06ec1ea72d515fb572c1fea59695aefbffb106501138762e1e915e \
+    --hash=sha256:0dfa6115c6def37905344d56fb54c03afc49104e2ca473d5dedec0f6606913b4 \
+    --hash=sha256:12bff2ad9447188377f1b2794772f91fe68bb4bbfa5a39d7941fbebdbf8c500f \
+    --hash=sha256:1533b7eb683fb5f38c1d68a3c78f5fdd8f1412fa6b9bf03b40f450785a0ab915 \
+    --hash=sha256:1766b5724c3f779317d5321664a343c07773c8c5fd1532e4039e6cc7d1a815be \
+    --hash=sha256:181ef9b6bbf9845a264f9aa45c31836e9f3c1f13be565d0d010e964c661d1e2b \
+    --hash=sha256:183f857a53bcf4b1b42ef0f57ca553ab56bdd170e49d8091e96c51c3d69ca696 \
+    --hash=sha256:191aa858f7d4902e975d4cf2f2d9243816c91e9605070aeb09c0a800d187e323 \
+    --hash=sha256:1a8b0dd8648709b62d9372fc00a57466f5fdeefed666afe3fea5a6c9539a0331 \
+    --hash=sha256:1c962145c7473723df9722ba4c058de12eb5ebedcb4e27e7d902920aa3831ee8 \
+    --hash=sha256:1cc81d14ddfa53d7f3906694d35d54d9d3f850ef8e4e99ee68bc0d1e5fed9a9c \
+    --hash=sha256:1d815d48b1804ed7867b539236b6dd62997850ca1c91cad187f2ddb1b7bbef19 \
+    --hash=sha256:1e6c15d2080a63aaed876e228efe4f814bc7889c63b1e112ad46fdc8b368b9e1 \
+    --hash=sha256:20ab1ae4fa534f73647aad289003f1104092890849e0266271351922ed5574f8 \
+    --hash=sha256:20dae58a859b0906f0685642e591056f1e787f3a8b39c8e8749a45dc7d26bdb0 \
+    --hash=sha256:238e8c8610cb7c29460e37184f6799547f7e09e6a9bdbdab4e8edb90986a2318 \
+    --hash=sha256:24a4146ccb15be237fdef10f331c568e1b0e505f8c8c9ed5d67759dac58ac246 \
+    --hash=sha256:257d011919f133a4746958257f2c75238e3ff54255acd5e3e11f3ff41fd14256 \
+    --hash=sha256:2a343f91b17097c546b93f7999976fd6c9d5900617aa848c81d794e062ab302b \
+    --hash=sha256:2abe21d8ba64cded53a2a677e149ceb76dcf44284202d737178afe7ba540c1eb \
+    --hash=sha256:2c03c9b0c64afd0320ae57de4c982801271c0c211aa2d37f3003ff5feb75bb04 \
+    --hash=sha256:2c9c1b92b774b2e68d11193dc39620d62fd8ab33f0a3c77ecdabe19c179cdbc1 \
+    --hash=sha256:3021933c2cb7def39d927b9862292e0f4c75a13d7de70eb0ab06efed4c508c19 \
+    --hash=sha256:3100b3090269f3a7ea727b06a6080d4eb7439dca4c0e91a07c5d133bb1727ea7 \
+    --hash=sha256:313cfcd6af1a55a286a3c9a25f64af6d0e46cf60bc5798f1db152d97a216ff6f \
+    --hash=sha256:35e9a70a0f335371275cdcd08bc5b8051ac494dd58bff3bbfb421038220dc871 \
+    --hash=sha256:38721d4c9edd3eb6670437d8d5e2070063f305bfa2d5aa4278c51cedcd508a84 \
+    --hash=sha256:390e3170babf42462739a93321e657444f0862c6d722a291accc46f9d21ed04e \
+    --hash=sha256:39bfea47c375f379d8e87ab4bb9eb2c836e4f2069f0f65731d85e55d74666387 \
+    --hash=sha256:3ac51b65e8dc76cf4949419c54c5528adb24fc721df722fd452e5fbc236f5c40 \
+    --hash=sha256:3c0909c5234543ada2515c05dc08595b08d621ba919629e94427e8e03539c958 \
+    --hash=sha256:3da5852aad63fa0c6f836f3359647870e21ea96cf433eb393ffa45263a170d44 \
+    --hash=sha256:3e1157659470aa42a75448b6e943c895be8c70531c43cb78b9ba990778955582 \
+    --hash=sha256:4019a9d473c708cf2f16415688ef0b4639e07abaa569d72f74745bbeffafa2c7 \
+    --hash=sha256:43f10b007033f359bc3fa9cd5e6c1e76723f056ffa9a6b5c117cc35720a80292 \
+    --hash=sha256:49028aa684c144ea502a8e847d23aed5e4c2ef7cadfa7d5eaafcb40864844b7a \
+    --hash=sha256:4916dc96489616a6f9667e7526af8fa693c0fdb4f3acb0e5d9f4400eb06a47ba \
+    --hash=sha256:4a59e5bc386de021f56337f757301b337d7ab58baa40174fb150accd480bc953 \
+    --hash=sha256:4b1f66eb81eab2e0ff5775a3a312e5e2e16bf758f7b06be82fb0d04078c7ac51 \
+    --hash=sha256:4c5fe114a6dd480a510b6d3661d09d67d1622c4bf20660a474507aaee7eeeee9 \
+    --hash=sha256:4c70c70f9169692b36307a95f3d8c0a9fcd79f7b4a383aad5eaa0e9718b79b37 \
+    --hash=sha256:4d11382bcaf12f80b51d790dee295c56a159633a8e81e6323b16e55d81ae37e9 \
+    --hash=sha256:4f01a5d6444a3258b00dc07b6ea4733e26f8072b788bef750baa37b370266137 \
+    --hash=sha256:4f789e32fa1fb6a7bf890e0124e7b42d1e60d28ebff57fe806719abb75f0e9a3 \
+    --hash=sha256:4feb7511c29f8442cbbc28149a92093d32e815a28aa2c50d333826ad2a20fdf0 \
+    --hash=sha256:511d15193cbe013619dd05414c35a7dedf2088fcee93c6bbb7c77859765bd4e8 \
+    --hash=sha256:519067e29f67b5c90e64fb1a6b6e9d2ec0ba28705c51956637bac23a2f4ddae1 \
+    --hash=sha256:521ccf56f45bb3a791182dc6b88ae5f8fa079dd705ee42138c76deb1238e554e \
+    --hash=sha256:529c8156d7506fba5740e05da8795688f87119cce330c244519cf706a4a3d618 \
+    --hash=sha256:582462833ba7cee52e968b0341b85e392ae53d44c0f9af6a5927c80e539a8b67 \
+    --hash=sha256:5963b72ccd199ade6ee493723d18a3f21ba7d5b957017607f815788cef50eaf1 \
+    --hash=sha256:59b2093224a18c6508d95cfdeba8db9cbfd6f3494e94793b58972933fcee4c6d \
+    --hash=sha256:5afaddaa8e8c7f1f7b4c5c725c0070b6eed0228f705b90a1732a48e84350f4e9 \
+    --hash=sha256:5afea17ab3a126006dc2f293b14ffc7ef3c85336cf451564a0515ed7648033da \
+    --hash=sha256:5e09330b21d98adc8ccb2dbb9fc6cb434e8908d4c119aeaa772cb1caab5440a0 \
+    --hash=sha256:6188de70e190847bb6db3dc3981cbadff87d27d6fe9b4f0e18726d55795cee9b \
+    --hash=sha256:68ffcf982715f5b5b7686bdd349ff75d422e8f22551000c24b30eaa1b7f7ae84 \
+    --hash=sha256:696764a5be111b036256c0b18cd29783fab22154690fc698062fc1b0084b511d \
+    --hash=sha256:69a607203441e07e9a8a529cff1d5b73f6a160f22db1097211e6212a68567d11 \
+    --hash=sha256:69b312fecc1d017b5327afa81d4da1480f51c68810963a7336d92203dbb3d4f1 \
+    --hash=sha256:69f0c0a3df7fd3a7eec50a00396104bb9a843ea6d45fcc31c2d5243446ffd7a7 \
+    --hash=sha256:6a1cb5d6ce81379401bbb7f6dbe3d56de537fb8235979843f0d53bc2e9815a79 \
+    --hash=sha256:6d3498ad0df07d81112aa6ec6c95a7e7b1ae00929fb73e7ebee0f3faaeabad2f \
+    --hash=sha256:72a8d9564a717ee291f554eeb4bfeafe2309d5ec0aa6c475170bdab0f9ee8e88 \
+    --hash=sha256:777c62479d12395bfb932944e61e915741e364c843afc3196b694db3d669fcd0 \
+    --hash=sha256:77a7711fa562ba2da1aa757e11024ad6d93bad6ad7ede5afb9af144623e5f76a \
+    --hash=sha256:79061ba1a11b6a12743a2b0f72a46aa2758613d454aa6ba4f5a265cc48850158 \
+    --hash=sha256:7a48af25d9b3c15684059d0d1fc0bc30e8eee5ca521030e2bffddcab5be40226 \
+    --hash=sha256:7ab504c4d654e4a29558eaa5bb8cea5fdc1703ea60a8099ffd9c758472cf913f \
+    --hash=sha256:7bdb17009696214c3b66bb3590c6d62e14ac5935e53e929bcdbc5a495987a84f \
+    --hash=sha256:7da84c2c74c0f5bc97d853d9e17bb83e2dcafcff0dc48286916001cc114379a1 \
+    --hash=sha256:801a71f70f9813e82d2513c9a96532551fce1e278ec0c64610992c49c04c2dad \
+    --hash=sha256:824e6d3503ab990d7090768e4dfd9e840837bae057f212ff9f4f05ec6d1975e7 \
+    --hash=sha256:82b165b07f416bdccf5c84546a484cc8f15137ca38325403864bfdf2b5b72f6a \
+    --hash=sha256:84cfbd4d4d2cdeb2be61a057a258d26b22877266dd905809e94172dff01a42ae \
+    --hash=sha256:84d142d2d6cf9b31c12aa4878d82ed3b2324226270b89b676ac62ccd7df52d08 \
+    --hash=sha256:87a5531de9f71aceb8af041d72fc4cab4943648d91875ed56d2e629bef6d4c03 \
+    --hash=sha256:893b022bfbdf26d7bedb083efeea624e8550ca6eb98bf7fea30211ce95b9201a \
+    --hash=sha256:894514d47e012e794f1350f076c427d2347ebf82f9b958d554d12819849a369d \
+    --hash=sha256:8a7898b6ca3b7d6659e55cdac825a2e58c638cbf335cde41f4619e290dd0ad11 \
+    --hash=sha256:8ad7fd2258228bf288f2331f0a6148ad0186b2e3643055ed0db30990e59817a6 \
+    --hash=sha256:92c8db839367ef16a662478f0a2fe13e15f2227da3c1430a782ad0f6ee009ec9 \
+    --hash=sha256:941c1cfdf4799d623cf3aa1d326a6b4fdb7a5799ee2687f3516738216d2262fb \
+    --hash=sha256:9bc596b30f86dc6f0929499c9e574601679d0341a0108c25b9b358a042f51bca \
+    --hash=sha256:9c55b0a669976cf258afd718de3d9ad1b7d1fe0a91cd1ab36f38b03d4d4aeaaf \
+    --hash=sha256:9da4e873860ad5bab3291438525cae80169daecbfafe5657f7f5fb4d6b3f96b9 \
+    --hash=sha256:9def736773fd56b305c0eef698be5192c77bfa30d55a0e5885f80126c4831a15 \
+    --hash=sha256:9dfbe56b299cf5875b68eb6f0ebaadc9cac520a1989cac0db0765abfb3709c19 \
+    --hash=sha256:9e851920caab2dbcae311fd28f4313c6953993893eb5c1bb367ec69d9a39e7ed \
+    --hash=sha256:9e8cb77286025bdb21be2941d64ac6ca016130bfdcd228739e8ab137eb4406ed \
+    --hash=sha256:a547e21c5610b7e9093d870be50682a6a6cf180d6da0f42c47c306073bfdbbf6 \
+    --hash=sha256:a90a13408a7a856b87be8a9f008fff53c5080eea4e4180f6c2e546e4a972fb5d \
+    --hash=sha256:a9a63785467b2d73635957d32a4f6e73d5e4df497a16a6392fa066b753e87387 \
+    --hash=sha256:aa81873e2c8c5aa616ab8e017a481a96742fdf9313c40f14338ca7dbf50cb55f \
+    --hash=sha256:ac64f4b2bdb4ea622175c9ab7cf09444e412e22c0e02e906978b3b488af5fde8 \
+    --hash=sha256:aea1f9741b603a8d8fedb0ed5502c2bc0accbc51f43e2ad1337fe7259c2b77a5 \
+    --hash=sha256:b0afb8cdd034150d4d9f53926226ed27ad15b7f465e93d7468caaf5eafae0d37 \
+    --hash=sha256:b37a04d9f52cb76b6b78f35109b513f6519efb481d8ca4c321f6a3b9580b3f45 \
+    --hash=sha256:b5f7a446ddaf6ca0fad9a5535b56fbfc29998bf0e0b450d174bbec0d600e1d72 \
+    --hash=sha256:b6d9e5a2ed9c4988c8f9b28b3bc0e3e5b1aaa10c28d210a594ff3a8c02742daf \
+    --hash=sha256:b6e2c12160c72aeda9d1283e612f68804621f448145a210f1bf1d79151c47090 \
+    --hash=sha256:b818a592bd69bfe437ee8368603d4a2d928c34cffcdf77c2e761a759ffd17d20 \
+    --hash=sha256:c1851f429b822831bd2edcbe0cfd12ee9ea77868f8d3daf267b189371671c80e \
+    --hash=sha256:c1fb0cda2abcc0ac62f64e2ea4b4e64c57dfd6b885e693095460c61bde7bb18e \
+    --hash=sha256:c5ab0ee51f560d179b057555b4f601b7df909ed31312d301b99f8b9fc6028284 \
+    --hash=sha256:c70d9ec912802ecfd6cd390dadb34a9578b04f9bcb8e863d0a7598ba5e9e7ccc \
+    --hash=sha256:c741107203954f6fc34d3066d213d0a0c40f7bb5aafd698fb39888af277c70d8 \
+    --hash=sha256:ca3f059f4ba485d90c8dc75cb5ca897e15325e4e609812ce57f896607c1c0867 \
+    --hash=sha256:caf51943715b12af827696ec395bfa68f090a4c1a1d2509eb4e2cb69abbbdb33 \
+    --hash=sha256:cb28c1f569f8d33b2b5dcd05d0e6ef7005d8639c54c2f0be824f05aedf715255 \
+    --hash=sha256:cdad4ea3b4513b475e027be79e5a0ceac8ee1c113a1a11e5edc3c30c29f964d8 \
+    --hash=sha256:cf47cfdabc2194a669dcf7a8dbba62e37a04c5041d2125fae0233b720da6f05c \
+    --hash=sha256:d04cab0a54b9dba4d278fe955a1390da3cf71f57feb78ddc7cb67cbe0bd30323 \
+    --hash=sha256:d422b945683e409000c888e384546dbab9009bb92f7c0b456e217988cf316107 \
+    --hash=sha256:d80bf832ac7b1920ee29a426cdca335f96a2b5caa839811803e999b41ba9030d \
+    --hash=sha256:da619979df60a940cd434084355c514c25cf8eb4cf9a508510682f6c851a4f7a \
+    --hash=sha256:dafd4c44b74aa4bed4b250f1aed165b8ef5de743bcca3b88fc9619b6087093d2 \
+    --hash=sha256:dca83c498b4650a91efcf7b88d669b170256bf8017a5db6f3e06c2bf031f57e0 \
+    --hash=sha256:de2713f48c1ad57f89ac25b3cb7daed2156d8e822cf0eca9b96a6f990718cc41 \
+    --hash=sha256:de4ed93a8c91debfd5a047be327b7cc8b0cc6afe32a716bbbc4aedca9e2a83af \
+    --hash=sha256:df52098cde6d5e02fa75c1f6244f07971773adb4a26625edd5c18fee906fa84d \
+    --hash=sha256:dfbf280da5f876d0b00c81f26bedce274e72a678c28845453885a9b3c22ae632 \
+    --hash=sha256:e3730a48e5622e598293eee0762b09cff34dd3f271530f47b0894891281f051d \
+    --hash=sha256:e5162afc9e0d1f9cae3b577d9c29ddbab3505ab39012cb794d94a005825bde21 \
+    --hash=sha256:e5d524d68a474a9688336045bbf76cb0def88549c1b2ad9dbfec1fb7cfbe9170 \
+    --hash=sha256:e99685fc95d386da368013e7fb4269dd39c30d99f812a8372d62f244f662709c \
+    --hash=sha256:ea89a2458a1a75f87caabefe789c87539ea4e43b40f18cff526052e35bbb4fdf \
+    --hash=sha256:ec671691e72dff75817386aa02d81e708b5a7ec0dec6669ec05213ff6b77e1bd \
+    --hash=sha256:eed5ac260dd545fbc20da5f4f15e7efe36a55e0e7cf706e4ec005b491a9546a0 \
+    --hash=sha256:f14440b9573a6f76b4ee4770c13f0b5921f71dde3b6fcb8dabbefd13b7fe05d7 \
+    --hash=sha256:f405c93675d8d4c5ac87364bb38d06c988e11028a64b52a47158a355079661f3 \
+    --hash=sha256:f53ec51f9d24e9638a40cabb95078ade8c99251945dad8d57bf4aabe86ecee35 \
+    --hash=sha256:f61a9326f80ca59214d1cceb0a09bb2ece5b2563d4e0cd37bfd5515c28510674 \
+    --hash=sha256:f7bf2496fa563c046d05e4d232d7b7fd61346e2402052064b773e5c378bf6f73 \
+    --hash=sha256:fbaa70553ca116c77717f513e08815aec458e6b69a028d4028d403b3bc84ff37 \
+    --hash=sha256:fc3e55a7db08dc9a6ed5fb7103019d2c1a38a349ac41901f9f66d7f95750942f \
+    --hash=sha256:fc921b96fa95a097add244da36a1d9e4f3039160d1d30f1b35837bf108c21136 \
+    --hash=sha256:fd0641abca296bc1a00183fe44f7fced8807ed49d501f188faa642d0e4975b83 \
+    --hash=sha256:feac1045b3327a45944e7dcbeb57530339f6b17baff154df51ef8b0da34c8c12 \
+    --hash=sha256:ff110acded3c22c033e637dd8896e411c7d3a11289b2edf041f86663dbc791e9
     # via
     #   jsonschema
     #   referencing
@@ -427,9 +456,9 @@ tomli==2.2.1 \
     --hash=sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a \
     --hash=sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7
     # via -r requirements.in
-typing-extensions==4.13.2 \
-    --hash=sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c \
-    --hash=sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef
+typing-extensions==4.14.1 \
+    --hash=sha256:38b39f4aeeab64884ce9f74c94263ef78f3c22467c8724005483154c26648d36 \
+    --hash=sha256:d1e1e3b58374dc93031d6eda2420a48ea44a36c2b4766a4fdeb3710755731d76
     # via -r requirements.in
 urllib3==2.5.0 \
     --hash=sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760 \

From f39d4ebe840c05036ed6d2e01a346abc80dfd642 Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Tue, 8 Jul 2025 15:36:07 -0500
Subject: [PATCH 134/157] Bump to 3.14.0b4 (#689)

---
 cpython-unix/build-cpython.sh           |  7 +-
 cpython-unix/patch-jit-cflags-314.patch | 90 -------------------------
 pythonbuild/downloads.py                |  8 +--
 3 files changed, 6 insertions(+), 99 deletions(-)
 delete mode 100644 cpython-unix/patch-jit-cflags-314.patch

diff --git a/cpython-unix/build-cpython.sh b/cpython-unix/build-cpython.sh
index 4a85ba73..cc93f0ad 100755
--- a/cpython-unix/build-cpython.sh
+++ b/cpython-unix/build-cpython.sh
@@ -480,11 +480,8 @@ if [ -n "${CPYTHON_OPTIMIZED}" ]; then
 
         # Respect CFLAGS during JIT compilation.
         #
-        # Backports https://github.com/python/cpython/pull/134276 which we're trying to get released
-        # in 3.14, but is currently only in 3.15+.
-        if [ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_14}" ]; then
-            patch -p1 -i ${ROOT}/patch-jit-cflags-314.patch
-        elif [ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_13}" ]; then
+        # Backports https://github.com/python/cpython/pull/134276
+        if [[ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_13}" && -n "${PYTHON_MEETS_MAXIMUM_VERSION_3_13}" ]]; then
             patch -p1 -i ${ROOT}/patch-jit-cflags-313.patch
         fi
 
diff --git a/cpython-unix/patch-jit-cflags-314.patch b/cpython-unix/patch-jit-cflags-314.patch
deleted file mode 100644
index a75563b4..00000000
--- a/cpython-unix/patch-jit-cflags-314.patch
+++ /dev/null
@@ -1,90 +0,0 @@
-diff --git a/Misc/NEWS.d/next/Build/2025-05-19-18-09-20.gh-issue-134273.ZAliyy.rst b/Misc/NEWS.d/next/Build/2025-05-19-18-09-20.gh-issue-134273.ZAliyy.rst
-new file mode 100644
-index 00000000000..3eb13cefbe6
---- /dev/null
-+++ b/Misc/NEWS.d/next/Build/2025-05-19-18-09-20.gh-issue-134273.ZAliyy.rst
-@@ -0,0 +1 @@
-+Add support for configuring compiler flags for the JIT with ``CFLAGS_JIT``
-diff --git a/Tools/jit/_targets.py b/Tools/jit/_targets.py
-index d0a1c081ffe..b383e39da19 100644
---- a/Tools/jit/_targets.py
-+++ b/Tools/jit/_targets.py
-@@ -10,6 +10,7 @@
- import sys
- import tempfile
- import typing
-+import shlex
- 
- import _llvm
- import _schema
-@@ -46,6 +47,7 @@ class _Target(typing.Generic[_S, _R]):
-     stable: bool = False
-     debug: bool = False
-     verbose: bool = False
-+    cflags: str = ""
-     known_symbols: dict[str, int] = dataclasses.field(default_factory=dict)
-     pyconfig_dir: pathlib.Path = pathlib.Path.cwd().resolve()
- 
-@@ -62,6 +64,7 @@ def _compute_digest(self) -> str:
-         hasher = hashlib.sha256()
-         hasher.update(self.triple.encode())
-         hasher.update(self.debug.to_bytes())
-+        hasher.update(self.cflags.encode())
-         # These dependencies are also reflected in _JITSources in regen.targets:
-         hasher.update(PYTHON_EXECUTOR_CASES_C_H.read_bytes())
-         hasher.update((self.pyconfig_dir / "pyconfig.h").read_bytes())
-@@ -155,6 +158,8 @@ async def _compile(
-             f"{o}",
-             f"{c}",
-             *self.args,
-+            # Allow user-provided CFLAGS to override any defaults
-+            *shlex.split(self.cflags),
-         ]
-         await _llvm.run("clang", args, echo=self.verbose)
-         return await self._parse(o)
-diff --git a/Tools/jit/build.py b/Tools/jit/build.py
-index 1afd0c76bad..a0733005929 100644
---- a/Tools/jit/build.py
-+++ b/Tools/jit/build.py
-@@ -39,11 +39,15 @@
-     parser.add_argument(
-         "-v", "--verbose", action="store_true", help="echo commands as they are run"
-     )
-+    parser.add_argument(
-+        "--cflags", help="additional flags to pass to the compiler", default=""
-+    )
-     args = parser.parse_args()
-     for target in args.target:
-         target.debug = args.debug
-         target.force = args.force
-         target.verbose = args.verbose
-+        target.cflags = args.cflags
-         target.pyconfig_dir = args.pyconfig_dir
-         target.build(
-             comment=comment,
-diff --git a/configure b/configure
-index 029bf527da4..fef9f2d7da9 100755
---- a/configure
-+++ b/configure
-@@ -10863,7 +10863,7 @@ then :
- 
- else case e in #(
-   e) as_fn_append CFLAGS_NODIST " $jit_flags"
--           REGEN_JIT_COMMAND="\$(PYTHON_FOR_REGEN) \$(srcdir)/Tools/jit/build.py ${ARCH_TRIPLES:-$host} --output-dir . --pyconfig-dir ."
-+           REGEN_JIT_COMMAND="\$(PYTHON_FOR_REGEN) \$(srcdir)/Tools/jit/build.py ${ARCH_TRIPLES:-$host} --output-dir . --pyconfig-dir . --cflags=\"$CFLAGS_JIT\""
-            JIT_STENCILS_H="jit_stencils.h"
-            if test "x$Py_DEBUG" = xtrue
- then :
-diff --git a/configure.ac b/configure.ac
-index 371b2e8ed73..cc37a636c52 100644
---- a/configure.ac
-+++ b/configure.ac
-@@ -2776,7 +2776,7 @@ AS_VAR_IF([jit_flags],
-           [],
-           [AS_VAR_APPEND([CFLAGS_NODIST], [" $jit_flags"])
-            AS_VAR_SET([REGEN_JIT_COMMAND],
--                      ["\$(PYTHON_FOR_REGEN) \$(srcdir)/Tools/jit/build.py ${ARCH_TRIPLES:-$host} --output-dir . --pyconfig-dir ."])
-+                      ["\$(PYTHON_FOR_REGEN) \$(srcdir)/Tools/jit/build.py ${ARCH_TRIPLES:-$host} --output-dir . --pyconfig-dir . --cflags=\"$CFLAGS_JIT\""])
-            AS_VAR_SET([JIT_STENCILS_H], ["jit_stencils.h"])
-            AS_VAR_IF([Py_DEBUG],
-                      [true],
diff --git a/pythonbuild/downloads.py b/pythonbuild/downloads.py
index a208ce56..20d5c98a 100644
--- a/pythonbuild/downloads.py
+++ b/pythonbuild/downloads.py
@@ -82,10 +82,10 @@
         "python_tag": "cp313",
     },
     "cpython-3.14": {
-        "url": "https://www.python.org/ftp/python/3.14.0/Python-3.14.0b3.tar.xz",
-        "size": 23626928,
-        "sha256": "c6f48bf51f01f50d87007a445dd7afe4a4c7a87ab482570be924c1ddfd0d3682",
-        "version": "3.14.0b3",
+        "url": "https://www.python.org/ftp/python/3.14.0/Python-3.14.0b4.tar.xz",
+        "size": 23641472,
+        "sha256": "15e123e056abebba6de5e73cfa304459a8c82cafa85d4fc7fc6de80e6a3e1b39",
+        "version": "3.14.0b4",
         "licenses": ["Python-2.0", "CNRI-Python"],
         "license_file": "LICENSE.cpython.txt",
         "python_tag": "cp314",

From e996271b4ac836282d9f7d997b0ef8ecfca34336 Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Wed, 9 Jul 2025 07:24:56 -0500
Subject: [PATCH 135/157] Drop `.sha256` files from releases (#691)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

GitHub has started enforcing a 1000 file limit, which breaks us.

I first encountered it in CI during the release:
https://github.com/astral-sh/python-build-standalone/actions/runs/16156480423

Then got to an actual error message via the CLI:

```
❯ gh release upload 20250708 dist/cpython-3.14.0b4-riscv64-unknown-linux-gnu-freethreaded+lto-20250708T1536.tar.zst
HTTP 422: Validation Failed (https://uploads.github.com/repos/astral-sh/python-build-standalone/releases/230978017/assets?label=&name=cpython-3.14.0b4-riscv64-unknown-linux-gnu-freethreaded%2Blto-20250708T1536.tar.zst)
file_count limited to 1000 assets per release
```

You can see they documented a limit recently:


https://docs.github.com/en/repositories/releasing-projects-on-github/about-releases#storage-and-bandwidth-quotas


https://web.archive.org/web/20250629152715/https://docs.github.com/en/repositories/releasing-projects-on-github/about-releases
---
 src/github.rs | 8 --------
 1 file changed, 8 deletions(-)

diff --git a/src/github.rs b/src/github.rs
index 0d3bc971..2dfbba58 100644
--- a/src/github.rs
+++ b/src/github.rs
@@ -505,14 +505,6 @@ pub async fn command_upload_release_distributions(args: &ArgMatches) -> Result<(
                 file_data,
                 dry_run,
             ));
-            fs.push(upload_release_artifact(
-                &raw_client,
-                token.clone(),
-                &release,
-                format!("{}.sha256", dest),
-                Bytes::copy_from_slice(format!("{}\n", digest).as_bytes()),
-                dry_run,
-            ));
         }
 
         let mut buffered = futures::stream::iter(fs).buffer_unordered(16);

From 62461bd628e8e6d0b406f4486222e388ba9d2724 Mon Sep 17 00:00:00 2001
From: Geoffrey Thomas <geofft@ldpreload.com>
Date: Thu, 10 Jul 2025 17:24:39 -0400
Subject: [PATCH 136/157] Add missing Makefile dependency for binutils -> gcc
 image (#692)

This was unintentionally removed in 21cf744dda2d0e19329950a81a07d9067179f976.
---
 cpython-unix/Makefile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/cpython-unix/Makefile b/cpython-unix/Makefile
index dcb239aa..40c34a27 100644
--- a/cpython-unix/Makefile
+++ b/cpython-unix/Makefile
@@ -79,7 +79,7 @@ $(OUTDIR)/image-%.$(HOST_PLATFORM).tar: $(OUTDIR)/%.Dockerfile
 	$(RUN_BUILD) --toolchain image-$*
 endif
 
-$(OUTDIR)/binutils-$(BINUTILS_VERSION)-$(HOST_PLATFORM).tar: $(HERE)/build-binutils.sh
+$(OUTDIR)/binutils-$(BINUTILS_VERSION)-$(HOST_PLATFORM).tar: $(OUTDIR)/image-$(DOCKER_IMAGE_GCC).$(HOST_PLATFORM).tar $(HERE)/build-binutils.sh
 	$(RUN_BUILD) --toolchain --docker-image $(DOCKER_IMAGE_GCC) binutils
 
 $(OUTDIR)/$(CLANG_FILENAME):

From 7797c3898aa2cc03f6b92dc1370f6e8fd0797345 Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Fri, 11 Jul 2025 10:39:07 -0500
Subject: [PATCH 137/157] Enable fts4, fts5, rtree, and geopoly in SQLite
 (#694)

And add some regression tests.

Co-authored-by: Geoffrey Thomas <geofft@ldpreload.com>
---
 cpython-unix/build-sqlite.sh | 14 +++++++++++++-
 src/verify_distribution.py   |  9 +++++++++
 2 files changed, 22 insertions(+), 1 deletion(-)

diff --git a/cpython-unix/build-sqlite.sh b/cpython-unix/build-sqlite.sh
index e01e3077..ef7c6a63 100755
--- a/cpython-unix/build-sqlite.sh
+++ b/cpython-unix/build-sqlite.sh
@@ -27,7 +27,19 @@ fi
 # it's not looked for.
 unset CXX
 
-CC_FOR_BUILD="${HOST_CC}" CFLAGS="${EXTRA_TARGET_CFLAGS} -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_FTS3_PARENTHESIS -DSQLITE_ENABLE_FTS3_TOKENIZER -fPIC" CPPFLAGS="${EXTRA_TARGET_CFLAGS} -fPIC" LDFLAGS="${EXTRA_TARGET_LDFLAGS}" ./configure ${CONFIGURE_FLAGS}
+CC_FOR_BUILD="${HOST_CC}" \
+CFLAGS="${EXTRA_TARGET_CFLAGS} \
+    -DSQLITE_ENABLE_DBSTAT_VTAB \
+    -DSQLITE_ENABLE_FTS3 \
+    -DSQLITE_ENABLE_FTS3_PARENTHESIS \
+    -DSQLITE_ENABLE_FTS3_TOKENIZER \
+    -DSQLITE_ENABLE_FTS4 \
+    -DSQLITE_ENABLE_FTS5 \
+    -DSQLITE_ENABLE_GEOPOLY \
+    -DSQLITE_ENABLE_RTREE \
+    -fPIC" \
+CPPFLAGS="${EXTRA_TARGET_CFLAGS} -fPIC" \
+LDFLAGS="${EXTRA_TARGET_LDFLAGS}" ./configure ${CONFIGURE_FLAGS}
 
 make -j ${NUM_CPUS} libsqlite3.a
 make install-lib DESTDIR=${ROOT}/out
diff --git a/src/verify_distribution.py b/src/verify_distribution.py
index 1ac2381f..d516f3a4 100644
--- a/src/verify_distribution.py
+++ b/src/verify_distribution.py
@@ -122,6 +122,15 @@ def test_sqlite(self):
         self.assertTrue(hasattr(conn, "enable_load_extension"))
         # Backup feature requires modern SQLite, which we always have.
         self.assertTrue(hasattr(conn, "backup"))
+        # Ensure that various extensions are present. These will raise
+        # if they are not.
+        cursor = conn.cursor()
+        cursor.execute("CREATE VIRTUAL TABLE fts3 USING fts3(sender, title, body);")
+        cursor.execute("CREATE VIRTUAL TABLE fts4 USING fts4(sender, title, body);")
+        cursor.execute("CREATE VIRTUAL TABLE fts5 USING fts5(sender, title, body);")
+        cursor.execute("CREATE VIRTUAL TABLE geopoly USING geopoly();")
+        cursor.execute("CREATE VIRTUAL TABLE rtree USING rtree(id, minX, maxX);")
+        conn.close()
 
     def test_ssl(self):
         import ssl

From 69c7662d877e7bc899ad46658662a5320ac3f93a Mon Sep 17 00:00:00 2001
From: Geoffrey Thomas <geofft@ldpreload.com>
Date: Sun, 29 Jun 2025 13:31:54 -0400
Subject: [PATCH 138/157] For non-release CI, upload before validating

This allows downloading and poking at build artifacts that fail validation.

Now the order of tasks for all platforms is the same: build, upload
attestations, upload artifacts, validate. (This was already the order for
macos.)
---
 .github/workflows/linux.yml   | 52 +++++++++++++++++------------------
 .github/workflows/windows.yml | 12 ++++----
 2 files changed, 32 insertions(+), 32 deletions(-)

diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml
index d4602fbe..39bc8733 100644
--- a/.github/workflows/linux.yml
+++ b/.github/workflows/linux.yml
@@ -249,6 +249,19 @@ jobs:
 
           ./build-linux.py --target-triple ${{ matrix.target_triple }} --python cpython-${{ matrix.python }} --options ${{ matrix.build_options }}
 
+      - name: Generate attestations
+        uses: actions/attest-build-provenance@v2
+        if: ${{ github.ref == 'refs/heads/main' }}
+        with:
+          subject-path: dist/*
+
+      - name: Upload Distribution
+        if: ${{ ! matrix.dry-run }}
+        uses: actions/upload-artifact@v4
+        with:
+          name: cpython-${{ matrix.python }}-${{ matrix.target_triple }}-${{ matrix.build_options }}
+          path: dist/*
+
       - name: Validate Distribution
         if: ${{ ! matrix.dry-run }}
         run: |
@@ -267,19 +280,6 @@ jobs:
 
           build/pythonbuild validate-distribution ${EXTRA_ARGS} dist/*.tar.zst
 
-      - name: Generate attestations
-        uses: actions/attest-build-provenance@v2
-        if: ${{ github.ref == 'refs/heads/main' }}
-        with:
-          subject-path: dist/*
-
-      - name: Upload Distribution
-        if: ${{ ! matrix.dry-run }}
-        uses: actions/upload-artifact@v4
-        with:
-          name: cpython-${{ matrix.python }}-${{ matrix.target_triple }}-${{ matrix.build_options }}
-          path: dist/*
-
   build-1:
     needs:
       - generate-matrix
@@ -349,6 +349,19 @@ jobs:
 
           ./build-linux.py --target-triple ${{ matrix.target_triple }} --python cpython-${{ matrix.python }} --options ${{ matrix.build_options }}
 
+      - name: Generate attestations
+        uses: actions/attest-build-provenance@v2
+        if: ${{ github.ref == 'refs/heads/main' }}
+        with:
+          subject-path: dist/*
+
+      - name: Upload Distribution
+        if: ${{ ! matrix.dry-run }}
+        uses: actions/upload-artifact@v4
+        with:
+          name: cpython-${{ matrix.python }}-${{ matrix.target_triple }}-${{ matrix.build_options }}
+          path: dist/*
+
       - name: Validate Distribution
         if: ${{ ! matrix.dry-run }}
         run: |
@@ -366,16 +379,3 @@ jobs:
           fi
 
           build/pythonbuild validate-distribution ${EXTRA_ARGS} dist/*.tar.zst
-
-      - name: Generate attestations
-        uses: actions/attest-build-provenance@v2
-        if: ${{ github.ref == 'refs/heads/main' }}
-        with:
-          subject-path: dist/*
-
-      - name: Upload Distribution
-        if: ${{ ! matrix.dry-run }}
-        uses: actions/upload-artifact@v4
-        with:
-          name: cpython-${{ matrix.python }}-${{ matrix.target_triple }}-${{ matrix.build_options }}
-          path: dist/*
diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml
index e285fac3..165ff261 100644
--- a/.github/workflows/windows.yml
+++ b/.github/workflows/windows.yml
@@ -146,12 +146,6 @@ jobs:
           call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\${{ matrix.vcvars }}"
           py.exe -3.12 build-windows.py --python cpython-${{ matrix.python }} --sh c:\cygwin\bin\sh.exe --options ${{ matrix.build_options }}
 
-      - name: Validate Distribution
-        if: ${{ ! matrix.dry-run }}
-        run: |
-          $Dists = Resolve-Path -Path "dist/*.tar.zst" -Relative
-          .\pythonbuild.exe validate-distribution --run $Dists
-
       - name: Generate attestations
         uses: actions/attest-build-provenance@v2
         if: ${{ github.ref == 'refs/heads/main' }}
@@ -163,3 +157,9 @@ jobs:
         with:
           name: cpython-${{ matrix.python }}-${{ matrix.vcvars }}-${{ matrix.build_options }}
           path: dist/*
+
+      - name: Validate Distribution
+        if: ${{ ! matrix.dry-run }}
+        run: |
+          $Dists = Resolve-Path -Path "dist/*.tar.zst" -Relative
+          .\pythonbuild.exe validate-distribution --run $Dists

From 6fd593c4b55c3e5e7dc3831bf97b8538aad8a815 Mon Sep 17 00:00:00 2001
From: Geoffrey Thomas <geofft@ldpreload.com>
Date: Fri, 11 Jul 2025 12:39:06 -0400
Subject: [PATCH 139/157] Skip sqlite3 geopoly test on Windows

---
 src/verify_distribution.py | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/src/verify_distribution.py b/src/verify_distribution.py
index d516f3a4..9773471b 100644
--- a/src/verify_distribution.py
+++ b/src/verify_distribution.py
@@ -128,8 +128,12 @@ def test_sqlite(self):
         cursor.execute("CREATE VIRTUAL TABLE fts3 USING fts3(sender, title, body);")
         cursor.execute("CREATE VIRTUAL TABLE fts4 USING fts4(sender, title, body);")
         cursor.execute("CREATE VIRTUAL TABLE fts5 USING fts5(sender, title, body);")
-        cursor.execute("CREATE VIRTUAL TABLE geopoly USING geopoly();")
         cursor.execute("CREATE VIRTUAL TABLE rtree USING rtree(id, minX, maxX);")
+        if os.name != "nt":
+            # TODO(geofft): not sure why this isn't present in the prebuilt
+            # sqlite3 Windows library from CPython upstream, it seems weird to
+            # be inconsistent across platforms, but that's the status quo
+            cursor.execute("CREATE VIRTUAL TABLE geopoly USING geopoly();")
         conn.close()
 
     def test_ssl(self):

From ffffa3d94592dda8a10fd59bbbbf5e1576d6558b Mon Sep 17 00:00:00 2001
From: Geoffrey Thomas <geofft@ldpreload.com>
Date: Fri, 11 Jul 2025 16:12:21 -0400
Subject: [PATCH 140/157] Further fix sqlite test cases (#701)

---
 src/verify_distribution.py | 25 ++++++++++++++-----------
 1 file changed, 14 insertions(+), 11 deletions(-)

diff --git a/src/verify_distribution.py b/src/verify_distribution.py
index 9773471b..65cd084a 100644
--- a/src/verify_distribution.py
+++ b/src/verify_distribution.py
@@ -122,18 +122,21 @@ def test_sqlite(self):
         self.assertTrue(hasattr(conn, "enable_load_extension"))
         # Backup feature requires modern SQLite, which we always have.
         self.assertTrue(hasattr(conn, "backup"))
-        # Ensure that various extensions are present. These will raise
-        # if they are not.
-        cursor = conn.cursor()
-        cursor.execute("CREATE VIRTUAL TABLE fts3 USING fts3(sender, title, body);")
-        cursor.execute("CREATE VIRTUAL TABLE fts4 USING fts4(sender, title, body);")
-        cursor.execute("CREATE VIRTUAL TABLE fts5 USING fts5(sender, title, body);")
-        cursor.execute("CREATE VIRTUAL TABLE rtree USING rtree(id, minX, maxX);")
+        # Ensure that various extensions are present. These will raise if they are not. Note that
+        # CPython upstream carries configuration flags for the Windows build, so geopoly is missing
+        # on all versions and rtree is missing in 3.9. On non-Windows platforms, we configure
+        # SQLite ourselves. We might want to patch the build to enable these on Windows, see #666.
+        extensions = ["fts3", "fts4", "fts5"]
         if os.name != "nt":
-            # TODO(geofft): not sure why this isn't present in the prebuilt
-            # sqlite3 Windows library from CPython upstream, it seems weird to
-            # be inconsistent across platforms, but that's the status quo
-            cursor.execute("CREATE VIRTUAL TABLE geopoly USING geopoly();")
+            extensions.append("geopoly")
+        if os.name == "nt" and sys.version_info[0:2] >= (3, 9):
+            extensions.append("rtree")
+        cursor = conn.cursor()
+        for extension in extensions:
+            with self.subTest(extension=extension):
+                cursor.execute(
+                    f"CREATE VIRTUAL TABLE test{extension} USING {extension}(a, b, c);"
+                )
         conn.close()
 
     def test_ssl(self):

From 6857d7f7c20b89f02b5581caf778b047f5f4be41 Mon Sep 17 00:00:00 2001
From: Geoffrey Thomas <geofft@ldpreload.com>
Date: Fri, 11 Jul 2025 16:17:11 -0400
Subject: [PATCH 141/157] typo (#702)

---
 src/verify_distribution.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/verify_distribution.py b/src/verify_distribution.py
index 65cd084a..9dc27400 100644
--- a/src/verify_distribution.py
+++ b/src/verify_distribution.py
@@ -129,7 +129,7 @@ def test_sqlite(self):
         extensions = ["fts3", "fts4", "fts5"]
         if os.name != "nt":
             extensions.append("geopoly")
-        if os.name == "nt" and sys.version_info[0:2] >= (3, 9):
+        if os.name != "nt" or sys.version_info[0:2] >= (3, 9):
             extensions.append("rtree")
         cursor = conn.cursor()
         for extension in extensions:

From 684cb94f5c4dd22e1591832532c041110b7f6f90 Mon Sep 17 00:00:00 2001
From: Geoffrey Thomas <geofft@ldpreload.com>
Date: Fri, 11 Jul 2025 18:20:15 -0400
Subject: [PATCH 142/157] typo (#703)

---
 src/verify_distribution.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/verify_distribution.py b/src/verify_distribution.py
index 9dc27400..d6e428d6 100644
--- a/src/verify_distribution.py
+++ b/src/verify_distribution.py
@@ -129,7 +129,7 @@ def test_sqlite(self):
         extensions = ["fts3", "fts4", "fts5"]
         if os.name != "nt":
             extensions.append("geopoly")
-        if os.name != "nt" or sys.version_info[0:2] >= (3, 9):
+        if os.name != "nt" or sys.version_info[0:2] > (3, 9):
             extensions.append("rtree")
         cursor = conn.cursor()
         for extension in extensions:

From 174daa6f039587d2e9488eeccc8d0d7e4573e45a Mon Sep 17 00:00:00 2001
From: Simon Lamon <32477463+silamon@users.noreply.github.com>
Date: Tue, 22 Jul 2025 02:11:47 +0200
Subject: [PATCH 143/157] Update rust dependencies (octocrab & object) (#705)

There are some dependencies with breaking or deprecated changes.
These have been upgraded in this PR applying the breaking changes.
It should unlock
https://github.com/astral-sh/python-build-standalone/pull/633
---
 Cargo.lock        | 188 +++++++++++++++++-----------------------------
 Cargo.toml        |   4 +-
 src/github.rs     |   4 +-
 src/validation.rs |   2 +-
 4 files changed, 72 insertions(+), 126 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index b0db1676..dcb95c77 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -263,8 +263,10 @@ checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825"
 dependencies = [
  "android-tzdata",
  "iana-time-zone",
+ "js-sys",
  "num-traits",
  "serde",
+ "wasm-bindgen",
  "windows-targets",
 ]
 
@@ -327,6 +329,16 @@ dependencies = [
  "libc",
 ]
 
+[[package]]
+name = "core-foundation"
+version = "0.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6"
+dependencies = [
+ "core-foundation-sys",
+ "libc",
+]
+
 [[package]]
 name = "core-foundation-sys"
 version = "0.8.7"
@@ -395,17 +407,6 @@ dependencies = [
  "powerfmt",
 ]
 
-[[package]]
-name = "derive_more"
-version = "0.99.19"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3da29a38df43d6f156149c9b43ded5e018ddff2a855cf2cfd62e8cd7d079c69f"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
 [[package]]
 name = "digest"
 version = "0.10.7"
@@ -782,25 +783,6 @@ dependencies = [
  "want",
 ]
 
-[[package]]
-name = "hyper-rustls"
-version = "0.26.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a0bea761b46ae2b24eb4aef630d8d1c398157b6fc29e6350ecf090a0b70c952c"
-dependencies = [
- "futures-util",
- "http",
- "hyper",
- "hyper-util",
- "log",
- "rustls 0.22.4",
- "rustls-native-certs",
- "rustls-pki-types",
- "tokio",
- "tokio-rustls 0.25.0",
- "tower-service",
-]
-
 [[package]]
 name = "hyper-rustls"
 version = "0.27.5"
@@ -811,10 +793,12 @@ dependencies = [
  "http",
  "hyper",
  "hyper-util",
- "rustls 0.23.22",
+ "log",
+ "rustls",
+ "rustls-native-certs",
  "rustls-pki-types",
  "tokio",
- "tokio-rustls 0.26.1",
+ "tokio-rustls",
  "tower-service",
  "webpki-roots",
 ]
@@ -1217,7 +1201,7 @@ dependencies = [
  "openssl-probe",
  "openssl-sys",
  "schannel",
- "security-framework",
+ "security-framework 2.11.1",
  "security-framework-sys",
  "tempfile",
 ]
@@ -1264,29 +1248,29 @@ dependencies = [
 
 [[package]]
 name = "object"
-version = "0.32.2"
+version = "0.36.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441"
+checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87"
 dependencies = [
- "flate2",
  "memchr",
- "ruzstd",
 ]
 
 [[package]]
 name = "object"
-version = "0.36.7"
+version = "0.37.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87"
+checksum = "03fd943161069e1768b4b3d050890ba48730e590f57e56d4aa04e7e090e61b4a"
 dependencies = [
+ "flate2",
  "memchr",
+ "ruzstd",
 ]
 
 [[package]]
 name = "octocrab"
-version = "0.34.3"
+version = "0.44.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1c4e00a4268539fda6c431a0fd01d016d4b44c361f9c283d0eb8f1ab7408a517"
+checksum = "86996964f8b721067b6ed238aa0ccee56ecad6ee5e714468aa567992d05d2b91"
 dependencies = [
  "arc-swap",
  "async-trait",
@@ -1302,7 +1286,7 @@ dependencies = [
  "http-body",
  "http-body-util",
  "hyper",
- "hyper-rustls 0.26.0",
+ "hyper-rustls",
  "hyper-timeout",
  "hyper-util",
  "jsonwebtoken",
@@ -1316,10 +1300,11 @@ dependencies = [
  "serde_urlencoded",
  "snafu",
  "tokio",
- "tower 0.4.13",
+ "tower",
  "tower-http",
  "tracing",
  "url",
+ "web-time",
 ]
 
 [[package]]
@@ -1567,7 +1552,7 @@ dependencies = [
  "hyper",
  "hyper-util",
  "normalize-path",
- "object 0.32.2",
+ "object 0.37.1",
  "octocrab",
  "once_cell",
  "pdb",
@@ -1611,7 +1596,7 @@ dependencies = [
  "quinn-proto",
  "quinn-udp",
  "rustc-hash",
- "rustls 0.23.22",
+ "rustls",
  "socket2",
  "thiserror 2.0.11",
  "tokio",
@@ -1629,7 +1614,7 @@ dependencies = [
  "rand",
  "ring",
  "rustc-hash",
- "rustls 0.23.22",
+ "rustls",
  "rustls-pki-types",
  "slab",
  "thiserror 2.0.11",
@@ -1745,7 +1730,7 @@ dependencies = [
  "http-body",
  "http-body-util",
  "hyper",
- "hyper-rustls 0.27.5",
+ "hyper-rustls",
  "hyper-tls",
  "hyper-util",
  "ipnet",
@@ -1757,7 +1742,7 @@ dependencies = [
  "percent-encoding",
  "pin-project-lite",
  "quinn",
- "rustls 0.23.22",
+ "rustls",
  "rustls-pemfile",
  "rustls-pki-types",
  "serde",
@@ -1767,9 +1752,9 @@ dependencies = [
  "system-configuration",
  "tokio",
  "tokio-native-tls",
- "tokio-rustls 0.26.1",
+ "tokio-rustls",
  "tokio-util",
- "tower 0.5.2",
+ "tower",
  "tower-service",
  "url",
  "wasm-bindgen",
@@ -1865,26 +1850,13 @@ dependencies = [
  "windows-sys 0.59.0",
 ]
 
-[[package]]
-name = "rustls"
-version = "0.22.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bf4ef73721ac7bcd79b2b315da7779d8fc09718c6b3d2d1b2d94850eb8c18432"
-dependencies = [
- "log",
- "ring",
- "rustls-pki-types",
- "rustls-webpki",
- "subtle",
- "zeroize",
-]
-
 [[package]]
 name = "rustls"
 version = "0.23.22"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9fb9263ab4eb695e42321db096e3b8fbd715a59b154d5c88d82db2175b681ba7"
 dependencies = [
+ "log",
  "once_cell",
  "ring",
  "rustls-pki-types",
@@ -1895,15 +1867,14 @@ dependencies = [
 
 [[package]]
 name = "rustls-native-certs"
-version = "0.7.3"
+version = "0.8.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e5bfb394eeed242e909609f56089eecfe5fda225042e8b171791b9c95f5931e5"
+checksum = "7fcff2dd52b58a8d98a70243663a0d234c4e2b79235637849d15913394a247d3"
 dependencies = [
  "openssl-probe",
- "rustls-pemfile",
  "rustls-pki-types",
  "schannel",
- "security-framework",
+ "security-framework 3.2.0",
 ]
 
 [[package]]
@@ -1943,12 +1914,10 @@ checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4"
 
 [[package]]
 name = "ruzstd"
-version = "0.5.0"
+version = "0.8.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "58c4eb8a81997cf040a091d1f7e1938aeab6749d3a0dfa73af43cdc32393483d"
+checksum = "3640bec8aad418d7d03c72ea2de10d5c646a598f9883c7babc160d91e3c1b26c"
 dependencies = [
- "byteorder",
- "derive_more",
  "twox-hash",
 ]
 
@@ -2001,9 +1970,9 @@ dependencies = [
 
 [[package]]
 name = "secrecy"
-version = "0.8.0"
+version = "0.10.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9bd1c54ea06cfd2f6b63219704de0b9b4f72dcc2b8fdef820be6cd799780e91e"
+checksum = "e891af845473308773346dc847b2c23ee78fe442e0472ac50e22a18a93d3ae5a"
 dependencies = [
  "zeroize",
 ]
@@ -2015,7 +1984,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02"
 dependencies = [
  "bitflags 2.8.0",
- "core-foundation",
+ "core-foundation 0.9.4",
+ "core-foundation-sys",
+ "libc",
+ "security-framework-sys",
+]
+
+[[package]]
+name = "security-framework"
+version = "3.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "271720403f46ca04f7ba6f55d438f8bd878d6b8ca0a1046e8228c4145bcbb316"
+dependencies = [
+ "bitflags 2.8.0",
+ "core-foundation 0.10.1",
  "core-foundation-sys",
  "libc",
  "security-framework-sys",
@@ -2206,12 +2188,6 @@ version = "1.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
 
-[[package]]
-name = "static_assertions"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
-
 [[package]]
 name = "strsim"
 version = "0.11.1"
@@ -2262,7 +2238,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b"
 dependencies = [
  "bitflags 2.8.0",
- "core-foundation",
+ "core-foundation 0.9.4",
  "system-configuration-sys",
 ]
 
@@ -2433,24 +2409,13 @@ dependencies = [
  "tokio",
 ]
 
-[[package]]
-name = "tokio-rustls"
-version = "0.25.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "775e0c0f0adb3a2f22a00c4745d728b479985fc15ee7ca6a2608388c5569860f"
-dependencies = [
- "rustls 0.22.4",
- "rustls-pki-types",
- "tokio",
-]
-
 [[package]]
 name = "tokio-rustls"
 version = "0.26.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "5f6d0975eaace0cf0fcadee4e4aaa5da15b5c079146f2cffb67c113be122bf37"
 dependencies = [
- "rustls 0.23.22",
+ "rustls",
  "tokio",
 ]
 
@@ -2467,23 +2432,6 @@ dependencies = [
  "tokio",
 ]
 
-[[package]]
-name = "tower"
-version = "0.4.13"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c"
-dependencies = [
- "futures-core",
- "futures-util",
- "pin-project",
- "pin-project-lite",
- "tokio",
- "tokio-util",
- "tower-layer",
- "tower-service",
- "tracing",
-]
-
 [[package]]
 name = "tower"
 version = "0.5.2"
@@ -2495,25 +2443,26 @@ dependencies = [
  "pin-project-lite",
  "sync_wrapper",
  "tokio",
+ "tokio-util",
  "tower-layer",
  "tower-service",
+ "tracing",
 ]
 
 [[package]]
 name = "tower-http"
-version = "0.5.2"
+version = "0.6.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e9cd434a998747dd2c4276bc96ee2e0c7a2eadf3cae88e52be55a05fa9053f5"
+checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2"
 dependencies = [
  "bitflags 2.8.0",
  "bytes",
  "futures-util",
  "http",
  "http-body",
- "http-body-util",
  "iri-string",
  "pin-project-lite",
- "tower 0.4.13",
+ "tower",
  "tower-layer",
  "tower-service",
  "tracing",
@@ -2571,13 +2520,9 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
 
 [[package]]
 name = "twox-hash"
-version = "1.6.3"
+version = "2.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675"
-dependencies = [
- "cfg-if",
- "static_assertions",
-]
+checksum = "8b907da542cbced5261bd3256de1b3a1bf340a3d37f93425a07362a1d687de56"
 
 [[package]]
 name = "typenum"
@@ -2809,6 +2754,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb"
 dependencies = [
  "js-sys",
+ "serde",
  "wasm-bindgen",
 ]
 
diff --git a/Cargo.toml b/Cargo.toml
index 82f02982..9b4af3a7 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -19,8 +19,8 @@ http-body-util = "0.1.0"
 hyper = { version = "1.2.0", features = ["client"] }
 hyper-util = { version = "0.1.3" }
 normalize-path = "0.2.1"
-object = "0.32.2"
-octocrab = { version = "0.34.1", features = ["rustls", "stream"] }
+object = "0.37.1"
+octocrab = { version = "0.44.1", features = ["rustls", "stream"] }
 once_cell = "1.19.0"
 pdb = "0.8.0"
 pep440_rs = "0.6.6"
diff --git a/src/github.rs b/src/github.rs
index 2dfbba58..70342008 100644
--- a/src/github.rs
+++ b/src/github.rs
@@ -551,8 +551,8 @@ pub async fn command_upload_release_distributions(args: &ArgMatches) -> Result<(
 
     let mut stream = client
         .repos(organization, repo)
-        .releases()
-        .stream_asset(shasums_asset.id)
+        .release_assets()
+        .stream(shasums_asset.id.into_inner())
         .await?;
 
     let mut asset_bytes = Vec::<u8>::new();
diff --git a/src/validation.rs b/src/validation.rs
index 5ab71708..b0ffb530 100644
--- a/src/validation.rs
+++ b/src/validation.rs
@@ -1051,7 +1051,7 @@ fn validate_elf<Elf: FileHeader<Endian = Endianness>>(
         {
             let strings = symbols.strings();
 
-            for (symbol_index, symbol) in symbols.iter().enumerate() {
+            for (symbol_index, symbol) in symbols.enumerate() {
                 let name = String::from_utf8_lossy(symbol.name(endian, strings)?);
 
                 // If symbol versions are defined and we're in the .dynsym section, there should

From 50a2c25e1f1cba1c3bc39af31505e0e3ffe68e97 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 21 Jul 2025 19:11:56 -0500
Subject: [PATCH 144/157] Bump the python group across 1 directory with 6
 updates (#708)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Bumps the python group with 6 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [certifi](https://github.com/certifi/python-certifi) | `2025.6.15` |
`2025.7.14` |
| [jsonschema](https://github.com/python-jsonschema/jsonschema) |
`4.24.0` | `4.25.0` |
| [pywin32](https://github.com/mhammond/pywin32) | `310` | `311` |
| [mypy](https://github.com/python/mypy) | `1.16.1` | `1.17.0` |
| [ruff](https://github.com/astral-sh/ruff) | `0.12.2` | `0.12.4` |
| [types-jsonschema](https://github.com/typeshed-internal/stub_uploader)
| `4.24.0.20250528` | `4.25.0.20250720` |


Updates `certifi` from 2025.6.15 to 2025.7.14
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/certifi/python-certifi/commit/ddd90c6d726f174c1e5820379dac0f2a8fc723a1"><code>ddd90c6</code></a>
2025.07.14 (<a
href="https://redirect.github.com/certifi/python-certifi/issues/359">#359</a>)</li>
<li><a
href="https://github.com/certifi/python-certifi/commit/d905221c916d51077f5c8071a0f7aa2df2a37c52"><code>d905221</code></a>
2025.07.09 (<a
href="https://redirect.github.com/certifi/python-certifi/issues/358">#358</a>)</li>
<li>See full diff in <a
href="https://github.com/certifi/python-certifi/compare/2025.06.15...2025.07.14">compare
view</a></li>
</ul>
</details>
<br />

Updates `jsonschema` from 4.24.0 to 4.25.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/python-jsonschema/jsonschema/releases">jsonschema's
releases</a>.</em></p>
<blockquote>
<h2>v4.25.0</h2>
<!-- raw HTML omitted -->
<h2>What's Changed</h2>
<ul>
<li>Add support for the <code>iri</code> and <code>iri-reference</code>
formats to the <code>format-nongpl</code> extra by <a
href="https://github.com/jkowalleck"><code>@​jkowalleck</code></a> in <a
href="https://redirect.github.com/python-jsonschema/jsonschema/pull/1388">python-jsonschema/jsonschema#1388</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a
href="https://github.com/jkowalleck"><code>@​jkowalleck</code></a> made
their first contribution in <a
href="https://redirect.github.com/python-jsonschema/jsonschema/pull/1388">python-jsonschema/jsonschema#1388</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/python-jsonschema/jsonschema/compare/v4.24.1...v4.25.0">https://github.com/python-jsonschema/jsonschema/compare/v4.24.1...v4.25.0</a></p>
<h2>v4.24.1</h2>
<!-- raw HTML omitted -->
<h2>What's Changed</h2>
<ul>
<li>Unambiguously quote and escape properties in JSON path rendering by
<a href="https://github.com/kurtmckee"><code>@​kurtmckee</code></a> in
<a
href="https://redirect.github.com/python-jsonschema/jsonschema/pull/1390">python-jsonschema/jsonschema#1390</a></li>
<li>Drop python&lt;3.9 backports by <a
href="https://github.com/hackowitz-af"><code>@​hackowitz-af</code></a>
in <a
href="https://redirect.github.com/python-jsonschema/jsonschema/pull/1367">python-jsonschema/jsonschema#1367</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a
href="https://github.com/hackowitz-af"><code>@​hackowitz-af</code></a>
made their first contribution in <a
href="https://redirect.github.com/python-jsonschema/jsonschema/pull/1367">python-jsonschema/jsonschema#1367</a></li>
<li><a href="https://github.com/kurtmckee"><code>@​kurtmckee</code></a>
made their first contribution in <a
href="https://redirect.github.com/python-jsonschema/jsonschema/pull/1390">python-jsonschema/jsonschema#1390</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/python-jsonschema/jsonschema/compare/v4.24.0...v4.24.1">https://github.com/python-jsonschema/jsonschema/compare/v4.24.0...v4.24.1</a></p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/python-jsonschema/jsonschema/blob/main/CHANGELOG.rst">jsonschema's
changelog</a>.</em></p>
<blockquote>
<h1>v4.25.0</h1>
<ul>
<li>Add support for the <code>iri</code> and <code>iri-reference</code>
formats to the <code>format-nongpl</code> extra via the MIT-licensed
<code>rfc3987-syntax</code>.
They were alread supported by the <code>format</code> extra. (<a
href="https://redirect.github.com/python-jsonschema/jsonschema/issues/1388">#1388</a>).</li>
</ul>
<h1>v4.24.1</h1>
<ul>
<li>Properly escape segments in <code>ValidationError.json_path</code>
(<a
href="https://redirect.github.com/python-jsonschema/jsonschema/issues/139">#139</a>).</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/python-jsonschema/jsonschema/commit/9889f69eb5ccb532e2147465697f30c82b2a8bb0"><code>9889f69</code></a>
Add the new functionality to the CHANGELOG.</li>
<li><a
href="https://github.com/python-jsonschema/jsonschema/commit/18855d01f7839083efc5bad1ca67688a7177be42"><code>18855d0</code></a>
Merge pull request <a
href="https://redirect.github.com/python-jsonschema/jsonschema/issues/1388">#1388</a>
from jkowalleck/feat/validate_rfc3987_non-gpl/rfc398...</li>
<li><a
href="https://github.com/python-jsonschema/jsonschema/commit/1a6067fc441177d1911446c7325eee7c776007ae"><code>1a6067f</code></a>
adjust rfc3987-syntax min-version</li>
<li><a
href="https://github.com/python-jsonschema/jsonschema/commit/6aadb8b7ad7f9d5eee58eed73df5a7d865dad34c"><code>6aadb8b</code></a>
Add the fix to the CHANGELOG.</li>
<li><a
href="https://github.com/python-jsonschema/jsonschema/commit/785741e73b63d97eda3973442b109df3f8aa5892"><code>785741e</code></a>
Add a dependency group for our new test dependency.</li>
<li><a
href="https://github.com/python-jsonschema/jsonschema/commit/dc547341f2a3304d73114b1d18da063be7fc43e0"><code>dc54734</code></a>
Add a uv.lock.</li>
<li><a
href="https://github.com/python-jsonschema/jsonschema/commit/b5572c9971358be547bbcf614a304f85886c1627"><code>b5572c9</code></a>
Merge pull request <a
href="https://redirect.github.com/python-jsonschema/jsonschema/issues/1390">#1390</a>
from kurtmckee/fix-json_path-str-rendering</li>
<li><a
href="https://github.com/python-jsonschema/jsonschema/commit/4cf45b95de90191b02396bd04d41760d9798ecd6"><code>4cf45b9</code></a>
Feedback: Use jsonpath-ng to re-parse the rendered JSON path</li>
<li><a
href="https://github.com/python-jsonschema/jsonschema/commit/2680f6ab44d6fe36d321fef6ee626608a5f0ec7a"><code>2680f6a</code></a>
Feedback: Make a compiled regex pattern private</li>
<li><a
href="https://github.com/python-jsonschema/jsonschema/commit/9a957d770d6e63646f4fc874bf8df6be4593f8c8"><code>9a957d7</code></a>
Unambiguously quote and escape properties in JSON path rendering</li>
<li>Additional commits viewable in <a
href="https://github.com/python-jsonschema/jsonschema/compare/v4.24.0...v4.25.0">compare
view</a></li>
</ul>
</details>
<br />

Updates `pywin32` from 310 to 311
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/mhammond/pywin32/releases">pywin32's
releases</a>.</em></p>
<blockquote>
<h2>Build 311</h2>
<p>A release with <a
href="https://github.com/mhammond/pywin32/blob/b311/CHANGES.txt#L18">a
number of incremental improvements</a></p>
<p>Install via pip:</p>
<pre><code>pip install pywin32 --upgrade
</code></pre>
<p>More <a
href="https://github.com/mhammond/pywin32#installing-via-pip">details in
the README</a></p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/mhammond/pywin32/blob/main/CHANGES.txt">pywin32's
changelog</a>.</em></p>
<blockquote>
<h2>Build 311, released 2025/07/14</h2>
<ul>
<li>Fix use-after-free in CertDeleteCertificateFromStore (<a
href="https://redirect.github.com/mhammond/pywin32/issues/2637">#2637</a>)</li>
<li>Better support for COM identifiers with non-ascii characters (<a
href="https://redirect.github.com/mhammond/pywin32/issues/2632">#2632</a>)</li>
<li>pywin32's own warnings will now refer to the caller, rather than to
the internal source of warning itself (<a
href="https://redirect.github.com/mhammond/pywin32/issues/2594">#2594</a>,
<a href="https://github.com/Avasam"><code>@​Avasam</code></a>)</li>
<li>Fixed a regression that broke special <strong>dunder</strong>
methods with CoClass. (<a
href="https://redirect.github.com/mhammond/pywin32/issues/1870">#1870</a>,
<a
href="https://redirect.github.com/mhammond/pywin32/issues/2493">#2493</a>,
<a href="https://github.com/Avasam"><code>@​Avasam</code></a>, <a
href="https://github.com/geppi"><code>@​geppi</code></a>)</li>
<li>Fixed <code>TypeError: cannot unpack non-iterable NoneType
object</code> when registering an axscript client ScriptItem (<a
href="https://redirect.github.com/mhammond/pywin32/issues/2513">#2513</a>,
<a href="https://github.com/Avasam"><code>@​Avasam</code></a>)</li>
<li>Fixed a memory leak when SafeArrays are used as out parameters (<a
href="https://github.com/the-snork"><code>@​the-snork</code></a>)</li>
<li>Fixed dispatch handling for properties (<a
href="https://github.com/the-snork"><code>@​the-snork</code></a>)</li>
<li>Resolved a handful of deprecation warnings (<a
href="https://redirect.github.com/mhammond/pywin32/issues/2567">#2567</a>,
<a
href="https://redirect.github.com/mhammond/pywin32/issues/2576">#2576</a>,
<a href="https://github.com/Avasam"><code>@​Avasam</code></a>)</li>
<li>The following classes now produce a valid <code>eval</code> string
representation when calling <code>repr</code>: (<a
href="https://redirect.github.com/mhammond/pywin32/issues/2573">#2573</a>,
<a href="https://github.com/Avasam"><code>@​Avasam</code></a>)
<ul>
<li><code>pywin.tools.browser.HLIPythonObject</code></li>
<li><code>win32com.server.exception.COMException</code></li>

<li><code>win32comext.axscript.client.error.AXScriptException</code></li>

<li><code>win32comext.axscript.client.pyscript.NamedScriptAttribute</code></li>
</ul>
</li>
<li>Added initial <code>DECIMAL/VT_DECIMAL</code> support (<a
href="https://redirect.github.com/mhammond/pywin32/issues/1501">#1501</a>,
<a
href="https://github.com/gesslerpd"><code>@​gesslerpd</code></a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a
href="https://github.com/mhammond/pywin32/commits">compare view</a></li>
</ul>
</details>
<br />

Updates `mypy` from 1.16.1 to 1.17.0
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/python/mypy/blob/master/CHANGELOG.md">mypy's
changelog</a>.</em></p>
<blockquote>
<h1>Mypy Release Notes</h1>
<h2>Next Release</h2>
<h2>Mypy 1.17</h2>
<p>We’ve just uploaded mypy 1.17 to the Python Package Index (<a
href="https://pypi.org/project/mypy/">PyPI</a>).
Mypy is a static type checker for Python. This release includes new
features and bug fixes.
You can install it as follows:</p>
<pre><code>python3 -m pip install -U mypy
</code></pre>
<p>You can read the full documentation for this release on <a
href="http://mypy.readthedocs.io">Read the Docs</a>.</p>
<h3>Optionally Check That Match Is Exhaustive</h3>
<p>Mypy can now optionally generate an error if a match statement does
not
match exhaustively, without having to use
<code>assert_never(...)</code>. Enable
this by using <code>--enable-error-code exhaustive-match</code>.</p>
<p>Example:</p>
<pre lang="python"><code># mypy: enable-error-code=exhaustive-match
<p>import enum</p>
<p>class Color(enum.Enum):
RED = 1
BLUE = 2</p>
<p>def show_color(val: Color) -&gt; None:
# error: Unhandled case for values of type
&quot;Literal[Color.BLUE]&quot;
match val:
case Color.RED:
print(&quot;red&quot;)
</code></pre></p>
<p>This feature was contributed by Donal Burns (PR <a
href="https://redirect.github.com/python/mypy/pull/19144">19144</a>).</p>
<h3>Further Improvements to Attribute Resolution</h3>
<p>This release includes additional improvements to how attribute types
and kinds are resolved. These fix many bugs and overall improve
consistency.</p>
<ul>
<li>Handle corner case: protocol/class variable/descriptor (Ivan
Levkivskyi, PR <a
href="https://redirect.github.com/python/mypy/pull/19277">19277</a>)</li>
<li>Fix a few inconsistencies in protocol/type object interactions (Ivan
Levkivskyi, PR <a
href="https://redirect.github.com/python/mypy/pull/19267">19267</a>)</li>
<li>Refactor/unify access to static attributes (Ivan Levkivskyi, PR <a
href="https://redirect.github.com/python/mypy/pull/19254">19254</a>)</li>
<li>Remove inconsistencies in operator handling (Ivan Levkivskyi, PR <a
href="https://redirect.github.com/python/mypy/pull/19250">19250</a>)</li>
<li>Make protocol subtyping more consistent (Ivan Levkivskyi, PR <a
href="https://redirect.github.com/python/mypy/pull/18943">18943</a>)</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/python/mypy/commit/0260991f6b055110c3df36bd5539d4f4489bf153"><code>0260991</code></a>
Update version string</li>
<li><a
href="https://github.com/python/mypy/commit/3901aa2f9523ce55e08d94c1716028d840398753"><code>3901aa2</code></a>
Updates to 1.17 changelog (<a
href="https://redirect.github.com/python/mypy/issues/19436">#19436</a>)</li>
<li><a
href="https://github.com/python/mypy/commit/7d133961a7e759aab84223bf8038b9489daaa93c"><code>7d13396</code></a>
Initial changelog for 1.17 release (<a
href="https://redirect.github.com/python/mypy/issues/19427">#19427</a>)</li>
<li><a
href="https://github.com/python/mypy/commit/a182dec997b418b925fe0c28575c50debba0bb3a"><code>a182dec</code></a>
Combine the revealed types of multiple iteration steps in a more robust
manne...</li>
<li><a
href="https://github.com/python/mypy/commit/ab4fd57d45b7f81cf281b17b7d3697ac9f79bc15"><code>ab4fd57</code></a>
Improve the handling of &quot;iteration dependent&quot; errors and notes
in finally cla...</li>
<li><a
href="https://github.com/python/mypy/commit/09ba1f6488b3e8d91c5204839421c61c306ff252"><code>09ba1f6</code></a>
[mypyc] Fix exception swallowing in async try/finally blocks with await
(<a
href="https://redirect.github.com/python/mypy/issues/19353">#19353</a>)</li>
<li><a
href="https://github.com/python/mypy/commit/5c65e330b0e4a188d68c04715a90e1f7d9c18df6"><code>5c65e33</code></a>
[mypyc] Fix AttributeError in async try/finally with mixed return paths
(<a
href="https://redirect.github.com/python/mypy/issues/19361">#19361</a>)</li>
<li><a
href="https://github.com/python/mypy/commit/934ec50744c766522329c604c6908a6ed05affd6"><code>934ec50</code></a>
Lessen dmypy suggest path limitations for Windows machines (<a
href="https://redirect.github.com/python/mypy/issues/19337">#19337</a>)</li>
<li><a
href="https://github.com/python/mypy/commit/a4801f928aaadb19f9893fe45af8e69ab6b509d0"><code>a4801f9</code></a>
Type ignore comments erroneously marked as unused by dmypy (<a
href="https://redirect.github.com/python/mypy/issues/15043">#15043</a>)</li>
<li><a
href="https://github.com/python/mypy/commit/c3bfa0d6f3ac3cea78cc497a3c44002ea46437a1"><code>c3bfa0d</code></a>
Handle corner case: protocol vs classvar vs descriptor (<a
href="https://redirect.github.com/python/mypy/issues/19277">#19277</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/python/mypy/compare/v1.16.1...v1.17.0">compare
view</a></li>
</ul>
</details>
<br />

Updates `ruff` from 0.12.2 to 0.12.4
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/astral-sh/ruff/releases">ruff's
releases</a>.</em></p>
<blockquote>
<h2>0.12.4</h2>
<h2>Release Notes</h2>
<h3>Preview features</h3>
<ul>
<li>[<code>flake8-type-checking</code>, <code>pyupgrade</code>,
<code>ruff</code>] Add <code>from __future__ import annotations</code>
when it would allow new fixes (<code>TC001</code>, <code>TC002</code>,
<code>TC003</code>, <code>UP037</code>, <code>RUF013</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/19100">#19100</a>)</li>
<li>[<code>flake8-use-pathlib</code>] Add autofix for
<code>PTH109</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/19245">#19245</a>)</li>
<li>[<code>pylint</code>] Detect indirect <code>pathlib.Path</code>
usages for <code>unspecified-encoding</code> (<code>PLW1514</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/19304">#19304</a>)</li>
</ul>
<h3>Bug fixes</h3>
<ul>
<li>[<code>flake8-bugbear</code>] Fix <code>B017</code> false negatives
for keyword exception arguments (<a
href="https://redirect.github.com/astral-sh/ruff/pull/19217">#19217</a>)</li>
<li>[<code>flake8-use-pathlib</code>] Fix false negative on direct
<code>Path()</code> instantiation (<code>PTH210</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/19388">#19388</a>)</li>
<li>[<code>flake8-django</code>] Fix <code>DJ008</code> false positive
for abstract models with type-annotated <code>abstract</code> field (<a
href="https://redirect.github.com/astral-sh/ruff/pull/19221">#19221</a>)</li>
<li>[<code>isort</code>] Fix <code>I002</code> import insertion after
docstring with multiple string statements (<a
href="https://redirect.github.com/astral-sh/ruff/pull/19222">#19222</a>)</li>
<li>[<code>isort</code>] Treat form feed as valid whitespace before a
semicolon (<a
href="https://redirect.github.com/astral-sh/ruff/pull/19343">#19343</a>)</li>
<li>[<code>pydoclint</code>] Fix <code>SyntaxError</code> from fixes
with line continuations (<code>D201</code>, <code>D202</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/19246">#19246</a>)</li>
<li>[<code>refurb</code>] <code>FURB164</code> fix should validate
arguments and should usually be marked unsafe (<a
href="https://redirect.github.com/astral-sh/ruff/pull/19136">#19136</a>)</li>
</ul>
<h3>Rule changes</h3>
<ul>
<li>[<code>flake8-use-pathlib</code>] Skip single dots for
<code>invalid-pathlib-with-suffix</code> (<code>PTH210</code>) on
versions &gt;= 3.14 (<a
href="https://redirect.github.com/astral-sh/ruff/pull/19331">#19331</a>)</li>
<li>[<code>pep8_naming</code>] Avoid false positives on standard library
functions with uppercase names (<code>N802</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/18907">#18907</a>)</li>
<li>[<code>pycodestyle</code>] Handle brace escapes for t-strings in
logical lines (<a
href="https://redirect.github.com/astral-sh/ruff/pull/19358">#19358</a>)</li>
<li>[<code>pylint</code>] Extend invalid string character rules to
include t-strings (<a
href="https://redirect.github.com/astral-sh/ruff/pull/19355">#19355</a>)</li>
<li>[<code>ruff</code>] Allow <code>strict</code> kwarg when checking
for <code>starmap-zip</code> (<code>RUF058</code>) in Python 3.14+ (<a
href="https://redirect.github.com/astral-sh/ruff/pull/19333">#19333</a>)</li>
</ul>
<h3>Documentation</h3>
<ul>
<li>[<code>flake8-type-checking</code>] Make <code>TC010</code> docs
example more realistic (<a
href="https://redirect.github.com/astral-sh/ruff/pull/19356">#19356</a>)</li>
<li>Make more documentation examples error out-of-the-box (<a
href="https://redirect.github.com/astral-sh/ruff/pull/19288">#19288</a>,<a
href="https://redirect.github.com/astral-sh/ruff/pull/19272">#19272</a>,<a
href="https://redirect.github.com/astral-sh/ruff/pull/19291">#19291</a>,<a
href="https://redirect.github.com/astral-sh/ruff/pull/19296">#19296</a>,<a
href="https://redirect.github.com/astral-sh/ruff/pull/19292">#19292</a>,<a
href="https://redirect.github.com/astral-sh/ruff/pull/19295">#19295</a>,<a
href="https://redirect.github.com/astral-sh/ruff/pull/19297">#19297</a>,<a
href="https://redirect.github.com/astral-sh/ruff/pull/19309">#19309</a>)</li>
</ul>
<h2>Contributors</h2>
<ul>
<li><a
href="https://github.com/AlexWaygood"><code>@​AlexWaygood</code></a></li>
<li><a
href="https://github.com/BurntSushi"><code>@​BurntSushi</code></a></li>
<li><a href="https://github.com/Gankra"><code>@​Gankra</code></a></li>
<li><a
href="https://github.com/MatthewMckee4"><code>@​MatthewMckee4</code></a></li>
<li><a
href="https://github.com/MeGaGiGaGon"><code>@​MeGaGiGaGon</code></a></li>
<li><a
href="https://github.com/MichaReiser"><code>@​MichaReiser</code></a></li>
<li><a
href="https://github.com/UnboundVariable"><code>@​UnboundVariable</code></a></li>
<li><a
href="https://github.com/chirizxc"><code>@​chirizxc</code></a></li>
<li><a
href="https://github.com/close2code-palm"><code>@​close2code-palm</code></a></li>
<li><a
href="https://github.com/corneliusroemer"><code>@​corneliusroemer</code></a></li>
<li><a
href="https://github.com/danparizher"><code>@​danparizher</code></a></li>
<li><a
href="https://github.com/dcreager"><code>@​dcreager</code></a></li>
<li><a
href="https://github.com/dhruvmanila"><code>@​dhruvmanila</code></a></li>
<li><a href="https://github.com/dylwil3"><code>@​dylwil3</code></a></li>
<li><a
href="https://github.com/github-actions"><code>@​github-actions</code></a></li>
<li><a href="https://github.com/ntBre"><code>@​ntBre</code></a></li>
<li><a
href="https://github.com/oconnor663"><code>@​oconnor663</code></a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md">ruff's
changelog</a>.</em></p>
<blockquote>
<h2>0.12.4</h2>
<h3>Preview features</h3>
<ul>
<li>[<code>flake8-type-checking</code>, <code>pyupgrade</code>,
<code>ruff</code>] Add <code>from __future__ import annotations</code>
when it would allow new fixes (<code>TC001</code>, <code>TC002</code>,
<code>TC003</code>, <code>UP037</code>, <code>RUF013</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/19100">#19100</a>)</li>
<li>[<code>flake8-use-pathlib</code>] Add autofix for
<code>PTH109</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/19245">#19245</a>)</li>
<li>[<code>pylint</code>] Detect indirect <code>pathlib.Path</code>
usages for <code>unspecified-encoding</code> (<code>PLW1514</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/19304">#19304</a>)</li>
</ul>
<h3>Bug fixes</h3>
<ul>
<li>[<code>flake8-bugbear</code>] Fix <code>B017</code> false negatives
for keyword exception arguments (<a
href="https://redirect.github.com/astral-sh/ruff/pull/19217">#19217</a>)</li>
<li>[<code>flake8-use-pathlib</code>] Fix false negative on direct
<code>Path()</code> instantiation (<code>PTH210</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/19388">#19388</a>)</li>
<li>[<code>flake8-django</code>] Fix <code>DJ008</code> false positive
for abstract models with type-annotated <code>abstract</code> field (<a
href="https://redirect.github.com/astral-sh/ruff/pull/19221">#19221</a>)</li>
<li>[<code>isort</code>] Fix <code>I002</code> import insertion after
docstring with multiple string statements (<a
href="https://redirect.github.com/astral-sh/ruff/pull/19222">#19222</a>)</li>
<li>[<code>isort</code>] Treat form feed as valid whitespace before a
semicolon (<a
href="https://redirect.github.com/astral-sh/ruff/pull/19343">#19343</a>)</li>
<li>[<code>pydoclint</code>] Fix <code>SyntaxError</code> from fixes
with line continuations (<code>D201</code>, <code>D202</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/19246">#19246</a>)</li>
<li>[<code>refurb</code>] <code>FURB164</code> fix should validate
arguments and should usually be marked unsafe (<a
href="https://redirect.github.com/astral-sh/ruff/pull/19136">#19136</a>)</li>
</ul>
<h3>Rule changes</h3>
<ul>
<li>[<code>flake8-use-pathlib</code>] Skip single dots for
<code>invalid-pathlib-with-suffix</code> (<code>PTH210</code>) on
versions &gt;= 3.14 (<a
href="https://redirect.github.com/astral-sh/ruff/pull/19331">#19331</a>)</li>
<li>[<code>pep8_naming</code>] Avoid false positives on standard library
functions with uppercase names (<code>N802</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/18907">#18907</a>)</li>
<li>[<code>pycodestyle</code>] Handle brace escapes for t-strings in
logical lines (<a
href="https://redirect.github.com/astral-sh/ruff/pull/19358">#19358</a>)</li>
<li>[<code>pylint</code>] Extend invalid string character rules to
include t-strings (<a
href="https://redirect.github.com/astral-sh/ruff/pull/19355">#19355</a>)</li>
<li>[<code>ruff</code>] Allow <code>strict</code> kwarg when checking
for <code>starmap-zip</code> (<code>RUF058</code>) in Python 3.14+ (<a
href="https://redirect.github.com/astral-sh/ruff/pull/19333">#19333</a>)</li>
</ul>
<h3>Documentation</h3>
<ul>
<li>[<code>flake8-type-checking</code>] Make <code>TC010</code> docs
example more realistic (<a
href="https://redirect.github.com/astral-sh/ruff/pull/19356">#19356</a>)</li>
<li>Make more documentation examples error out-of-the-box (<a
href="https://redirect.github.com/astral-sh/ruff/pull/19288">#19288</a>,<a
href="https://redirect.github.com/astral-sh/ruff/pull/19272">#19272</a>,<a
href="https://redirect.github.com/astral-sh/ruff/pull/19291">#19291</a>,<a
href="https://redirect.github.com/astral-sh/ruff/pull/19296">#19296</a>,<a
href="https://redirect.github.com/astral-sh/ruff/pull/19292">#19292</a>,<a
href="https://redirect.github.com/astral-sh/ruff/pull/19295">#19295</a>,<a
href="https://redirect.github.com/astral-sh/ruff/pull/19297">#19297</a>,<a
href="https://redirect.github.com/astral-sh/ruff/pull/19309">#19309</a>)</li>
</ul>
<h2>0.12.3</h2>
<h3>Preview features</h3>
<ul>
<li>[<code>flake8-bugbear</code>] Support non-context-manager calls in
<code>B017</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/19063">#19063</a>)</li>
<li>[<code>flake8-use-pathlib</code>] Add autofixes for
<code>PTH100</code>, <code>PTH106</code>, <code>PTH107</code>,
<code>PTH108</code>, <code>PTH110</code>, <code>PTH111</code>,
<code>PTH112</code>, <code>PTH113</code>, <code>PTH114</code>,
<code>PTH115</code>, <code>PTH117</code>, <code>PTH119</code>,
<code>PTH120</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/19213">#19213</a>)</li>
<li>[<code>flake8-use-pathlib</code>] Add autofixes for
<code>PTH203</code>, <code>PTH204</code>, <code>PTH205</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/18922">#18922</a>)</li>
</ul>
<h3>Bug fixes</h3>
<ul>
<li>[<code>flake8-return</code>] Fix false-positive for variables used
inside nested functions in <code>RET504</code> (<a
href="https://redirect.github.com/astral-sh/ruff/pull/18433">#18433</a>)</li>
<li>Treat form feed as valid whitespace before a line continuation (<a
href="https://redirect.github.com/astral-sh/ruff/pull/19220">#19220</a>)</li>
<li>[<code>flake8-type-checking</code>] Fix syntax error introduced by
fix (<code>TC008</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/19150">#19150</a>)</li>
<li>[<code>pyupgrade</code>] Keyword arguments in <code>super</code>
should suppress the <code>UP008</code> fix (<a
href="https://redirect.github.com/astral-sh/ruff/pull/19131">#19131</a>)</li>
</ul>
<h3>Documentation</h3>
<ul>
<li>[<code>flake8-pyi</code>] Make example error out-of-the-box
(<code>PYI007</code>, <code>PYI008</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/19103">#19103</a>)</li>
<li>[<code>flake8-simplify</code>] Make example error out-of-the-box
(<code>SIM116</code>) (<a
href="https://redirect.github.com/astral-sh/ruff/pull/19111">#19111</a>)</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/astral-sh/ruff/commit/ee2759b365448e58503b63636c1cedaa65360bd1"><code>ee2759b</code></a>
Bump 0.12.4 (<a
href="https://redirect.github.com/astral-sh/ruff/issues/19406">#19406</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/35f33d9bf5b9dd1cdf4af96999c0f61b8e900579"><code>35f33d9</code></a>
[ty] publish settings diagnostics (<a
href="https://redirect.github.com/astral-sh/ruff/issues/19335">#19335</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/5d78b3117aecccbf02a43f10b759127149ae6ce3"><code>5d78b31</code></a>
[<code>flake8-use-pathlib</code>] Add autofix for <code>PTH109</code>
(<a
href="https://redirect.github.com/astral-sh/ruff/issues/19245">#19245</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/c2a05b4825a51d9875b88e5b8b05720ceb4b0e51"><code>c2a05b4</code></a>
[ty] Use <code>bitflags</code> for resolved client capabilities (<a
href="https://redirect.github.com/astral-sh/ruff/issues/19393">#19393</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/fae0b5c89e266237d10e5879df80f452fe2d4ad9"><code>fae0b5c</code></a>
[ty] Initial implementation of declaration and definition providers. (<a
href="https://redirect.github.com/astral-sh/ruff/issues/19371">#19371</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/cbe94b094b4d8ab88feea1ec8343e0ff033e8cae"><code>cbe94b0</code></a>
[ty] Support empty function bodies in <code>if TYPE_CHECKING</code>
blocks (<a
href="https://redirect.github.com/astral-sh/ruff/issues/19372">#19372</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/029de784f1ea5ef470cf1471c89e2cbe320f125a"><code>029de78</code></a>
[<code>flake8-use-pathlib</code>] Fix false negative on direct
<code>Path()</code> instantiation (`...</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/ff94fe7447a8aff4f408fcac8d7dd1d686c50688"><code>ff94fe7</code></a>
Treat form feed as valid whitespace before a semicolon (<a
href="https://redirect.github.com/astral-sh/ruff/issues/19343">#19343</a>)</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/b2501b45e06ecdc653ae52565e90dd163aa30f8a"><code>b2501b4</code></a>
[<code>pylint</code>] Detect indirect <code>pathlib.Path</code> usages
for <code>unspecified-encoding</code> (...</li>
<li><a
href="https://github.com/astral-sh/ruff/commit/291699b375f694c659fe82bdd68b149bde2494ee"><code>291699b</code></a>
[<code>refurb</code>] <code>FURB164</code> fix should validate arguments
and should usually be mark...</li>
<li>Additional commits viewable in <a
href="https://github.com/astral-sh/ruff/compare/0.12.2...0.12.4">compare
view</a></li>
</ul>
</details>
<br />

Updates `types-jsonschema` from 4.24.0.20250528 to 4.25.0.20250720
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a
href="https://github.com/typeshed-internal/stub_uploader/commits">compare
view</a></li>
</ul>
</details>
<br />


Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
 requirements.dev.txt | 110 +++++++++++++++++++++----------------------
 requirements.win.txt |  50 +++++++++++---------
 2 files changed, 82 insertions(+), 78 deletions(-)

diff --git a/requirements.dev.txt b/requirements.dev.txt
index 0876769e..b45edbc3 100644
--- a/requirements.dev.txt
+++ b/requirements.dev.txt
@@ -198,39 +198,39 @@ markupsafe==3.0.2 \
     # via
     #   -r requirements.txt
     #   jinja2
-mypy==1.16.1 \
-    --hash=sha256:051e1677689c9d9578b9c7f4d206d763f9bbd95723cd1416fad50db49d52f359 \
-    --hash=sha256:08e850ea22adc4d8a4014651575567b0318ede51e8e9fe7a68f25391af699507 \
-    --hash=sha256:09aa4f91ada245f0a45dbc47e548fd94e0dd5a8433e0114917dc3b526912a30c \
-    --hash=sha256:0a7cfb0fe29fe5a9841b7c8ee6dffb52382c45acdf68f032145b75620acfbd6f \
-    --hash=sha256:0ab5eca37b50188163fa7c1b73c685ac66c4e9bdee4a85c9adac0e91d8895e15 \
-    --hash=sha256:1256688e284632382f8f3b9e2123df7d279f603c561f099758e66dd6ed4e8bd6 \
-    --hash=sha256:13c7cd5b1cb2909aa318a90fd1b7e31f17c50b242953e7dd58345b2a814f6383 \
-    --hash=sha256:1f0435cf920e287ff68af3d10a118a73f212deb2ce087619eb4e648116d1fe9b \
-    --hash=sha256:211287e98e05352a2e1d4e8759c5490925a7c784ddc84207f4714822f8cf99b6 \
-    --hash=sha256:22d76a63a42619bfb90122889b903519149879ddbf2ba4251834727944c8baca \
-    --hash=sha256:2c7ce0662b6b9dc8f4ed86eb7a5d505ee3298c04b40ec13b30e572c0e5ae17c4 \
-    --hash=sha256:352025753ef6a83cb9e7f2427319bb7875d1fdda8439d1e23de12ab164179574 \
-    --hash=sha256:44e7acddb3c48bd2713994d098729494117803616e116032af192871aed80b79 \
-    --hash=sha256:472e4e4c100062488ec643f6162dd0d5208e33e2f34544e1fc931372e806c0cc \
-    --hash=sha256:4f58ac32771341e38a853c5d0ec0dfe27e18e27da9cdb8bbc882d2249c71a3ee \
-    --hash=sha256:58e07fb958bc5d752a280da0e890c538f1515b79a65757bbdc54252ba82e0b40 \
-    --hash=sha256:5e198ab3f55924c03ead626ff424cad1732d0d391478dfbf7bb97b34602395da \
-    --hash=sha256:5fc2ac4027d0ef28d6ba69a0343737a23c4d1b83672bf38d1fe237bdc0643b37 \
-    --hash=sha256:66df38405fd8466ce3517eda1f6640611a0b8e70895e2a9462d1d4323c5eb4b9 \
-    --hash=sha256:6bd00a0a2094841c5e47e7374bb42b83d64c527a502e3334e1173a0c24437bab \
-    --hash=sha256:7fc688329af6a287567f45cc1cefb9db662defeb14625213a5b7da6e692e2069 \
-    --hash=sha256:86042bbf9f5a05ea000d3203cf87aa9d0ccf9a01f73f71c58979eb9249f46d72 \
-    --hash=sha256:87ff2c13d58bdc4bbe7dc0dedfe622c0f04e2cb2a492269f3b418df2de05c536 \
-    --hash=sha256:af4792433f09575d9eeca5c63d7d90ca4aeceda9d8355e136f80f8967639183d \
-    --hash=sha256:b4f0fed1022a63c6fec38f28b7fc77fca47fd490445c69d0a66266c59dd0b88a \
-    --hash=sha256:d5d2309511cc56c021b4b4e462907c2b12f669b2dbeb68300110ec27723971be \
-    --hash=sha256:ddc91eb318c8751c69ddb200a5937f1232ee8efb4e64e9f4bc475a33719de438 \
-    --hash=sha256:dedb6229b2c9086247e21a83c309754b9058b438704ad2f6807f0d8227f6ebdd \
-    --hash=sha256:ea16e2a7d2714277e349e24d19a782a663a34ed60864006e8585db08f8ad1782 \
-    --hash=sha256:ea7469ee5902c95542bea7ee545f7006508c65c8c54b06dc2c92676ce526f3ea \
-    --hash=sha256:f895078594d918f93337a505f8add9bd654d1a24962b4c6ed9390e12531eb31b \
-    --hash=sha256:ff9fa5b16e4c1364eb89a4d16bcda9987f05d39604e1e6c35378a2987c1aac2d
+mypy==1.17.0 \
+    --hash=sha256:037bc0f0b124ce46bfde955c647f3e395c6174476a968c0f22c95a8d2f589bba \
+    --hash=sha256:03ba330b76710f83d6ac500053f7727270b6b8553b0423348ffb3af6f2f7b889 \
+    --hash=sha256:0e69db1fb65b3114f98c753e3930a00514f5b68794ba80590eb02090d54a5d4a \
+    --hash=sha256:1051df7ec0886fa246a530ae917c473491e9a0ba6938cfd0ec2abc1076495c3e \
+    --hash=sha256:15d9d0018237ab058e5de3d8fce61b6fa72cc59cc78fd91f1b474bce12abf496 \
+    --hash=sha256:1619a485fd0e9c959b943c7b519ed26b712de3002d7de43154a489a2d0fd817d \
+    --hash=sha256:24cfcc1179c4447854e9e406d3af0f77736d631ec87d31c6281ecd5025df625d \
+    --hash=sha256:2c41aa59211e49d717d92b3bb1238c06d387c9325d3122085113c79118bebb06 \
+    --hash=sha256:3204d773bab5ff4ebbd1f8efa11b498027cd57017c003ae970f310e5b96be8d8 \
+    --hash=sha256:3c56f180ff6430e6373db7a1d569317675b0a451caf5fef6ce4ab365f5f2f6c3 \
+    --hash=sha256:434ad499ad8dde8b2f6391ddfa982f41cb07ccda8e3c67781b1bfd4e5f9450a8 \
+    --hash=sha256:51e455a54d199dd6e931cd7ea987d061c2afbaf0960f7f66deef47c90d1b304d \
+    --hash=sha256:63e751f1b5ab51d6f3d219fe3a2fe4523eaa387d854ad06906c63883fde5b1ab \
+    --hash=sha256:6ff25d151cc057fdddb1cb1881ef36e9c41fa2a5e78d8dd71bee6e4dcd2bc05b \
+    --hash=sha256:73a0ff2dd10337ceb521c080d4147755ee302dcde6e1a913babd59473904615f \
+    --hash=sha256:93468cf29aa9a132bceb103bd8475f78cacde2b1b9a94fd978d50d4bdf616c9a \
+    --hash=sha256:98189382b310f16343151f65dd7e6867386d3e35f7878c45cfa11383d175d91f \
+    --hash=sha256:9d4fe5c72fd262d9c2c91c1117d16aac555e05f5beb2bae6a755274c6eec42be \
+    --hash=sha256:b72c34ce05ac3a1361ae2ebb50757fb6e3624032d91488d93544e9f82db0ed6c \
+    --hash=sha256:ba06254a5a22729853209550d80f94e28690d5530c661f9416a68ac097b13fc4 \
+    --hash=sha256:c004135a300ab06a045c1c0d8e3f10215e71d7b4f5bb9a42ab80236364429937 \
+    --hash=sha256:c38876106cb6132259683632b287238858bd58de267d80defb6f418e9ee50658 \
+    --hash=sha256:ce4a17920ec144647d448fc43725b5873548b1aae6c603225626747ededf582d \
+    --hash=sha256:d30ba01c0f151998f367506fab31c2ac4527e6a7b2690107c7a7f9e3cb419a9c \
+    --hash=sha256:d96b196e5c16f41b4f7736840e8455958e832871990c7ba26bf58175e357ed61 \
+    --hash=sha256:e5d7ccc08ba089c06e2f5629c660388ef1fee708444f1dee0b9203fa031dee03 \
+    --hash=sha256:eafaf8b9252734400f9b77df98b4eee3d2eecab16104680d51341c75702cad70 \
+    --hash=sha256:f105f61a5eff52e137fd73bee32958b2add9d9f0a856f17314018646af838e97 \
+    --hash=sha256:f773c6d14dcc108a5b141b4456b0871df638eb411a89cd1c0c001fc4a9d08fc8 \
+    --hash=sha256:f7fb09d05e0f1c329a36dcd30e27564a3555717cde87301fae4fb542402ddfad \
+    --hash=sha256:f8e08de6138043108b3b18f09d3f817a4783912e48828ab397ecf183135d84d6 \
+    --hash=sha256:f986f1cab8dbec39ba6e0eaa42d4d3ac6686516a5d3dccd64be095db05ebc6bb
     # via -r requirements.dev.in
 mypy-extensions==1.0.0 \
     --hash=sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d \
@@ -417,25 +417,25 @@ rpds-py==0.22.3 \
     #   -r requirements.txt
     #   jsonschema
     #   referencing
-ruff==0.12.2 \
-    --hash=sha256:093ea2b221df1d2b8e7ad92fc6ffdca40a2cb10d8564477a987b44fd4008a7be \
-    --hash=sha256:09e4cf27cc10f96b1708100fa851e0daf21767e9709e1649175355280e0d950e \
-    --hash=sha256:2a4a20aeed74671b2def096bdf2eac610c7d8ffcbf4fb0e627c06947a1d7078d \
-    --hash=sha256:369ffb69b70cd55b6c3fc453b9492d98aed98062db9fec828cdfd069555f5f1a \
-    --hash=sha256:3b8b94317cbc2ae4a2771af641739f933934b03555e51515e6e021c64441532d \
-    --hash=sha256:3eb3a6b2db4d6e2c77e682f0b988d4d61aff06860158fdb413118ca133d57922 \
-    --hash=sha256:45fc42c3bf1d30d2008023a0a9a0cfb06bf9835b147f11fe0679f21ae86d34b1 \
-    --hash=sha256:48d6c6bfb4761df68bc05ae630e24f506755e702d4fb08f08460be778c7ccb12 \
-    --hash=sha256:4987b8f4ceadf597c927beee65a5eaf994c6e2b631df963f86d8ad1bdea99342 \
-    --hash=sha256:6932323db80484dda89153da3d8e58164d01d6da86857c79f1961934354992da \
-    --hash=sha256:6aa7e623a3a11538108f61e859ebf016c4f14a7e6e4eba1980190cacb57714ce \
-    --hash=sha256:71a4c550195612f486c9d1f2b045a600aeba851b298c667807ae933478fcef04 \
-    --hash=sha256:73448de992d05517170fc37169cbca857dfeaeaa8c2b9be494d7bcb0d36c8f4b \
-    --hash=sha256:793d8859445ea47591272021a81391350205a4af65a9392401f418a95dfb75c9 \
-    --hash=sha256:8ae64755b22f4ff85e9c52d1f82644abd0b6b6b6deedceb74bd71f35c24044cc \
-    --hash=sha256:ce48f675c394c37e958bf229fb5c1e843e20945a6d962cf3ea20b7a107dcd9f4 \
-    --hash=sha256:d7b4f55cd6f325cb7621244f19c873c565a08aff5a4ba9c69aa7355f3f7afd3e \
-    --hash=sha256:dca8a3b6d6dc9810ed8f328d406516bf4d660c00caeaef36eb831cf4871b0639
+ruff==0.12.4 \
+    --hash=sha256:0618ec4442a83ab545e5b71202a5c0ed7791e8471435b94e655b570a5031a98e \
+    --hash=sha256:0fc426bec2e4e5f4c4f182b9d2ce6a75c85ba9bcdbe5c6f2a74fcb8df437df4b \
+    --hash=sha256:13efa16df6c6eeb7d0f091abae50f58e9522f3843edb40d56ad52a5a4a4b6873 \
+    --hash=sha256:2abc48f3d9667fdc74022380b5c745873499ff827393a636f7a59da1515e7c57 \
+    --hash=sha256:2b2449dc0c138d877d629bea151bee8c0ae3b8e9c43f5fcaafcd0c0d0726b184 \
+    --hash=sha256:478fccdb82ca148a98a9ff43658944f7ab5ec41c3c49d77cd99d44da019371a1 \
+    --hash=sha256:4de27977827893cdfb1211d42d84bc180fceb7b72471104671c59be37041cf93 \
+    --hash=sha256:55c0f4ca9769408d9b9bac530c30d3e66490bd2beb2d3dae3e4128a1f05c7442 \
+    --hash=sha256:56e45bb11f625db55f9b70477062e6a1a04d53628eda7784dce6e0f55fd549eb \
+    --hash=sha256:a7dea966bcb55d4ecc4cc3270bccb6f87a337326c9dcd3c07d5b97000dbff41c \
+    --hash=sha256:a8224cc3722c9ad9044da7f89c4c1ec452aef2cfe3904365025dd2f51daeae0e \
+    --hash=sha256:afcfa3ab5ab5dd0e1c39bf286d829e042a15e966b3726eea79528e2e24d8371a \
+    --hash=sha256:be0593c69df9ad1465e8a2d10e3defd111fdb62dcd5be23ae2c06da77e8fcffb \
+    --hash=sha256:c057ce464b1413c926cdb203a0f858cd52f3e73dcb3270a3318d1630f6395bb3 \
+    --hash=sha256:cb0d261dac457ab939aeb247e804125a5d521b21adf27e721895b0d3f83a0d0a \
+    --hash=sha256:e64b90d1122dc2713330350626b10d60818930819623abbb56535c6466cce045 \
+    --hash=sha256:e9949d01d64fa3672449a51ddb5d7548b33e130240ad418884ee6efa7a229586 \
+    --hash=sha256:fe0b9e9eb23736b453143d72d2ceca5db323963330d5b7859d60d101147d461a
     # via -r requirements.dev.in
 six==1.17.0 \
     --hash=sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274 \
@@ -481,9 +481,9 @@ types-jinja2==2.11.9 \
     --hash=sha256:60a1e21e8296979db32f9374d8a239af4cb541ff66447bb915d8ad398f9c63b2 \
     --hash=sha256:dbdc74a40aba7aed520b7e4d89e8f0fe4286518494208b35123bcf084d4b8c81
     # via -r requirements.dev.in
-types-jsonschema==4.24.0.20250528 \
-    --hash=sha256:6a906b5ff73ac11c8d1e0b6c30a9693e1e4e1ab56c56c932b3a7e081b86d187b \
-    --hash=sha256:7e28c64e0ae7980eeb158105b20663fc6a6b8f81d5f86ea6614aa0014417bd1e
+types-jsonschema==4.25.0.20250720 \
+    --hash=sha256:765a3b6144798fe3161fd8cbe570a756ed3e8c0e5adb7c09693eb49faad39dbd \
+    --hash=sha256:7d7897c715310d8bf9ae27a2cedba78bbb09e4cad83ce06d2aa79b73a88941df
     # via -r requirements.dev.in
 types-markupsafe==1.1.10 \
     --hash=sha256:85b3a872683d02aea3a5ac2a8ef590193c344092032f58457287fbf8e06711b1 \
diff --git a/requirements.win.txt b/requirements.win.txt
index faa01357..a9132ab3 100644
--- a/requirements.win.txt
+++ b/requirements.win.txt
@@ -6,9 +6,9 @@ attrs==25.3.0 \
     # via
     #   jsonschema
     #   referencing
-certifi==2025.6.15 \
-    --hash=sha256:2e0c7ce7cb5d8f8634ca55d2ba7e6ec2689a2fd6537d8dec1296a477a4910057 \
-    --hash=sha256:d747aa5a8b9bbbb1bb8c22bb13e22bd1f18e9796defa16bab421f7f7a317323b
+certifi==2025.7.14 \
+    --hash=sha256:6b31f564a415d79ee77df69d757bb49a5bb53bd9f756cbbe24394ffd6fc1f4b2 \
+    --hash=sha256:8ea99dbdfaaf2ba2f9bac77b9249ef62ec5218e7c2b2e903378ed5fccf765995
     # via requests
 charset-normalizer==3.4.2 \
     --hash=sha256:005fa3432484527f9732ebd315da8da8001593e2cf46a3d817669f062c3d9ed4 \
@@ -116,9 +116,9 @@ jinja2==3.1.6 \
     --hash=sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d \
     --hash=sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67
     # via -r requirements.in
-jsonschema==4.24.0 \
-    --hash=sha256:0b4e8069eb12aedfa881333004bccaec24ecef5a8a6a4b6df142b2cc9599d196 \
-    --hash=sha256:a462455f19f5faf404a7902952b6f0e3ce868f3ee09a359b05eca6673bd8412d
+jsonschema==4.25.0 \
+    --hash=sha256:24c2e8da302de79c8b9382fee3e76b355e44d2a4364bb207159ce10b517bd716 \
+    --hash=sha256:e63acf5c11762c0e6672ffb61482bdf57f0876684d8d249c0fe2d730d48bc55f
     # via -r requirements.in
 jsonschema-specifications==2025.4.1 \
     --hash=sha256:4653bffbd6584f7de83a67e0d620ef16900b390ddc7939d56684d6c81e33f1af \
@@ -187,23 +187,27 @@ markupsafe==3.0.2 \
     --hash=sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430 \
     --hash=sha256:fcabf5ff6eea076f859677f5f0b6b5c1a51e70a376b0579e0eadef8db48c6b50
     # via jinja2
-pywin32==310 \
-    --hash=sha256:0867beb8addefa2e3979d4084352e4ac6e991ca45373390775f7084cc0209b9c \
-    --hash=sha256:126298077a9d7c95c53823934f000599f66ec9296b09167810eb24875f32689c \
-    --hash=sha256:19ec5fc9b1d51c4350be7bb00760ffce46e6c95eaf2f0b2f1150657b1a43c582 \
-    --hash=sha256:1e765f9564e83011a63321bb9d27ec456a0ed90d3732c4b2e312b855365ed8bd \
-    --hash=sha256:2349cc906eae872d0663d4d6290d13b90621eaf78964bb1578632ff20e152966 \
-    --hash=sha256:30f0a9b3138fb5e07eb4973b7077e1883f558e40c578c6925acc7a94c34eaa36 \
-    --hash=sha256:33babed0cf0c92a6f94cc6cc13546ab24ee13e3e800e61ed87609ab91e4c8213 \
-    --hash=sha256:5d241a659c496ada3253cd01cfaa779b048e90ce4b2b38cd44168ad555ce74ab \
-    --hash=sha256:667827eb3a90208ddbdcc9e860c81bde63a135710e21e4cb3348968e4bd5249e \
-    --hash=sha256:6dd97011efc8bf51d6793a82292419eba2c71cf8e7250cfac03bba284454abc1 \
-    --hash=sha256:851c8d927af0d879221e616ae1f66145253537bbdd321a77e8ef701b443a9a1a \
-    --hash=sha256:8a75a5cc3893e83a108c05d82198880704c44bbaee4d06e442e471d3c9ea4f3d \
-    --hash=sha256:96867217335559ac619f00ad70e513c0fcf84b8a3af9fc2bba3b59b97da70475 \
-    --hash=sha256:bf5c397c9a9a19a6f62f3fb821fbf36cac08f03770056711f765ec1503972060 \
-    --hash=sha256:c3e78706e4229b915a0821941a84e7ef420bf2b77e08c9dae3c76fd03fd2ae3d \
-    --hash=sha256:e308f831de771482b7cf692a1f308f8fca701b2d8f9dde6cc440c7da17e47b33
+pywin32==311 \
+    --hash=sha256:0502d1facf1fed4839a9a51ccbcc63d952cf318f78ffc00a7e78528ac27d7a2b \
+    --hash=sha256:184eb5e436dea364dcd3d2316d577d625c0351bf237c4e9a5fabbcfa5a58b151 \
+    --hash=sha256:3aca44c046bd2ed8c90de9cb8427f581c479e594e99b5c0bb19b29c10fd6cb87 \
+    --hash=sha256:3ce80b34b22b17ccbd937a6e78e7225d80c52f5ab9940fe0506a1a16f3dab503 \
+    --hash=sha256:62ea666235135fee79bb154e695f3ff67370afefd71bd7fea7512fc70ef31e3d \
+    --hash=sha256:6c6f2969607b5023b0d9ce2541f8d2cbb01c4f46bc87456017cf63b73f1e2d8c \
+    --hash=sha256:718a38f7e5b058e76aee1c56ddd06908116d35147e133427e59a3983f703a20d \
+    --hash=sha256:750ec6e621af2b948540032557b10a2d43b0cee2ae9758c54154d711cc852d31 \
+    --hash=sha256:797c2772017851984b97180b0bebe4b620bb86328e8a884bb626156295a63b3b \
+    --hash=sha256:7b4075d959648406202d92a2310cb990fea19b535c7f4a78d3f5e10b926eeb8a \
+    --hash=sha256:a508e2d9025764a8270f93111a970e1d0fbfc33f4153b388bb649b7eec4f9b42 \
+    --hash=sha256:a733f1388e1a842abb67ffa8e7aad0e70ac519e09b0f6a784e65a136ec7cefd2 \
+    --hash=sha256:aba8f82d551a942cb20d4a83413ccbac30790b50efb89a75e4f586ac0bb8056b \
+    --hash=sha256:b7a2c10b93f8986666d0c803ee19b5990885872a7de910fc460f9b0c2fbf92ee \
+    --hash=sha256:b8c095edad5c211ff31c05223658e71bf7116daa0ecf3ad85f3201ea3190d067 \
+    --hash=sha256:c8015b09fb9a5e188f83b7b04de91ddca4658cee2ae6f3bc483f0b21a77ef6cd \
+    --hash=sha256:d03ff496d2a0cd4a5893504789d4a15399133fe82517455e78bad62efbb7f0a3 \
+    --hash=sha256:e0c4cfb0621281fe40387df582097fd796e80430597cb9944f0ae70447bacd91 \
+    --hash=sha256:e286f46a9a39c4a18b319c28f59b61de793654af2f395c102b4f819e584b5852 \
+    --hash=sha256:f95ba5a847cba10dd8c4d8fefa9f2a6cf283b8b88ed6178fa8a6c1ab16054d0d
     # via docker
 pyyaml==6.0.2 \
     --hash=sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff \

From cf3c7eaf4e668e064e3260b09e366231075cfc8c Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Mon, 21 Jul 2025 19:18:45 -0500
Subject: [PATCH 145/157] Run dependabot monthly instead of weekly (#709)

The CI is expensive and there is ~no benefit to end users from a faster
update cadence
---
 .github/dependabot.yml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index 7a977433..a79e311f 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -3,7 +3,7 @@ updates:
 - package-ecosystem: "pip"
   directory: "/"
   schedule:
-    interval: "weekly"
+    interval: "monthly"
   groups:
     python:
       patterns:
@@ -11,7 +11,7 @@ updates:
 - package-ecosystem: "cargo"
   directory: "/"
   schedule:
-    interval: "weekly"
+    interval: "monthly"
   groups:
     rust:
       patterns:

From 0ca55fec9f0f20edf1907f7e2b2824d4b54ea03b Mon Sep 17 00:00:00 2001
From: Geoffrey Thomas <geofft@ldpreload.com>
Date: Tue, 22 Jul 2025 20:12:07 -0400
Subject: [PATCH 146/157] Bump CPython to 3.14.0rc1 (#710)

---
 cpython-unix/extension-modules.yml | 3 +++
 pythonbuild/downloads.py           | 8 ++++----
 2 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/cpython-unix/extension-modules.yml b/cpython-unix/extension-modules.yml
index 4b834563..c069ca1b 100644
--- a/cpython-unix/extension-modules.yml
+++ b/cpython-unix/extension-modules.yml
@@ -206,6 +206,9 @@ _curses_panel:
 _datetime:
   sources:
     - _datetimemodule.c
+  setup-enabled-conditional:
+    - enabled: true
+      minimum-python-version: "3.14"
 
 _dbm:
   sources:
diff --git a/pythonbuild/downloads.py b/pythonbuild/downloads.py
index 20d5c98a..78a24011 100644
--- a/pythonbuild/downloads.py
+++ b/pythonbuild/downloads.py
@@ -82,10 +82,10 @@
         "python_tag": "cp313",
     },
     "cpython-3.14": {
-        "url": "https://www.python.org/ftp/python/3.14.0/Python-3.14.0b4.tar.xz",
-        "size": 23641472,
-        "sha256": "15e123e056abebba6de5e73cfa304459a8c82cafa85d4fc7fc6de80e6a3e1b39",
-        "version": "3.14.0b4",
+        "url": "https://www.python.org/ftp/python/3.14.0/Python-3.14.0rc1.tar.xz",
+        "size": 23661916,
+        "sha256": "8707780ae9f19c5bf5b9f27827181ba11cdad7bb292ea49cad5424331e40ee8b",
+        "version": "3.14.0rc1",
         "licenses": ["Python-2.0", "CNRI-Python"],
         "license_file": "LICENSE.cpython.txt",
         "python_tag": "cp314",

From 32b1e3038310a9e6333f65fc49d27e164174998c Mon Sep 17 00:00:00 2001
From: Geoffrey Thomas <geofft@ldpreload.com>
Date: Tue, 1 Jul 2025 16:02:59 -0400
Subject: [PATCH 147/157] Allow using a custom GitHub API endpoint for
 releasing

This lets me test the release scripts against a custom, fault-injected
Python server, but I suppose it might also be useful for downstream
users who have GHES, maybe. Patches welcome if anyone is using this and
it doesn't quite work right!
---
 src/github.rs | 30 ++++++++++++++++--------------
 src/main.rs   | 12 ++++++++++++
 2 files changed, 28 insertions(+), 14 deletions(-)

diff --git a/src/github.rs b/src/github.rs
index 70342008..f42d9995 100644
--- a/src/github.rs
+++ b/src/github.rs
@@ -112,6 +112,20 @@ async fn upload_release_artifact(
     Ok(())
 }
 
+fn new_github_client(args: &ArgMatches) -> Result<(Octocrab, String)> {
+    let token = args
+        .get_one::<String>("token")
+        .expect("token should be specified")
+        .to_string();
+    let github_uri = args.get_one::<String>("github-uri");
+
+    let mut builder = OctocrabBuilder::new().personal_token(token.clone());
+    if let Some(github_uri) = github_uri {
+        builder = builder.base_uri(github_uri.clone())?;
+    }
+    Ok((builder.build()?, token))
+}
+
 pub async fn command_fetch_release_distributions(args: &ArgMatches) -> Result<()> {
     let dest_dir = args
         .get_one::<PathBuf>("dest")
@@ -121,13 +135,7 @@ pub async fn command_fetch_release_distributions(args: &ArgMatches) -> Result<()
         .expect("organization should be set");
     let repo = args.get_one::<String>("repo").expect("repo should be set");
 
-    let client = OctocrabBuilder::new()
-        .personal_token(
-            args.get_one::<String>("token")
-                .expect("token should be required argument")
-                .to_string(),
-        )
-        .build()?;
+    let (client, _) = new_github_client(args)?;
 
     let release_version_range = pep440_rs::VersionSpecifier::from_str(">=3.9")?;
 
@@ -358,10 +366,6 @@ pub async fn command_upload_release_distributions(args: &ArgMatches) -> Result<(
         .get_one::<String>("tag")
         .expect("tag should be specified");
     let ignore_missing = args.get_flag("ignore_missing");
-    let token = args
-        .get_one::<String>("token")
-        .expect("token should be specified")
-        .to_string();
     let organization = args
         .get_one::<String>("organization")
         .expect("organization should be specified");
@@ -451,9 +455,7 @@ pub async fn command_upload_release_distributions(args: &ArgMatches) -> Result<(
         return Err(anyhow!("missing {} release artifacts", missing.len()));
     }
 
-    let client = OctocrabBuilder::new()
-        .personal_token(token.clone())
-        .build()?;
+    let (client, token) = new_github_client(args)?;
     let repo_handler = client.repos(organization, repo);
     let releases = repo_handler.releases();
 
diff --git a/src/main.rs b/src/main.rs
index df441e13..c8d422e8 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -70,6 +70,12 @@ fn main_impl() -> Result<()> {
                     .action(ArgAction::Set)
                     .default_value("python-build-standalone")
                     .help("GitHub repository name"),
+            )
+            .arg(
+                Arg::new("github-uri")
+                    .long("github-uri")
+                    .action(ArgAction::Set)
+                    .help("Alternative GitHub URI"),
             ),
     );
 
@@ -154,6 +160,12 @@ fn main_impl() -> Result<()> {
                     .action(ArgAction::Set)
                     .default_value("python-build-standalone")
                     .help("GitHub repository name"),
+            )
+            .arg(
+                Arg::new("github-uri")
+                    .long("github-uri")
+                    .action(ArgAction::Set)
+                    .help("Alternative GitHub URI"),
             ),
     );
 

From abac59fdd834e9a84aa2a3a6954232ddce772c66 Mon Sep 17 00:00:00 2001
From: Geoffrey Thomas <geofft@ldpreload.com>
Date: Sun, 29 Jun 2025 16:34:13 -0400
Subject: [PATCH 148/157] Do not load the entire artifact in memory when
 uploading (#618)

---
 Cargo.lock               |   1 +
 Cargo.toml               |   1 +
 src/github.rs            | 119 +++++++++-----
 src/github_api_tester.py | 340 +++++++++++++++++++++++++++++++++++++++
 4 files changed, 424 insertions(+), 37 deletions(-)
 create mode 100755 src/github_api_tester.py

diff --git a/Cargo.lock b/Cargo.lock
index dcb95c77..6a2f0890 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1570,6 +1570,7 @@ dependencies = [
  "tempfile",
  "text-stub-library",
  "tokio",
+ "tokio-util",
  "url",
  "version-compare",
  "zip",
diff --git a/Cargo.toml b/Cargo.toml
index 9b4af3a7..b74eeb6e 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -37,6 +37,7 @@ tar = "0.4.40"
 tempfile = "3.10.0"
 text-stub-library = "0.9.0"
 tokio = "1.43.1"
+tokio-util = "0.7.13"
 url = "2.5.0"
 version-compare = "0.1.1"
 zip = "0.6.6"
diff --git a/src/github.rs b/src/github.rs
index f42d9995..676104f9 100644
--- a/src/github.rs
+++ b/src/github.rs
@@ -17,10 +17,9 @@ use {
     },
     rayon::prelude::*,
     reqwest::{Client, StatusCode},
-    reqwest_middleware::{self, ClientWithMiddleware},
     reqwest_retry::{
-        default_on_request_failure, policies::ExponentialBackoff, RetryTransientMiddleware,
-        Retryable, RetryableStrategy,
+        default_on_request_failure, policies::ExponentialBackoff, RetryPolicy, Retryable,
+        RetryableStrategy,
     },
     sha2::{Digest, Sha256},
     std::{
@@ -28,6 +27,7 @@ use {
         io::Read,
         path::PathBuf,
         str::FromStr,
+        time::{Duration, SystemTime},
     },
     url::Url,
     zip::ZipArchive,
@@ -65,12 +65,19 @@ async fn fetch_artifact(
     Ok(res)
 }
 
+enum UploadSource {
+    Filename(PathBuf),
+    Data(Bytes),
+}
+
 async fn upload_release_artifact(
-    client: &ClientWithMiddleware,
+    client: &Client,
+    retry_policy: &impl RetryPolicy,
+    retryable_strategy: &impl RetryableStrategy,
     auth_token: String,
     release: &Release,
     filename: String,
-    data: Bytes,
+    body: UploadSource,
     dry_run: bool,
 ) -> Result<()> {
     if release.assets.iter().any(|asset| asset.name == filename) {
@@ -93,17 +100,52 @@ async fn upload_release_artifact(
         return Ok(());
     }
 
-    // Octocrab doesn't yet support release artifact upload. And the low-level HTTP API
-    // forces the use of strings on us. So we have to make our own HTTP client.
-
-    let response = client
-        .put(url)
-        .header("Authorization", format!("Bearer {auth_token}"))
-        .header("Content-Length", data.len())
-        .header("Content-Type", "application/x-tar")
-        .body(data)
-        .send()
-        .await?;
+    // Octocrab's high-level API for uploading release artifacts doesn't yet support streaming
+    // bodies, and their low-level API isn't more helpful than using our own HTTP client.
+    //
+    // Because we are streaming the body, we can't use the standard retry middleware for reqwest
+    // (see e.g. https://github.com/seanmonstar/reqwest/issues/2416), so we have to recreate the
+    // request on each retry and handle the retry logic ourself. This logic is inspired by
+    // uv/crates/uv-publish/src/lib.rs (which has the same problem), which in turn is inspired by
+    // reqwest-middleware/reqwest-retry/src/middleware.rs.
+    //
+    // (While Octocrab's API would work fine for the non-streaming case, we just use this function
+    // for both cases so that we can make a homogeneous Vec<impl Future> later in the file.)
+
+    let mut n_past_retries = 0;
+    let start_time = SystemTime::now();
+    let response = loop {
+        let request = client
+            .put(url.clone())
+            .timeout(Duration::from_secs(60))
+            .header("Authorization", format!("Bearer {auth_token}"))
+            .header("Content-Type", "application/octet-stream");
+        let request = match body {
+            UploadSource::Filename(ref path) => {
+                let file = tokio::fs::File::open(&path).await?;
+                let len = file.metadata().await?.len();
+                request.header("Content-Length", len).body(file)
+            }
+            UploadSource::Data(ref bytes) => request
+                .header("Content-Length", bytes.len())
+                .body(bytes.clone()),
+        };
+        let result = request.send().await.map_err(|e| e.into());
+
+        if retryable_strategy.handle(&result) == Some(Retryable::Transient) {
+            let retry_decision = retry_policy.should_retry(start_time, n_past_retries);
+            if let reqwest_retry::RetryDecision::Retry { execute_after } = retry_decision {
+                println!("retrying upload to {url} after {result:?}");
+                let duration = execute_after
+                    .duration_since(SystemTime::now())
+                    .unwrap_or_else(|_| Duration::default());
+                tokio::time::sleep(duration).await;
+                n_past_retries += 1;
+                continue;
+            }
+        }
+        break result?;
+    };
 
     if !response.status().is_success() {
         return Err(anyhow!("HTTP {}", response.status()));
@@ -215,10 +257,8 @@ pub async fn command_fetch_release_distributions(args: &ArgMatches) -> Result<()
             .await?;
 
         for artifact in artifacts {
-            if matches!(
-                artifact.name.as_str(),
-                "pythonbuild" | "toolchain"
-            ) || artifact.name.contains("install-only")
+            if matches!(artifact.name.as_str(), "pythonbuild" | "toolchain")
+                || artifact.name.contains("install-only")
             {
                 continue;
             }
@@ -475,12 +515,7 @@ pub async fn command_upload_release_distributions(args: &ArgMatches) -> Result<(
     let mut digests = BTreeMap::new();
 
     let retry_policy = ExponentialBackoff::builder().build_with_max_retries(5);
-    let raw_client = reqwest_middleware::ClientBuilder::new(Client::new())
-        .with(RetryTransientMiddleware::new_with_policy_and_strategy(
-            retry_policy,
-            GitHubUploadRetryStrategy,
-        ))
-        .build();
+    let raw_client = Client::new();
 
     {
         let mut fs = vec![];
@@ -490,23 +525,31 @@ pub async fn command_upload_release_distributions(args: &ArgMatches) -> Result<(
                 continue;
             }
 
-            let file_data = Bytes::copy_from_slice(&std::fs::read(dist_dir.join(&source))?);
-
-            let mut digest = Sha256::new();
-            digest.update(&file_data);
-
-            let digest = hex::encode(digest.finalize());
-
-            digests.insert(dest.clone(), digest.clone());
-
+            let local_filename = dist_dir.join(&source);
             fs.push(upload_release_artifact(
                 &raw_client,
+                &retry_policy,
+                &GitHubUploadRetryStrategy,
                 token.clone(),
                 &release,
                 dest.clone(),
-                file_data,
+                UploadSource::Filename(local_filename.clone()),
                 dry_run,
             ));
+
+            // reqwest wants to take ownership of the body, so it's hard for us to do anything
+            // clever with reading the file once and calculating the sha256sum while we read.
+            // So we open and read the file again.
+            let digest = {
+                let file = tokio::fs::File::open(local_filename).await?;
+                let mut stream = tokio_util::io::ReaderStream::with_capacity(file, 1048576);
+                let mut hasher = Sha256::new();
+                while let Some(chunk) = stream.next().await {
+                    hasher.update(&chunk?);
+                }
+                hex::encode(hasher.finalize())
+            };
+            digests.insert(dest.clone(), digest.clone());
         }
 
         let mut buffered = futures::stream::iter(fs).buffer_unordered(16);
@@ -526,10 +569,12 @@ pub async fn command_upload_release_distributions(args: &ArgMatches) -> Result<(
 
     upload_release_artifact(
         &raw_client,
+        &retry_policy,
+        &GitHubUploadRetryStrategy,
         token.clone(),
         &release,
         "SHA256SUMS".to_string(),
-        Bytes::copy_from_slice(shasums.as_bytes()),
+        UploadSource::Data(Bytes::copy_from_slice(shasums.as_bytes())),
         dry_run,
     )
     .await?;
diff --git a/src/github_api_tester.py b/src/github_api_tester.py
new file mode 100755
index 00000000..9ff4bc07
--- /dev/null
+++ b/src/github_api_tester.py
@@ -0,0 +1,340 @@
+#!/usr/bin/env -S uv run
+#
+# A fake GitHub API server for testing upload-release-distributions's
+# behavior in the presence of API failures.
+#
+# Call with no arguments or with pytest CLI arguments to run the tests
+# at the bottom which invoke `cargo run`.
+#
+# Call with one argument "serve" to start an HTTP server on 0.0.0.0.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# /// script
+# requires-python = ">=3.13"
+# dependencies = [
+#     "quart>=0.20.0",
+#     "quart-trio>=0.12.0",
+#     # Pinned because we mess with hypercorn internals, see below.
+#     "hypercorn==0.17.3",
+#     "pytest",
+#     "pytest-trio",
+# ]
+# ///
+
+import dataclasses
+import hashlib
+import logging
+import os
+import sys
+from collections.abc import Callable
+
+import hypercorn
+import pytest
+import quart
+import trio
+from quart import request
+from quart_trio import QuartTrio
+
+app = QuartTrio(__name__)
+app.config["MAX_CONTENT_LENGTH"] = None
+
+
+async def drop_connection():
+    """Drop the (HTTP/1.1) connection belonging to the current Quart request."""
+    # We need to do two things:
+    # - Convince hypercorn (specifically, around HTTPStream.app_send())
+    #   that it doesn't need to send a 500 and can just close the socket.
+    # - Convince h11's state machine that it's okay to close the socket
+    #   without sending a response.
+    # We can't do this at the ASGI layer: hypercorn will insert the 500
+    # for protocol compliance if the ASGI app doesn't provide a
+    # response. We need to modify the actual HTTP server, either with a
+    # pull request or by digging into its internals as follows:
+    # - Grab the HTTPStream whose bound method app_send was passed into
+    #   the Quart request
+    # - Grab the H11Protocol whose bound method stream_send was passed
+    #   into the HTTPStream's constructor
+    # - Tell the H11Protocol's underlying h11 state machine to act as if
+    #   the remote side errored, so it thinks dropping the connection is
+    #   the appropriate next step and not misbehavior on our end
+    # - Tell the HTTPStream to move the state machine forward with no
+    #   further send on our side, which will drop the connection (and
+    #   not consider it for keepalive)
+    import hypercorn.protocol as hp
+
+    http_stream: hp.http_stream.HTTPStream = request._send_push_promise.args[0].__self__
+    protocol: hp.h11.H11Protocol = http_stream.send.__self__
+    protocol.connection._process_error(protocol.connection.their_role)
+    await http_stream.send(hp.events.EndBody(stream_id=http_stream.stream_id))
+    await http_stream.app_send(None)
+
+    # Some other things I tried, kept for reference:
+    # http_stream.state = hypercorn.protocol.http_stream.ASGIHTTPState.RESPONSE
+    # await http_stream._send_closed()
+    # http_stream.state = hypercorn.protocol.http_stream.ASGIHTTPState.CLOSED
+
+
+# The following GitHub API datatypes are complete enough to satisfy
+# octocrab's deserialization.
+
+
+@dataclasses.dataclass
+class Asset:
+    name: str
+    label: str | None
+    sha256: str
+    contents: bytes | None
+
+    _ASSETS = []
+
+    def __post_init__(self):
+        self.id = len(self._ASSETS)
+        self._ASSETS.append(self)
+
+    def render(self) -> dict:
+        return {
+            "url": quart.url_for("get_asset", id=self.id, _external=True),
+            "browser_download_url": "https://github.invalid/unneeded",
+            "id": self.id,
+            "node_id": "fakenode",
+            "name": self.name,
+            "label": self.label,
+            "state": "uploaded",
+            "content_type": "application/octet-stream",
+            "size": 1000,
+            "download_count": 1000,
+            "created_at": "2020-01-01T00:00:00Z",
+            "updated_at": "2020-01-01T00:00:00Z",
+            "uploader": None,
+        }
+
+
+@dataclasses.dataclass
+class Upload:
+    name: str
+    label: str | None
+
+    def __post_init__(self):
+        self.hasher = hashlib.sha256()
+        if self.name == "SHA256SUMS":
+            self.contents = b""
+        else:
+            self.contents = None
+
+    def update(self, chunk: bytes) -> None:
+        self.hasher.update(chunk)
+        if self.contents is not None:
+            self.contents += chunk
+
+    def to_asset(self) -> Asset:
+        return Asset(self.name, self.label, self.hasher.hexdigest(), self.contents)
+
+
+@dataclasses.dataclass
+class Release:
+    release_id: int
+    tag_name: str
+    assets: list = dataclasses.field(default_factory=list)
+    # fault0 and fault1 are called before and after receiving the first
+    # chunk of a PUT request, respectively. Each is called once per
+    # release - the first upload that hits it will disarm it.
+    fault0: Callable[[], None] | None = None
+    fault1: Callable[[], None] | None = None
+
+    def render(self) -> dict:
+        upload_asset = quart.url_for(
+            "upload_asset", release=self.release_id, _external=True
+        )
+        return {
+            "url": request.url,
+            "html_url": "https://github.invalid/unneeded",
+            "assets_url": "https://github.invalid/unneeded",
+            "upload_url": upload_asset + "{?name,label}",
+            "id": self.release_id,
+            "node_id": "fakenode",
+            "tag_name": self.tag_name,
+            "target_commitish": "main",
+            "draft": False,
+            "prerelease": True,
+            "assets": [i.render() for i in self.assets],
+        }
+
+
+releases = [
+    Release(1, "basic"),
+    Release(11, "early-drop", fault0=drop_connection),
+    Release(12, "late-drop", fault1=drop_connection),
+    Release(4011, "early-401", fault0=lambda: quart.abort(401)),
+    Release(4012, "late-401", fault1=lambda: quart.abort(401)),
+    Release(4031, "early-403", fault0=lambda: quart.abort(403)),
+    Release(4032, "late-403", fault1=lambda: quart.abort(403)),
+    Release(5001, "early-500", fault0=lambda: quart.abort(500)),
+    Release(5002, "late-500", fault1=lambda: quart.abort(500)),
+]
+
+
+def get_release(*, tag=None, release=None) -> Release:
+    if tag is not None:
+        condition = lambda r: r.tag_name == tag
+    elif release is not None:
+        condition = lambda r: r.release_id == release
+    else:
+        raise TypeError("tag or release must be set")
+
+    for r in releases:
+        if condition(r):
+            return r
+    quart.abort(404, response=quart.jsonify({"message": "Not Found", "status": "404"}))
+
+
+# GitHub API functions
+
+
+@app.route("/repos/<org>/<repo>/releases/tags/<tag>")
+async def get_release_by_tag(org, repo, tag):
+    return get_release(tag=tag).render()
+
+
+@app.route("/repos/<org>/<repo>/releases/<int:release>")
+async def get_release_by_id(org, repo, release):
+    return get_release(release=release).render()
+
+
+@app.put("/upload/<int:release>/assets")
+async def upload_asset(release):
+    filename = request.args["name"]
+    release = get_release(release=release)
+
+    if (fault := release.fault0) is not None:
+        logging.info(f"{filename}: injecting fault0")
+        release.fault0 = None
+        return await fault()
+
+    logging.info(f"{filename}: upload begin")
+    upload = Upload(filename, request.args.get("label"))
+    async for chunk in request.body:
+        logging.debug(f"{filename}: {len(chunk)=}")
+        upload.update(chunk)
+        if (fault := release.fault1) is not None:
+            if "SHA256" not in filename:
+                logging.info(f"{filename}: injecting fault1")
+                release.fault1 = None
+                return await fault()
+
+    asset = upload.to_asset()
+    logging.info(f"{filename}: upload complete, {asset.sha256=}")
+    release.assets.append(asset)
+    return asset.render()
+
+
+@app.route("/get_asset/<int:id>")
+@app.route("/repos/<org>/<repo>/releases/assets/<int:id>")
+async def get_asset(id, org=None, repo=None):
+    try:
+        asset = Asset._ASSETS[id]
+    except IndexError:
+        quart.abort(
+            404, response=quart.jsonify({"message": "Not Found", "status": "404"})
+        )
+
+    if "application/octet-stream" in request.accept_mimetypes:
+        if asset.contents is None:
+            print(
+                f"USAGE ERROR: Received request for contents of {asset.filename=} which was not stored"
+            )
+            return "Did not store contents", 410
+        return asset.contents
+    else:
+        return asset.render()
+
+
+# Generic upload function, useful for testing clients in isolation
+
+
+@app.put("/file/<path:path>")
+async def upload_file(path):
+    logging.info(f"{path}: upload begin")
+    s = hashlib.sha256()
+    async for chunk in request.body:
+        logging.debug(f"{path}: {len(chunk)=}")
+        if "drop" in request.args:
+            await drop_connection()
+        s.update(chunk)
+    digest = s.hexdigest()
+    logging.info(f"{path}: {digest=}")
+    return f"{digest}  {path}\n", 500
+
+
+# Test cases
+
+
+@pytest.fixture
+async def server(nursery):
+    await nursery.start(app.run_task)
+
+
+FILENAME = "cpython-3.0.0-x86_64-unknown-linux-gnu-install_only-19700101T1234.tar.gz"
+SHA256_20MEG = "9e21c61969cd3e077a1b2b58ddb583b175e13c6479d2d83912eaddc23c0cdd52"
+
+
+@pytest.fixture(scope="session")
+def upload_release_distributions(tmp_path_factory):
+    dist = tmp_path_factory.mktemp("dist")
+    filename = dist / FILENAME
+    filename.touch()
+    os.truncate(filename, 20_000_000)
+
+    async def upload_release_distributions(*args):
+        return await trio.run_process(
+            [
+                "cargo",
+                "run",
+                "--",
+                "upload-release-distributions",
+                "--github-uri",
+                "http://localhost:5000",
+                "--token",
+                "no-token-needed",
+                "--dist",
+                dist,
+                "--datetime",
+                "19700101T1234",
+                "--ignore-missing",
+            ]
+            + list(args)
+        )
+
+    return upload_release_distributions
+
+
+# TODO: test all of [r.tag_name for r in releases]
+TAGS_TO_TEST = ["basic", "early-drop", "late-drop", "early-403", "late-403"]
+
+
+@pytest.mark.parametrize("tag", TAGS_TO_TEST)
+async def test_upload(server, upload_release_distributions, tag):
+    with trio.fail_after(300):
+        await upload_release_distributions("--tag", tag)
+    release = get_release(tag=tag)
+    assets = sorted(release.assets, key=lambda a: a.name)
+    assert len(assets) == 2
+    assert assets[0].name == "SHA256SUMS"
+    filename = FILENAME.replace("3.0.0", f"3.0.0+{tag}").replace("-19700101T1234", "")
+    assert assets[1].name == filename
+    assert assets[1].sha256 == SHA256_20MEG
+    assert assets[0].contents == f"{SHA256_20MEG}  {filename}\n".encode()
+
+
+# Work around https://github.com/pgjones/hypercorn/issues/238 not being in a release
+# Without it, test failures are unnecessarily noisy
+hypercorn.trio.lifespan.LifespanFailureError = trio.Cancelled
+
+if __name__ == "__main__":
+    if len(sys.argv) > 1 and sys.argv[1] == "serve":
+        logging.basicConfig(level=logging.INFO)
+        app.run("0.0.0.0")
+    else:
+        pytest.main(["-o", "trio_mode=true", __file__] + sys.argv[1:])

From a376f32981a4e690963fe29a6ae31203afb440ae Mon Sep 17 00:00:00 2001
From: Geoffrey Thomas <geofft@ldpreload.com>
Date: Wed, 23 Jul 2025 10:51:58 -0400
Subject: [PATCH 149/157] Go back to the normal runner for the releease process

Now that we're not loading every artifact in memory, hopefully the
normal runner will work.
---
 .github/workflows/release.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 6381b3e5..a81dc2f9 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -29,7 +29,7 @@ jobs:
   release:
     env:
       GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-    runs-on: github-ubuntu-24.04-x86_64-16
+    runs-on: ubuntu-latest
     steps:
       - uses: actions/checkout@v4
         with:

From 98ed87173db339948c7a666937ceed396ec519ec Mon Sep 17 00:00:00 2001
From: William Woodruff <william@astral.sh>
Date: Fri, 1 Aug 2025 10:25:32 -0400
Subject: [PATCH 150/157] chore(ci): apply security fixes, add zizmor workflow
 (#716)

---
 .github/dependabot.yml        | 46 +++++++++++++++++---------
 .github/workflows/check.yml   |  4 +++
 .github/workflows/linux.yml   | 62 ++++++++++++++++++++++++++---------
 .github/workflows/macos.yml   | 38 ++++++++++++++-------
 .github/workflows/release.yml | 50 ++++++++++++++++++----------
 .github/workflows/windows.yml | 31 +++++++++++++-----
 .github/workflows/zizmor.yml  | 24 ++++++++++++++
 .github/zizmor.yml            |  7 ++++
 8 files changed, 194 insertions(+), 68 deletions(-)
 create mode 100644 .github/workflows/zizmor.yml
 create mode 100644 .github/zizmor.yml

diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index a79e311f..b2994206 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -1,18 +1,32 @@
 version: 2
 updates:
-- package-ecosystem: "pip"
-  directory: "/"
-  schedule:
-    interval: "monthly"
-  groups:
-    python:
-      patterns:
-        - "*"
-- package-ecosystem: "cargo"
-  directory: "/"
-  schedule:
-    interval: "monthly"
-  groups:
-    rust:
-      patterns:
-        - "*"
+  - package-ecosystem: "pip"
+    directory: "/"
+    schedule:
+      interval: "monthly"
+    cooldown:
+      default-days: 14
+    groups:
+      python:
+        patterns:
+          - "*"
+  - package-ecosystem: "cargo"
+    directory: "/"
+    schedule:
+      interval: "monthly"
+    cooldown:
+      default-days: 14
+    groups:
+      rust:
+        patterns:
+          - "*"
+  - package-ecosystem: "github-actions"
+    directory: ".github/workflows"
+    schedule:
+      interval: "monthly"
+    cooldown:
+      default-days: 14
+    groups:
+      actions:
+        patterns:
+          - "*"
diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml
index 5630ba46..c7874e74 100644
--- a/.github/workflows/check.yml
+++ b/.github/workflows/check.yml
@@ -12,12 +12,16 @@ concurrency:
 env:
   FORCE_COLOR: 1
 
+permissions: {}
+
 jobs:
   check:
     runs-on: "ubuntu-latest"
     name: "check"
     steps:
       - uses: actions/checkout@v4
+        with:
+          persist-credentials: false
       - uses: actions/setup-python@v5
         with:
           python-version: "3.12"
diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml
index 39bc8733..2ed390b7 100644
--- a/.github/workflows/linux.yml
+++ b/.github/workflows/linux.yml
@@ -2,7 +2,7 @@ name: linux
 
 on:
   push:
-    branches: [ main ]
+    branches: [main]
   pull_request:
 
 concurrency:
@@ -12,6 +12,8 @@ concurrency:
 env:
   FORCE_COLOR: 1
 
+permissions: {}
+
 jobs:
   crate-build:
     needs:
@@ -28,6 +30,8 @@ jobs:
           sudo apt install -y --no-install-recommends libssl-dev pkg-config
 
       - uses: actions/checkout@v4
+        with:
+          persist-credentials: false
 
       - name: Emit rustc version
         run: |
@@ -64,11 +68,13 @@ jobs:
       packages: write
     steps:
       - uses: actions/checkout@v4
+        with:
+          persist-credentials: false
 
       - name: Install Python
         uses: actions/setup-python@v5
         with:
-          python-version: '3.11'
+          python-version: "3.11"
 
       - name: Set up Docker Buildx
         uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3
@@ -90,7 +96,7 @@ jobs:
 
       - name: Build Image
         id: build-image
-        uses: docker/build-push-action@v5
+        uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0
         with:
           context: .
           file: build/${{ matrix.name }}.Dockerfile
@@ -110,8 +116,12 @@ jobs:
 
       - name: Compress Image
         run: |
-          echo ${{ steps.build-image.outputs.imageid }} > build/image-${{ matrix.name }}.linux_${{ matrix.arch }}
+          echo ${STEPS_BUILD_IMAGE_OUTPUTS_IMAGEID} > build/image-${MATRIX_NAME}.linux_${MATRIX_ARCH}
           zstd -v -T0 -6 --rm build/image-*.tar
+        env:
+          STEPS_BUILD_IMAGE_OUTPUTS_IMAGEID: ${{ steps.build-image.outputs.imageid }}
+          MATRIX_NAME: ${{ matrix.name }}
+          MATRIX_ARCH: ${{ matrix.arch }}
 
       - name: Upload Docker Image
         uses: actions/upload-artifact@v4
@@ -120,6 +130,7 @@ jobs:
           path: build/image-*
 
   generate-matrix:
+    name: Generate build matrix
     runs-on: ubuntu-latest
     outputs:
       python-build-matrix-0: ${{ steps.set-matrix.outputs.python-build-matrix-0 }}
@@ -130,16 +141,19 @@ jobs:
     steps:
       - uses: actions/checkout@v4
         with:
-          fetch-depth: 0  # fetch history for subsequent `git diff`
+          fetch-depth: 0
+          persist-credentials: false
 
       - name: Set up Python
         uses: astral-sh/setup-uv@v4
 
       - name: Get pull request labels
         id: get-labels
+        env:
+          PULL_REQUEST_LABELS: ${{ toJson(github.event.pull_request.labels.*.name) }}
         run: |
           # Convert GitHub labels array to comma-separated string
-          LABELS=$(echo '${{ toJson(github.event.pull_request.labels.*.name) }}' | jq -r 'join(",")')
+          LABELS=$(echo "${PULL_REQUEST_LABELS}" | jq -r 'join(",")')
           echo "labels=$LABELS" >> $GITHUB_OUTPUT
 
       - name: Check if the `pythonbuild` crate changed
@@ -159,7 +173,7 @@ jobs:
         run: |
           uv run ci-matrix.py \
             --platform linux \
-            --labels '${{ steps.get-labels.outputs.labels }}' \
+            --labels '${STEPS_GET_LABELS_OUTPUTS_LABELS}' \
             --max-shards 2 \
             ${{ (steps.check-pythonbuild.outputs.changed == 'true' || github.ref == 'refs/heads/main') && '--force-crate-build' || '' }} \
             > matrix.json
@@ -179,6 +193,8 @@ jobs:
             # Build matrix is empty
             echo "any_builds=false" >> $GITHUB_OUTPUT
           fi
+        env:
+          STEPS_GET_LABELS_OUTPUTS_LABELS: ${{ steps.get-labels.outputs.labels }}
 
   build-0:
     needs:
@@ -198,11 +214,12 @@ jobs:
       - uses: actions/checkout@v4
         with:
           fetch-depth: 0
+          persist-credentials: false
 
       - name: Install Python
         uses: actions/setup-python@v5
         with:
-          python-version: '3.11'
+          python-version: "3.11"
 
       - name: Download pythonbuild
         uses: actions/download-artifact@v4
@@ -247,7 +264,11 @@ jobs:
           # Touch mtimes of all images so they are newer than autogenerated files above.
           touch build/image-*
 
-          ./build-linux.py --target-triple ${{ matrix.target_triple }} --python cpython-${{ matrix.python }} --options ${{ matrix.build_options }}
+          ./build-linux.py --target-triple ${MATRIX_TARGET_TRIPLE} --python cpython-${MATRIX_PYTHON} --options ${MATRIX_BUILD_OPTIONS}
+        env:
+          MATRIX_TARGET_TRIPLE: ${{ matrix.target_triple }}
+          MATRIX_PYTHON: ${{ matrix.python }}
+          MATRIX_BUILD_OPTIONS: ${{ matrix.build_options }}
 
       - name: Generate attestations
         uses: actions/attest-build-provenance@v2
@@ -267,8 +288,8 @@ jobs:
         run: |
           chmod +x build/pythonbuild
 
-          if [ "${{ matrix.run }}" == "true" ]; then
-            if [ "${{ matrix.libc }}" == "musl" ]; then
+          if [ "${MATRIX_RUN}" == "true" ]; then
+            if [ "${MATRIX_LIBC}" == "musl" ]; then
               sudo apt install musl-dev
 
               # GitHub's setup-python action sets `LD_LIBRARY_PATH` which overrides `RPATH`
@@ -279,6 +300,9 @@ jobs:
           fi
 
           build/pythonbuild validate-distribution ${EXTRA_ARGS} dist/*.tar.zst
+        env:
+          MATRIX_RUN: ${{ matrix.run }}
+          MATRIX_LIBC: ${{ matrix.libc }}
 
   build-1:
     needs:
@@ -298,11 +322,12 @@ jobs:
       - uses: actions/checkout@v4
         with:
           fetch-depth: 0
+          persist-credentials: false
 
       - name: Install Python
         uses: actions/setup-python@v5
         with:
-          python-version: '3.11'
+          python-version: "3.11"
 
       - name: Download pythonbuild
         uses: actions/download-artifact@v4
@@ -347,7 +372,11 @@ jobs:
           # Touch mtimes of all images so they are newer than autogenerated files above.
           touch build/image-*
 
-          ./build-linux.py --target-triple ${{ matrix.target_triple }} --python cpython-${{ matrix.python }} --options ${{ matrix.build_options }}
+          ./build-linux.py --target-triple ${MATRIX_TARGET_TRIPLE} --python cpython-${MATRIX_PYTHON} --options ${MATRIX_BUILD_OPTIONS}
+        env:
+          MATRIX_TARGET_TRIPLE: ${{ matrix.target_triple }}
+          MATRIX_PYTHON: ${{ matrix.python }}
+          MATRIX_BUILD_OPTIONS: ${{ matrix.build_options }}
 
       - name: Generate attestations
         uses: actions/attest-build-provenance@v2
@@ -367,8 +396,8 @@ jobs:
         run: |
           chmod +x build/pythonbuild
 
-          if [ "${{ matrix.run }}" == "true" ]; then
-            if [ "${{ matrix.libc }}" == "musl" ]; then
+          if [ "${MATRIX_RUN}" == "true" ]; then
+            if [ "${MATRIX_LIBC}" == "musl" ]; then
               sudo apt install musl-dev
 
               # GitHub's setup-python action sets `LD_LIBRARY_PATH` which overrides `RPATH`
@@ -379,3 +408,6 @@ jobs:
           fi
 
           build/pythonbuild validate-distribution ${EXTRA_ARGS} dist/*.tar.zst
+        env:
+          MATRIX_RUN: ${{ matrix.run }}
+          MATRIX_LIBC: ${{ matrix.libc }}
diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml
index 1199b398..0bc73b13 100644
--- a/.github/workflows/macos.yml
+++ b/.github/workflows/macos.yml
@@ -12,6 +12,8 @@ concurrency:
 env:
   FORCE_COLOR: 1
 
+permissions: {}
+
 jobs:
   crate-build:
     needs:
@@ -23,6 +25,8 @@ jobs:
     name: crate / ${{ matrix.arch }}
     steps:
       - uses: actions/checkout@v4
+        with:
+          persist-credentials: false
 
       - name: Emit rustc version
         run: |
@@ -47,6 +51,7 @@ jobs:
           path: target/release/pythonbuild
 
   generate-matrix:
+    name: Generate build matrix
     runs-on: ubuntu-latest
     outputs:
       matrix: ${{ steps.set-matrix.outputs.matrix }}
@@ -55,16 +60,19 @@ jobs:
     steps:
       - uses: actions/checkout@v4
         with:
-          fetch-depth: 0  # fetch history for subsequent `git diff`
+          fetch-depth: 0
+          persist-credentials: false
 
       - name: Set up Python
         uses: astral-sh/setup-uv@v4
 
       - name: Get pull request labels
         id: get-labels
+        env:
+          PULL_REQUEST_LABELS: ${{ toJson(github.event.pull_request.labels.*.name) }}
         run: |
           # Convert GitHub labels array to comma-separated string
-          LABELS=$(echo '${{ toJson(github.event.pull_request.labels.*.name) }}' | jq -r 'join(",")')
+          LABELS=$(echo "${PULL_REQUEST_LABELS}" | jq -r 'join(",")')
           echo "labels=$LABELS" >> $GITHUB_OUTPUT
 
       - name: Check if the `pythonbuild` crate changed
@@ -82,12 +90,12 @@ jobs:
       - name: Generate build matrix
         id: set-matrix
         run: |
-          uv run ci-matrix.py --platform darwin --labels '${{ steps.get-labels.outputs.labels }}' ${{ (steps.check-pythonbuild.outputs.changed == 'true' || github.ref == 'refs/heads/main') && '--force-crate-build' || '' }} > matrix.json
-          
+          uv run ci-matrix.py --platform darwin --labels '${STEPS_GET_LABELS_OUTPUTS_LABELS}' ${{ (steps.check-pythonbuild.outputs.changed == 'true' || github.ref == 'refs/heads/main') && '--force-crate-build' || '' }} > matrix.json
+
           # Extract python-build matrix
           echo "matrix=$(jq -c '."python-build"' matrix.json)" >> $GITHUB_OUTPUT
           echo "crate-build-matrix=$(jq -c '."crate-build"' matrix.json)" >> $GITHUB_OUTPUT
-          
+
           # Display the matrix for debugging too
           cat matrix.json | jq
 
@@ -98,6 +106,8 @@ jobs:
             # Build matrix is empty
             echo "any_builds=false" >> $GITHUB_OUTPUT
           fi
+        env:
+          STEPS_GET_LABELS_OUTPUTS_LABELS: ${{ steps.get-labels.outputs.labels }}
 
   build:
     needs:
@@ -116,11 +126,12 @@ jobs:
       - uses: actions/checkout@v4
         with:
           fetch-depth: 0
+          persist-credentials: false
 
       - name: Install Python
         uses: actions/setup-python@v5
         with:
-          python-version: '3.11'
+          python-version: "3.11"
 
       - name: Download pythonbuild
         uses: actions/download-artifact@v4
@@ -131,16 +142,20 @@ jobs:
       - name: Build
         if: ${{ ! matrix.dry-run }}
         run: |
-          if [ "${{ matrix.target_triple }}" = "aarch64-apple-darwin" ]; then
+          if [ "${MATRIX_TARGET_TRIPLE}" = "aarch64-apple-darwin" ]; then
             export APPLE_SDK_PATH=/Applications/Xcode_15.2.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.2.sdk
-          elif [ "${{ matrix.target_triple }}" = "x86_64-apple-darwin" ]; then
+          elif [ "${MATRIX_TARGET_TRIPLE}" = "x86_64-apple-darwin" ]; then
             export APPLE_SDK_PATH=/Applications/Xcode_15.2.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.2.sdk
           else
-            echo "unhandled target triple: ${{ matrix.target_triple }}"
+            echo "unhandled target triple: ${MATRIX_TARGET_TRIPLE}"
             exit 1
           fi
 
-          ./build-macos.py --target-triple ${{ matrix.target_triple }} --python cpython-${{ matrix.python }} --options ${{ matrix.build_options }}
+          ./build-macos.py --target-triple ${MATRIX_TARGET_TRIPLE} --python cpython-${MATRIX_PYTHON} --options ${MATRIX_BUILD_OPTIONS}
+        env:
+          MATRIX_TARGET_TRIPLE: ${{ matrix.target_triple }}
+          MATRIX_PYTHON: ${{ matrix.python }}
+          MATRIX_BUILD_OPTIONS: ${{ matrix.build_options }}
 
       - name: Generate attestations
         uses: actions/attest-build-provenance@v2
@@ -159,9 +174,10 @@ jobs:
         if: ${{ ! matrix.dry-run }}
         uses: actions/checkout@v4
         with:
-          repository: 'phracker/MacOSX-SDKs'
+          repository: phracker/MacOSX-SDKs
           ref: master
           path: macosx-sdks
+          persist-credentials: false
 
       - name: Validate Distribution
         if: ${{ ! matrix.dry-run }}
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index a81dc2f9..be1c85e2 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -18,30 +18,36 @@ on:
 env:
   FORCE_COLOR: 1
 
-permissions:
-  contents: write
-  packages: write
-  # Permissions used for actions/attest-build-provenance
-  id-token: write
-  attestations: write
+permissions: {}
 
 jobs:
   release:
+    name: Release
     env:
       GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
     runs-on: ubuntu-latest
+
+    permissions:
+      contents: write
+      packages: write
+      # Permissions used for actions/attest-build-provenance
+      id-token: write
+      attestations: write
+
     steps:
       - uses: actions/checkout@v4
         with:
           submodules: recursive
+          persist-credentials: false
 
       - uses: extractions/setup-just@dd310ad5a97d8e7b41793f8ef055398d51ad4de6 # v2
 
       # Perform a release in dry-run mode.
-      - run: just release-dry-run ${{ secrets.GITHUB_TOKEN }} ${{ github.event.inputs.sha }} ${{ github.event.inputs.tag }}
+      - run: just release-dry-run ${GH_TOKEN} ${GITHUB_EVENT_INPUTS_SHA} ${GITHUB_EVENT_INPUTS_TAG}
         if: ${{ github.event.inputs.dry-run == 'true' }}
-
-      # Set our identity for git operations (on the latest-release branch).
+        env:
+          GITHUB_EVENT_INPUTS_SHA: ${{ github.event.inputs.sha }}
+          GITHUB_EVENT_INPUTS_TAG: ${{ github.event.inputs.tag }}
       - name: Configure Git identity
         if: ${{ github.event.inputs.dry-run == 'false' }}
         run: |
@@ -51,28 +57,36 @@ jobs:
       # Fetch the commit so that it exists locally.
       - name: Fetch commit
         if: ${{ github.event.inputs.dry-run == 'false' }}
-        run: git fetch origin ${{ github.event.inputs.sha }}
+        run: git fetch origin ${GITHUB_EVENT_INPUTS_SHA}
+        env:
+          GITHUB_EVENT_INPUTS_SHA: ${{ github.event.inputs.sha }}
 
       # Associate the commit with the tag.
       - name: Create tag
         if: ${{ github.event.inputs.dry-run == 'false' }}
-        run: git tag ${{ github.event.inputs.tag }} ${{ github.event.inputs.sha }}
-
-      # Push the tag to GitHub.
+        run: git tag ${GITHUB_EVENT_INPUTS_TAG} ${GITHUB_EVENT_INPUTS_SHA}
+        env:
+          GITHUB_EVENT_INPUTS_TAG: ${{ github.event.inputs.tag }}
+          GITHUB_EVENT_INPUTS_SHA: ${{ github.event.inputs.sha }}
       - name: Push tag
         if: ${{ github.event.inputs.dry-run == 'false' }}
-        run: git push origin ${{ github.event.inputs.tag }}
+        run: git push origin ${GITHUB_EVENT_INPUTS_TAG}
+        env:
+          GITHUB_EVENT_INPUTS_TAG: ${{ github.event.inputs.tag }}
 
       # Create a GitHub release.
       - name: Create GitHub Release
         if: ${{ github.event.inputs.dry-run == 'false' }}
-        run: just release-create ${{ github.event.inputs.tag }}
+        run: just release-create ${GITHUB_EVENT_INPUTS_TAG}
+        env:
+          GITHUB_EVENT_INPUTS_TAG: ${{ github.event.inputs.tag }}
 
       # Uploading the relevant artifact to the GitHub release.
-      - run: just release-run ${{ secrets.GITHUB_TOKEN }} ${{ github.event.inputs.sha }} ${{ github.event.inputs.tag }}
+      - run: just release-run ${GH_TOKEN} ${GITHUB_EVENT_INPUTS_SHA} ${GITHUB_EVENT_INPUTS_TAG}
         if: ${{ github.event.inputs.dry-run == 'false' }}
-
-      # We filter by *.tar.@(zst|gz) since actions/attest-build-provenance only supports up to 1024 subjects
+        env:
+          GITHUB_EVENT_INPUTS_SHA: ${{ github.event.inputs.sha }}
+          GITHUB_EVENT_INPUTS_TAG: ${{ github.event.inputs.tag }}
       - name: Generate attestations
         uses: actions/attest-build-provenance@v2
         if: ${{ github.event.inputs.dry-run == 'false' }}
diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml
index 165ff261..e1fea413 100644
--- a/.github/workflows/windows.yml
+++ b/.github/workflows/windows.yml
@@ -12,6 +12,8 @@ concurrency:
 env:
   FORCE_COLOR: 1
 
+permissions: {}
+
 jobs:
   crate-build:
     needs:
@@ -23,6 +25,8 @@ jobs:
     name: crate / ${{ matrix.arch }}
     steps:
       - uses: actions/checkout@v4
+        with:
+          persist-credentials: false
 
       - name: Emit rustc version
         run: |
@@ -47,6 +51,7 @@ jobs:
           path: target/release/pythonbuild.exe
 
   generate-matrix:
+    name: Generate build matrix
     runs-on: ubuntu-latest
     outputs:
       matrix: ${{ steps.set-matrix.outputs.matrix }}
@@ -55,16 +60,19 @@ jobs:
     steps:
       - uses: actions/checkout@v4
         with:
-          fetch-depth: 0  # fetch history for subsequent `git diff`
+          fetch-depth: 0
+          persist-credentials: false
 
       - name: Set up Python
         uses: astral-sh/setup-uv@v4
 
       - name: Get pull request labels
         id: get-labels
+        env:
+          PULL_REQUEST_LABELS: ${{ toJson(github.event.pull_request.labels.*.name) }}
         run: |
           # Convert GitHub labels array to comma-separated string
-          LABELS=$(echo '${{ toJson(github.event.pull_request.labels.*.name) }}' | jq -r 'join(",")')
+          LABELS=$(echo "${PULL_REQUEST_LABELS}" | jq -r 'join(",")')
           echo "labels=$LABELS" >> $GITHUB_OUTPUT
 
       - name: Check if the `pythonbuild` crate changed
@@ -82,12 +90,12 @@ jobs:
       - name: Generate build matrix
         id: set-matrix
         run: |
-          uv run ci-matrix.py --platform windows --labels '${{ steps.get-labels.outputs.labels }}' ${{ (steps.check-pythonbuild.outputs.changed == 'true' || github.ref == 'refs/heads/main') && '--force-crate-build' || '' }} > matrix.json
-          
+          uv run ci-matrix.py --platform windows --labels '${STEPS_GET_LABELS_OUTPUTS_LABELS}' ${{ (steps.check-pythonbuild.outputs.changed == 'true' || github.ref == 'refs/heads/main') && '--force-crate-build' || '' }} > matrix.json
+
           # Extract python-build matrix
           echo "matrix=$(jq -c '."python-build"' matrix.json)" >> $GITHUB_OUTPUT
           echo "crate-build-matrix=$(jq -c '."crate-build"' matrix.json)" >> $GITHUB_OUTPUT
-          
+
           # Display the matrix for debugging too
           cat matrix.json | jq
 
@@ -98,6 +106,8 @@ jobs:
             # Build matrix is empty
             echo "any_builds=false" >> $GITHUB_OUTPUT
           fi
+        env:
+          STEPS_GET_LABELS_OUTPUTS_LABELS: ${{ steps.get-labels.outputs.labels }}
 
   build:
     timeout-minutes: 60
@@ -117,6 +127,7 @@ jobs:
       - uses: actions/checkout@v4
         with:
           fetch-depth: 0
+          persist-credentials: false
 
       - name: Install Cygwin Environment
         uses: cygwin/cygwin-install-action@49f298a7ebb00d4b3ddf58000c3e78eff5fbd6b9 # v2
@@ -126,7 +137,7 @@ jobs:
       - name: Install Python
         uses: actions/setup-python@v5
         with:
-          python-version: '3.12'
+          python-version: "3.12"
 
       - name: Download pythonbuild Executable
         uses: actions/download-artifact@v4
@@ -143,8 +154,12 @@ jobs:
         if: ${{ ! matrix.dry-run }}
         shell: cmd
         run: |
-          call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\${{ matrix.vcvars }}"
-          py.exe -3.12 build-windows.py --python cpython-${{ matrix.python }} --sh c:\cygwin\bin\sh.exe --options ${{ matrix.build_options }}
+          call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\%MATRIX_VCVARS%"
+          py.exe -3.12 build-windows.py --python cpython-%MATRIX_PYTHON% --sh c:\cygwin\bin\sh.exe --options %MATRIX_BUILD_OPTIONS%
+        env:
+          MATRIX_VCVARS: ${{ matrix.vcvars }}
+          MATRIX_PYTHON: ${{ matrix.python }}
+          MATRIX_BUILD_OPTIONS: ${{ matrix.build_options }}
 
       - name: Generate attestations
         uses: actions/attest-build-provenance@v2
diff --git a/.github/workflows/zizmor.yml b/.github/workflows/zizmor.yml
new file mode 100644
index 00000000..a60e2865
--- /dev/null
+++ b/.github/workflows/zizmor.yml
@@ -0,0 +1,24 @@
+name: zizmor
+
+on:
+  push:
+    branches: ["main"]
+  pull_request:
+    branches: ["**"]
+
+permissions: {}
+
+jobs:
+  zizmor:
+    name: Run zizmor
+    runs-on: ubuntu-latest
+    permissions:
+      security-events: write
+    steps:
+      - name: Checkout repository
+        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+        with:
+          persist-credentials: false
+
+      - name: Run zizmor
+        uses: zizmorcore/zizmor-action@f52a838cfabf134edcbaa7c8b3677dde20045018 # v0.1.1
diff --git a/.github/zizmor.yml b/.github/zizmor.yml
new file mode 100644
index 00000000..c3db9686
--- /dev/null
+++ b/.github/zizmor.yml
@@ -0,0 +1,7 @@
+rules:
+  unpinned-uses:
+    config:
+      policies:
+        actions/*: ref-pin
+        astral-sh/*: ref-pin
+        "*": hash-pin

From 55f3d50aee9743ea48afaa18d43ff7a96af7b056 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 4 Aug 2025 16:19:36 -0500
Subject: [PATCH 151/157] Bump the actions group in /.github/workflows with 3
 updates (#718)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Bumps the actions group in /.github/workflows with 3 updates:
[docker/setup-buildx-action](https://github.com/docker/setup-buildx-action),
[extractions/setup-just](https://github.com/extractions/setup-just) and
[cygwin/cygwin-install-action](https://github.com/cygwin/cygwin-install-action).

Updates `docker/setup-buildx-action` from 3.10.0 to 3.11.1
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/docker/setup-buildx-action/releases">docker/setup-buildx-action's
releases</a>.</em></p>
<blockquote>
<h2>v3.11.1</h2>
<ul>
<li>Fix <code>keep-state</code> not being respected by <a
href="https://github.com/crazy-max"><code>@​crazy-max</code></a> in <a
href="https://redirect.github.com/docker/setup-buildx-action/pull/429">docker/setup-buildx-action#429</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/docker/setup-buildx-action/compare/v3.11.0...v3.11.1">https://github.com/docker/setup-buildx-action/compare/v3.11.0...v3.11.1</a></p>
<h2>v3.11.0</h2>
<ul>
<li>Keep BuildKit state support by <a
href="https://github.com/crazy-max"><code>@​crazy-max</code></a> in <a
href="https://redirect.github.com/docker/setup-buildx-action/pull/427">docker/setup-buildx-action#427</a></li>
<li>Remove aliases created when installing by default by <a
href="https://github.com/hashhar"><code>@​hashhar</code></a> in <a
href="https://redirect.github.com/docker/setup-buildx-action/pull/139">docker/setup-buildx-action#139</a></li>
<li>Bump <code>@​docker/actions-toolkit</code> from 0.56.0 to 0.62.1 in
<a
href="https://redirect.github.com/docker/setup-buildx-action/pull/422">docker/setup-buildx-action#422</a>
<a
href="https://redirect.github.com/docker/setup-buildx-action/pull/425">docker/setup-buildx-action#425</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/docker/setup-buildx-action/compare/v3.10.0...v3.11.0">https://github.com/docker/setup-buildx-action/compare/v3.10.0...v3.11.0</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/docker/setup-buildx-action/commit/e468171a9de216ec08956ac3ada2f0791b6bd435"><code>e468171</code></a>
Merge pull request <a
href="https://redirect.github.com/docker/setup-buildx-action/issues/429">#429</a>
from crazy-max/fix-keep-state</li>
<li><a
href="https://github.com/docker/setup-buildx-action/commit/a3e7502fd02828f4a26a8294ad2621a6c2204952"><code>a3e7502</code></a>
chore: update generated content</li>
<li><a
href="https://github.com/docker/setup-buildx-action/commit/b145473295476dbef957d01d109fe7810b511c95"><code>b145473</code></a>
fix keep-state not being respected</li>
<li><a
href="https://github.com/docker/setup-buildx-action/commit/18ce135bb5112fa8ce4ed6c17ab05699d7f3a5e0"><code>18ce135</code></a>
Merge pull request <a
href="https://redirect.github.com/docker/setup-buildx-action/issues/425">#425</a>
from docker/dependabot/npm_and_yarn/docker/actions-to...</li>
<li><a
href="https://github.com/docker/setup-buildx-action/commit/0e198e93af3b40a76583e851660b876e62b3a155"><code>0e198e9</code></a>
chore: update generated content</li>
<li><a
href="https://github.com/docker/setup-buildx-action/commit/05f3f3ac108784e8fb56815c12fbfcf2d0ed660f"><code>05f3f3a</code></a>
build(deps): bump <code>@​docker/actions-toolkit</code> from 0.61.0 to
0.62.1</li>
<li><a
href="https://github.com/docker/setup-buildx-action/commit/622913496df23a5293cfb3418e5836ee4dd28f3a"><code>6229134</code></a>
Merge pull request <a
href="https://redirect.github.com/docker/setup-buildx-action/issues/427">#427</a>
from crazy-max/keep-state</li>
<li><a
href="https://github.com/docker/setup-buildx-action/commit/c6f6a0702519e6c47b71b117b24c0c1c130fdf32"><code>c6f6a07</code></a>
chore: update generated content</li>
<li><a
href="https://github.com/docker/setup-buildx-action/commit/6c5e29d8485c56f3f8d1cb2197b657959dd6e032"><code>6c5e29d</code></a>
skip builder creation if one already exists with the same name</li>
<li><a
href="https://github.com/docker/setup-buildx-action/commit/548b2977492e10f459d0f0df8bee7ce3c5937792"><code>548b297</code></a>
ci: keep-state check</li>
<li>Additional commits viewable in <a
href="https://github.com/docker/setup-buildx-action/compare/b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2...e468171a9de216ec08956ac3ada2f0791b6bd435">compare
view</a></li>
</ul>
</details>
<br />

Updates `extractions/setup-just` from 2.0.0 to 3.0.0
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/extractions/setup-just/commit/e33e0265a09d6d736e2ee1e0eb685ef1de4669ff"><code>e33e026</code></a>
This is 3.0.0</li>
<li><a
href="https://github.com/extractions/setup-just/commit/e8fa8d355d631b0b67a34b2a41355122ee456f31"><code>e8fa8d3</code></a>
Convert to composite action (<a
href="https://redirect.github.com/extractions/setup-just/issues/19">#19</a>)</li>
<li><a
href="https://github.com/extractions/setup-just/commit/6e1de3cc407de738551abd6c0923bd5ed5608042"><code>6e1de3c</code></a>
Keep GitHub Actions up to date with GitHub's Dependabot (<a
href="https://redirect.github.com/extractions/setup-just/issues/14">#14</a>)</li>
<li><a
href="https://github.com/extractions/setup-just/commit/d91bfae12fd0bead47c99d6298d48f484e2857ff"><code>d91bfae</code></a>
doc: update example code with the latest gha version (<a
href="https://redirect.github.com/extractions/setup-just/issues/16">#16</a>)</li>
<li>See full diff in <a
href="https://github.com/extractions/setup-just/compare/dd310ad5a97d8e7b41793f8ef055398d51ad4de6...e33e0265a09d6d736e2ee1e0eb685ef1de4669ff">compare
view</a></li>
</ul>
</details>
<br />

Updates `cygwin/cygwin-install-action` from 2 to 6
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/cygwin/cygwin-install-action/releases">cygwin/cygwin-install-action's
releases</a>.</em></p>
<blockquote>
<h2>v6</h2>
<h2>What's Changed</h2>
<ul>
<li>Add warning about using SHELLOPTS to set igncr by <a
href="https://github.com/tobil4sk"><code>@​tobil4sk</code></a> in <a
href="https://redirect.github.com/cygwin/cygwin-install-action/pull/22">cygwin/cygwin-install-action#22</a></li>
<li>Add work-vol option by <a
href="https://github.com/gstrauss"><code>@​gstrauss</code></a> in <a
href="https://redirect.github.com/cygwin/cygwin-install-action/pull/27">cygwin/cygwin-install-action#27</a></li>
<li>For performance, default work-vol to D: (if it exists) by <a
href="https://github.com/gstrauss"><code>@​gstrauss</code></a> in <a
href="https://redirect.github.com/cygwin/cygwin-install-action/pull/27">cygwin/cygwin-install-action#27</a></li>
<li>Add a retry mechanism for fetching setup executable by <a
href="https://github.com/jon-turney"><code>@​jon-turney</code></a> in <a
href="https://redirect.github.com/cygwin/cygwin-install-action/pull/26">cygwin/cygwin-install-action#26</a></li>
<li>Check Authenticode signature on setup execitable by <a
href="https://github.com/jon-turney"><code>@​jon-turney</code></a></li>
<li>Give the action some outputs (e.g. so uses can find out where we
installed) by <a
href="https://github.com/jon-turney"><code>@​jon-turney</code></a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/tobil4sk"><code>@​tobil4sk</code></a>
made their first contribution in <a
href="https://redirect.github.com/cygwin/cygwin-install-action/pull/22">cygwin/cygwin-install-action#22</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/cygwin/cygwin-install-action/compare/v5...v6">https://github.com/cygwin/cygwin-install-action/compare/v5...v6</a></p>
<h2>v5</h2>
<h2>What's Changed</h2>
<ul>
<li>Drop the -g/--upgrade-also from the options used to invoke
setup</li>
<li>Use action/checkout v4 instead of v2 in tests by <a
href="https://github.com/mlocati"><code>@​mlocati</code></a> in <a
href="https://redirect.github.com/cygwin/cygwin-install-action/pull/16">cygwin/cygwin-install-action#16</a></li>
<li>Add allow-test-packages option by <a
href="https://github.com/gstrauss"><code>@​gstrauss</code></a> in <a
href="https://redirect.github.com/cygwin/cygwin-install-action/pull/12">cygwin/cygwin-install-action#12</a></li>
<li>Check hash of downloaded setup by <a
href="https://github.com/mlocati"><code>@​mlocati</code></a> in <a
href="https://redirect.github.com/cygwin/cygwin-install-action/pull/17">cygwin/cygwin-install-action#17</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/mlocati"><code>@​mlocati</code></a> made
their first contribution in <a
href="https://redirect.github.com/cygwin/cygwin-install-action/pull/16">cygwin/cygwin-install-action#16</a></li>
<li><a href="https://github.com/gstrauss"><code>@​gstrauss</code></a>
made their first contribution in <a
href="https://redirect.github.com/cygwin/cygwin-install-action/pull/12">cygwin/cygwin-install-action#12</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/cygwin/cygwin-install-action/compare/v4...v5">https://github.com/cygwin/cygwin-install-action/compare/v4...v5</a></p>
<h2>v4</h2>
<p>No release notes provided.</p>
<h2>v3</h2>
<p>No release notes provided.</p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/cygwin/cygwin-install-action/commit/f2009323764960f80959895c7bc3bb30210afe4d"><code>f200932</code></a>
Give the action some outputs</li>
<li><a
href="https://github.com/cygwin/cygwin-install-action/commit/52b4c10c3c3c152011c84c698ed112f074bec132"><code>52b4c10</code></a>
Check Authenticode signature on setup</li>
<li><a
href="https://github.com/cygwin/cygwin-install-action/commit/e67b1f4a359a621ee71cc8f0a96d3b8be1c9a218"><code>e67b1f4</code></a>
Factor out download retry as a function, to use on sha512.sum file
also</li>
<li><a
href="https://github.com/cygwin/cygwin-install-action/commit/8381d6dafbfc33ae8c47cda1c6b2961e60982167"><code>8381d6d</code></a>
Add a retry mechanism for fetching setup executable</li>
<li><a
href="https://github.com/cygwin/cygwin-install-action/commit/354b33742a1a418d28d424f6e93c20b97566e9ee"><code>354b337</code></a>
Consistently use throw to terminate with an error</li>
<li><a
href="https://github.com/cygwin/cygwin-install-action/commit/f623c572783fc7145a11ba60d5003edb26470f01"><code>f623c57</code></a>
Add a test of work-vol option</li>
<li><a
href="https://github.com/cygwin/cygwin-install-action/commit/d3a7464b92425a95438e794ec49927871dde78d2"><code>d3a7464</code></a>
Use D: drive as default work-vol</li>
<li><a
href="https://github.com/cygwin/cygwin-install-action/commit/1c9eb7ccd83440c2e551604eb2ce58194c127cff"><code>1c9eb7c</code></a>
Add work-vol option to target different setup volume</li>
<li><a
href="https://github.com/cygwin/cygwin-install-action/commit/d6a07e1ea12d51fdcc036ad67f1bc8376f2056b3"><code>d6a07e1</code></a>
Tweak wording about SHELLOPTS and line-endings</li>
<li><a
href="https://github.com/cygwin/cygwin-install-action/commit/63d1e759cfd6f52de03d886de9443cf4958a2ce4"><code>63d1e75</code></a>
Add warning about using SHELLOPTS to set igncr</li>
<li>Additional commits viewable in <a
href="https://github.com/cygwin/cygwin-install-action/compare/49f298a7ebb00d4b3ddf58000c3e78eff5fbd6b9...f2009323764960f80959895c7bc3bb30210afe4d">compare
view</a></li>
</ul>
</details>
<br />


Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
 .github/workflows/linux.yml   | 2 +-
 .github/workflows/release.yml | 2 +-
 .github/workflows/windows.yml | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml
index 2ed390b7..2d8c8a15 100644
--- a/.github/workflows/linux.yml
+++ b/.github/workflows/linux.yml
@@ -77,7 +77,7 @@ jobs:
           python-version: "3.11"
 
       - name: Set up Docker Buildx
-        uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3
+        uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3
 
       - name: Login to GitHub Container Registry
         uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index be1c85e2..f4036a02 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -40,7 +40,7 @@ jobs:
           submodules: recursive
           persist-credentials: false
 
-      - uses: extractions/setup-just@dd310ad5a97d8e7b41793f8ef055398d51ad4de6 # v2
+      - uses: extractions/setup-just@e33e0265a09d6d736e2ee1e0eb685ef1de4669ff # v2
 
       # Perform a release in dry-run mode.
       - run: just release-dry-run ${GH_TOKEN} ${GITHUB_EVENT_INPUTS_SHA} ${GITHUB_EVENT_INPUTS_TAG}
diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml
index e1fea413..14840f46 100644
--- a/.github/workflows/windows.yml
+++ b/.github/workflows/windows.yml
@@ -130,7 +130,7 @@ jobs:
           persist-credentials: false
 
       - name: Install Cygwin Environment
-        uses: cygwin/cygwin-install-action@49f298a7ebb00d4b3ddf58000c3e78eff5fbd6b9 # v2
+        uses: cygwin/cygwin-install-action@f2009323764960f80959895c7bc3bb30210afe4d # v6
         with:
           packages: autoconf automake libtool
 

From b670cd8b835d206c521a70863080762b98455b09 Mon Sep 17 00:00:00 2001
From: Nathan Cain <13713501+nathanscain@users.noreply.github.com>
Date: Wed, 6 Aug 2025 16:04:21 -0500
Subject: [PATCH 152/157] apply disable-multiarch patch to all musl builds
 (#725)

Potential solve for #724
---
 cpython-unix/build-cpython.sh | 7 +------
 1 file changed, 1 insertion(+), 6 deletions(-)

diff --git a/cpython-unix/build-cpython.sh b/cpython-unix/build-cpython.sh
index cc93f0ad..3c252a5d 100755
--- a/cpython-unix/build-cpython.sh
+++ b/cpython-unix/build-cpython.sh
@@ -116,17 +116,12 @@ fi
 # Clang 13 actually prints something with --print-multiarch, confusing CPython's
 # configure. This is reported as https://bugs.python.org/issue45405. We nerf the
 # check since we know what we're doing.
-if [ "${CC}" = "clang" ]; then
+if [[ "${CC}" = "clang" || "${CC}" = "musl-clang" ]]; then
     if [ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_13}" ]; then
         patch -p1 -i ${ROOT}/patch-disable-multiarch-13.patch
     else
         patch -p1 -i ${ROOT}/patch-disable-multiarch.patch
     fi
-elif [ "${CC}" = "musl-clang" ]; then
-  # Similarly, this is a problem for musl Clang on Python 3.13+
-  if [ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_13}" ]; then
-    patch -p1 -i ${ROOT}/patch-disable-multiarch-13.patch
-  fi
 fi
 
 # Python 3.11 supports using a provided Python to use during bootstrapping

From be22cba141e263d56d40f78c7fb910ef8916d86b Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Wed, 6 Aug 2025 17:34:36 -0500
Subject: [PATCH 153/157] Bump CPython 3.13 version to 3.13.6 (#726)

---
 cpython-unix/build-cpython.sh                 |   7 -
 .../patch-uuid-getnode-stable-3.13.patch      | 708 ------------------
 pythonbuild/downloads.py                      |   8 +-
 3 files changed, 4 insertions(+), 719 deletions(-)
 delete mode 100644 cpython-unix/patch-uuid-getnode-stable-3.13.patch

diff --git a/cpython-unix/build-cpython.sh b/cpython-unix/build-cpython.sh
index 3c252a5d..04dab671 100755
--- a/cpython-unix/build-cpython.sh
+++ b/cpython-unix/build-cpython.sh
@@ -76,13 +76,6 @@ if [ -n "${CROSS_COMPILING}" ]; then
     fi
 fi
 
-# `uuid.getnode()` is not stable on our libuuid, CPython should fallback to another method
-# Cherry-pick https://github.com/python/cpython/pull/134704 until it is released
-# We could backport this to more versions too, it won't be done by the upstream
-if [[ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_13}" && -n "${PYTHON_MEETS_MAXIMUM_VERSION_3_13}" ]]; then
-    patch -p1 -i ${ROOT}/patch-uuid-getnode-stable-3.13.patch
-fi
-
 # This patch is slightly different on Python 3.10+.
 if [ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_10}" ]; then
     patch -p1 -i ${ROOT}/patch-xopen-source-ios.patch
diff --git a/cpython-unix/patch-uuid-getnode-stable-3.13.patch b/cpython-unix/patch-uuid-getnode-stable-3.13.patch
deleted file mode 100644
index 11bdf83a..00000000
--- a/cpython-unix/patch-uuid-getnode-stable-3.13.patch
+++ /dev/null
@@ -1,708 +0,0 @@
-diff --git a/Lib/test/test_uuid.py b/Lib/test/test_uuid.py
-index e7e44c6413c2e2..ce396aa942b6ed 100755
---- a/Lib/test/test_uuid.py
-+++ b/Lib/test/test_uuid.py
-@@ -1,6 +1,7 @@
- import unittest
- from test import support
- from test.support import import_helper
-+from test.support.script_helper import assert_python_ok
- import builtins
- import contextlib
- import copy
-@@ -773,10 +774,37 @@ def test_cli_uuid5_ouputted_with_valid_namespace_and_name(self):
- class TestUUIDWithoutExtModule(BaseTestUUID, unittest.TestCase):
-     uuid = py_uuid
- 
-+
- @unittest.skipUnless(c_uuid, 'requires the C _uuid module')
- class TestUUIDWithExtModule(BaseTestUUID, unittest.TestCase):
-     uuid = c_uuid
- 
-+    def check_has_stable_libuuid_extractable_node(self):
-+        if not self.uuid._has_stable_extractable_node:
-+            self.skipTest("libuuid cannot deduce MAC address")
-+
-+    @unittest.skipUnless(os.name == 'posix', 'POSIX only')
-+    def test_unix_getnode_from_libuuid(self):
-+        self.check_has_stable_libuuid_extractable_node()
-+        script = 'import uuid; print(uuid._unix_getnode())'
-+        _, n_a, _ = assert_python_ok('-c', script)
-+        _, n_b, _ = assert_python_ok('-c', script)
-+        n_a, n_b = n_a.decode().strip(), n_b.decode().strip()
-+        self.assertTrue(n_a.isdigit())
-+        self.assertTrue(n_b.isdigit())
-+        self.assertEqual(n_a, n_b)
-+
-+    @unittest.skipUnless(os.name == 'nt', 'Windows only')
-+    def test_windows_getnode_from_libuuid(self):
-+        self.check_has_stable_libuuid_extractable_node()
-+        script = 'import uuid; print(uuid._windll_getnode())'
-+        _, n_a, _ = assert_python_ok('-c', script)
-+        _, n_b, _ = assert_python_ok('-c', script)
-+        n_a, n_b = n_a.decode().strip(), n_b.decode().strip()
-+        self.assertTrue(n_a.isdigit())
-+        self.assertTrue(n_b.isdigit())
-+        self.assertEqual(n_a, n_b)
-+
- 
- class BaseTestInternals:
-     _uuid = py_uuid
-diff --git a/Lib/uuid.py b/Lib/uuid.py
-index c286eac38e1ef4..6ab1658cc5249a 100644
---- a/Lib/uuid.py
-+++ b/Lib/uuid.py
-@@ -572,22 +572,24 @@ def _netstat_getnode():
- try:
-     import _uuid
-     _generate_time_safe = getattr(_uuid, "generate_time_safe", None)
-+    _has_stable_extractable_node = getattr(_uuid, "has_stable_extractable_node", False)
-     _UuidCreate = getattr(_uuid, "UuidCreate", None)
- except ImportError:
-     _uuid = None
-     _generate_time_safe = None
-+    _has_stable_extractable_node = False
-     _UuidCreate = None
- 
- 
- def _unix_getnode():
-     """Get the hardware address on Unix using the _uuid extension module."""
--    if _generate_time_safe:
-+    if _generate_time_safe and _has_stable_extractable_node:
-         uuid_time, _ = _generate_time_safe()
-         return UUID(bytes=uuid_time).node
- 
- def _windll_getnode():
-     """Get the hardware address on Windows using the _uuid extension module."""
--    if _UuidCreate:
-+    if _UuidCreate and _has_stable_extractable_node:
-         uuid_bytes = _UuidCreate()
-         return UUID(bytes_le=uuid_bytes).node
- 
-diff --git a/Modules/_uuidmodule.c b/Modules/_uuidmodule.c
-index c5e78b1510b5e3..c31a7e8fea5608 100644
---- a/Modules/_uuidmodule.c
-+++ b/Modules/_uuidmodule.c
-@@ -78,23 +78,47 @@ py_UuidCreate(PyObject *Py_UNUSED(context),
-     return NULL;
- }
- 
-+static int
-+py_windows_has_stable_node(void)
-+{
-+    UUID uuid;
-+    RPC_STATUS res;
-+    Py_BEGIN_ALLOW_THREADS
-+    res = UuidCreateSequential(&uuid);
-+    Py_END_ALLOW_THREADS
-+    return res == RPC_S_OK;
-+}
- #endif /* MS_WINDOWS */
- 
- 
- static int
--uuid_exec(PyObject *module) {
-+uuid_exec(PyObject *module)
-+{
-+#define ADD_INT(NAME, VALUE)                                        \
-+    do {                                                            \
-+        if (PyModule_AddIntConstant(module, (NAME), (VALUE)) < 0) { \
-+           return -1;                                               \
-+        }                                                           \
-+    } while (0)
-+
-     assert(sizeof(uuid_t) == 16);
- #if defined(MS_WINDOWS)
--    int has_uuid_generate_time_safe = 0;
-+    ADD_INT("has_uuid_generate_time_safe", 0);
- #elif defined(HAVE_UUID_GENERATE_TIME_SAFE)
--    int has_uuid_generate_time_safe = 1;
-+    ADD_INT("has_uuid_generate_time_safe", 1);
- #else
--    int has_uuid_generate_time_safe = 0;
-+    ADD_INT("has_uuid_generate_time_safe", 0);
- #endif
--    if (PyModule_AddIntConstant(module, "has_uuid_generate_time_safe",
--                                has_uuid_generate_time_safe) < 0) {
--        return -1;
--    }
-+
-+#if defined(MS_WINDOWS)
-+    ADD_INT("has_stable_extractable_node", py_windows_has_stable_node());
-+#elif defined(HAVE_UUID_GENERATE_TIME_SAFE_STABLE_MAC)
-+    ADD_INT("has_stable_extractable_node", 1);
-+#else
-+    ADD_INT("has_stable_extractable_node", 0);
-+#endif
-+
-+#undef ADD_INT
-     return 0;
- }
- 
-diff --git a/configure b/configure
-index 1cd1f690f7b9c1..cc976aafc09b34 100755
---- a/configure
-+++ b/configure
-@@ -13381,6 +13381,7 @@ fi
- 
- 
- 
-+
- have_uuid=missing
- 
-        for ac_header in uuid.h
-@@ -13390,6 +13391,7 @@ if test "x$ac_cv_header_uuid_h" = xyes
- then :
-   printf "%s\n" "#define HAVE_UUID_H 1" >>confdefs.h
- 
-+
-   for ac_func in uuid_create uuid_enc_be
- do :
-   as_ac_var=`printf "%s\n" "ac_cv_func_$ac_func" | $as_tr_sh`
-@@ -13399,7 +13401,9 @@ then :
-   cat >>confdefs.h <<_ACEOF
- #define `printf "%s\n" "HAVE_$ac_func" | $as_tr_cpp` 1
- _ACEOF
-- have_uuid=yes
-+
-+    have_uuid=yes
-+    ac_cv_have_uuid_h=yes
-     LIBUUID_CFLAGS=${LIBUUID_CFLAGS-""}
-     LIBUUID_LIBS=${LIBUUID_LIBS-""}
- 
-@@ -13489,6 +13493,7 @@ if test "x$ac_cv_header_uuid_uuid_h" = xyes
- then :
-   printf "%s\n" "#define HAVE_UUID_UUID_H 1" >>confdefs.h
- 
-+          ac_cv_have_uuid_uuid_h=yes
-           py_check_lib_save_LIBS=$LIBS
- { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for uuid_generate_time in -luuid" >&5
- printf %s "checking for uuid_generate_time in -luuid... " >&6; }
-@@ -13570,8 +13575,9 @@ fi
- printf "%s\n" "$ac_cv_lib_uuid_uuid_generate_time_safe" >&6; }
- if test "x$ac_cv_lib_uuid_uuid_generate_time_safe" = xyes
- then :
--  have_uuid=yes
--            printf "%s\n" "#define HAVE_UUID_GENERATE_TIME_SAFE 1" >>confdefs.h
-+
-+            have_uuid=yes
-+            ac_cv_have_uuid_generate_time_safe=yes
- 
- fi
- 
-@@ -13615,6 +13621,7 @@ if test "x$ac_cv_header_uuid_uuid_h" = xyes
- then :
-   printf "%s\n" "#define HAVE_UUID_UUID_H 1" >>confdefs.h
- 
-+          ac_cv_have_uuid_uuid_h=yes
-           py_check_lib_save_LIBS=$LIBS
- { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for uuid_generate_time in -luuid" >&5
- printf %s "checking for uuid_generate_time in -luuid... " >&6; }
-@@ -13696,8 +13703,9 @@ fi
- printf "%s\n" "$ac_cv_lib_uuid_uuid_generate_time_safe" >&6; }
- if test "x$ac_cv_lib_uuid_uuid_generate_time_safe" = xyes
- then :
--  have_uuid=yes
--            printf "%s\n" "#define HAVE_UUID_GENERATE_TIME_SAFE 1" >>confdefs.h
-+
-+            have_uuid=yes
-+            ac_cv_have_uuid_generate_time_safe=yes
- 
- fi
- 
-@@ -13727,11 +13735,25 @@ else
- 	LIBUUID_LIBS=$pkg_cv_LIBUUID_LIBS
-         { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
- printf "%s\n" "yes" >&6; }
-+<<<<<<< HEAD
- 	            have_uuid=yes
-       printf "%s\n" "#define HAVE_UUID_H 1" >>confdefs.h
- 
-       printf "%s\n" "#define HAVE_UUID_GENERATE_TIME_SAFE 1" >>confdefs.h
- 
-+=======
-+                    have_uuid=yes
-+      ac_cv_have_uuid_generate_time_safe=yes
-+      # The uuid.h file to include may be <uuid.h> *or* <uuid/uuid.h>.
-+      # Since pkg-config --cflags uuid may return -I/usr/include/uuid,
-+      # it's possible to write '#include <uuid.h>' in _uuidmodule.c,
-+      # assuming that the compiler flags are properly updated.
-+      #
-+      # Ideally, we should have defined HAVE_UUID_H if and only if
-+      # #include <uuid.h> can be written, *without* assuming extra
-+      # include path.
-+      ac_cv_have_uuid_h=yes
-+>>>>>>> 3bffada4672 (gh-132710: only use stable `_uuid.generate_time_safe()` to deduce MAC address (#132901))
- 
- fi
- 
-@@ -13752,6 +13774,7 @@ if test "x$ac_cv_func_uuid_generate_time" = xyes
- then :
- 
-       have_uuid=yes
-+      ac_cv_have_uuid_uuid_h=yes
-       LIBUUID_CFLAGS=${LIBUUID_CFLAGS-""}
-       LIBUUID_LIBS=${LIBUUID_LIBS-""}
- 
-@@ -13764,11 +13787,198 @@ done
- 
- fi
- 
-+<<<<<<< HEAD
-+=======
-+if test "x$ac_cv_have_uuid_h" = xyes
-+then :
-+  printf "%s\n" "#define HAVE_UUID_H 1" >>confdefs.h
-+
-+fi
-+if test "x$ac_cv_have_uuid_uuid_h" = xyes
-+then :
-+  printf "%s\n" "#define HAVE_UUID_UUID_H 1" >>confdefs.h
-+
-+fi
-+if test "x$ac_cv_have_uuid_generate_time_safe" = xyes
-+then :
-+
-+  printf "%s\n" "#define HAVE_UUID_GENERATE_TIME_SAFE 1" >>confdefs.h
-+
-+
-+fi
-+
-+# gh-124228: While the libuuid library is available on NetBSD, it supports only UUID version 4.
-+# This restriction inhibits the proper generation of time-based UUIDs.
-+if test "$ac_sys_system" = "NetBSD"; then
-+  have_uuid=missing
-+  printf "%s\n" "#define HAVE_UUID_H 0" >>confdefs.h
-+
-+fi
-+
-+>>>>>>> 3bffada4672 (gh-132710: only use stable `_uuid.generate_time_safe()` to deduce MAC address (#132901))
- if test "x$have_uuid" = xmissing
- then :
-   have_uuid=no
- fi
- 
-+# gh-132710: The UUID node is fetched by using libuuid when possible
-+# and cached. While the node is constant within the same process,
-+# different interpreters may have different values as libuuid may
-+# randomize the node value if the latter cannot be deduced.
-+#
-+# Consumers may define HAVE_UUID_GENERATE_TIME_SAFE_STABLE_MAC
-+# to indicate that libuuid is unstable and should not be relied
-+# upon to deduce the MAC address.
-+
-+
-+if test "$have_uuid" = "yes" -a "$HAVE_UUID_GENERATE_TIME_SAFE" = "1"
-+then
-+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if uuid_generate_time_safe() node value is stable" >&5
-+printf %s "checking if uuid_generate_time_safe() node value is stable... " >&6; }
-+  save_CFLAGS=$CFLAGS
-+save_CPPFLAGS=$CPPFLAGS
-+save_LDFLAGS=$LDFLAGS
-+save_LIBS=$LIBS
-+
-+
-+  # Be sure to add the extra include path if we used pkg-config
-+  # as HAVE_UUID_H may be set even though <uuid.h> is only reachable
-+  # by adding extra -I flags.
-+  #
-+  # If the following script does not compile, we simply assume that
-+  # libuuid is missing.
-+  CFLAGS="$CFLAGS $LIBUUID_CFLAGS"
-+  LIBS="$LIBS $LIBUUID_LIBS"
-+  if test "$cross_compiling" = yes
-+then :
-+
-+
-+else case e in #(
-+  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-+/* end confdefs.h.  */
-+
-+    #include <inttypes.h>   // PRIu64
-+    #include <stdint.h>     // uint64_t
-+    #include <stdio.h>      // fopen(), fclose()
-+
-+    #ifdef HAVE_UUID_H
-+    #include <uuid.h>
-+    #else
-+    #include <uuid/uuid.h>
-+    #endif
-+
-+    #define ERR 1
-+    int main(void) {
-+        uuid_t uuid;  // unsigned char[16]
-+        (void)uuid_generate_time_safe(uuid);
-+        uint64_t node = 0;
-+        for (size_t i = 0; i < 6; i++) {
-+            node |= (uint64_t)uuid[15 - i] << (8 * i);
-+        }
-+        FILE *fp = fopen("conftest.out", "w");
-+        if (fp == NULL) {
-+            return ERR;
-+        }
-+        int rc = fprintf(fp, "%" PRIu64 "\n", node) >= 0;
-+        rc |= fclose(fp);
-+        return rc == 0 ? 0 : ERR;
-+    }
-+_ACEOF
-+if ac_fn_c_try_run "$LINENO"
-+then :
-+
-+      py_cv_uuid_node1=`cat conftest.out`
-+
-+fi
-+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
-+  conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
-+esac
-+fi
-+
-+CFLAGS=$save_CFLAGS
-+CPPFLAGS=$save_CPPFLAGS
-+LDFLAGS=$save_LDFLAGS
-+LIBS=$save_LIBS
-+
-+
-+  save_CFLAGS=$CFLAGS
-+save_CPPFLAGS=$CPPFLAGS
-+save_LDFLAGS=$LDFLAGS
-+save_LIBS=$LIBS
-+
-+
-+  # Be sure to add the extra include path if we used pkg-config
-+  # as HAVE_UUID_H may be set even though <uuid.h> is only reachable
-+  # by adding extra -I flags.
-+  #
-+  # If the following script does not compile, we simply assume that
-+  # libuuid is missing.
-+  CFLAGS="$CFLAGS $LIBUUID_CFLAGS"
-+  LIBS="$LIBS $LIBUUID_LIBS"
-+  if test "$cross_compiling" = yes
-+then :
-+
-+
-+else case e in #(
-+  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-+/* end confdefs.h.  */
-+
-+    #include <inttypes.h>   // PRIu64
-+    #include <stdint.h>     // uint64_t
-+    #include <stdio.h>      // fopen(), fclose()
-+
-+    #ifdef HAVE_UUID_H
-+    #include <uuid.h>
-+    #else
-+    #include <uuid/uuid.h>
-+    #endif
-+
-+    #define ERR 1
-+    int main(void) {
-+        uuid_t uuid;  // unsigned char[16]
-+        (void)uuid_generate_time_safe(uuid);
-+        uint64_t node = 0;
-+        for (size_t i = 0; i < 6; i++) {
-+            node |= (uint64_t)uuid[15 - i] << (8 * i);
-+        }
-+        FILE *fp = fopen("conftest.out", "w");
-+        if (fp == NULL) {
-+            return ERR;
-+        }
-+        int rc = fprintf(fp, "%" PRIu64 "\n", node) >= 0;
-+        rc |= fclose(fp);
-+        return rc == 0 ? 0 : ERR;
-+    }
-+_ACEOF
-+if ac_fn_c_try_run "$LINENO"
-+then :
-+
-+      py_cv_uuid_node2=`cat conftest.out`
-+
-+fi
-+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
-+  conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
-+esac
-+fi
-+
-+CFLAGS=$save_CFLAGS
-+CPPFLAGS=$save_CPPFLAGS
-+LDFLAGS=$save_LDFLAGS
-+LIBS=$save_LIBS
-+
-+
-+  if test -n "$py_cv_uuid_node1" -a "$py_cv_uuid_node1" = "$py_cv_uuid_node2"
-+  then
-+    printf "%s\n" "#define HAVE_UUID_GENERATE_TIME_SAFE_STABLE_MAC 1" >>confdefs.h
-+
-+    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: stable" >&5
-+printf "%s\n" "stable" >&6; }
-+  else
-+    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unstable" >&5
-+printf "%s\n" "unstable" >&6; }
-+  fi
-+fi
-+
- # 'Real Time' functions on Solaris
- # posix4 on Solaris 2.6
- # pthread (first!) on Linux
-diff --git a/configure.ac b/configure.ac
-index 3fcb18922c5330..9898af7ffd5f25 100644
---- a/configure.ac
-+++ b/configure.ac
-@@ -3740,15 +3740,17 @@ dnl check for uuid dependencies
- AH_TEMPLATE([HAVE_UUID_H], [Define to 1 if you have the <uuid.h> header file.])
- AH_TEMPLATE([HAVE_UUID_UUID_H], [Define to 1 if you have the <uuid/uuid.h> header file.])
- AH_TEMPLATE([HAVE_UUID_GENERATE_TIME_SAFE], [Define if uuid_generate_time_safe() exists.])
-+AH_TEMPLATE([HAVE_UUID_GENERATE_TIME_SAFE_STABLE_MAC], [Define if uuid_generate_time_safe() is able to deduce a MAC address.])
- have_uuid=missing
- 
- dnl AIX provides support for RFC4122 (uuid) in libc.a starting with AIX 6.1
- dnl (anno 2007). FreeBSD and OpenBSD provides support in libc as well.
- dnl Little-endian FreeBSD, OpenBSD and NetBSD needs encoding into an octet
- dnl stream in big-endian byte-order
--AC_CHECK_HEADERS([uuid.h],
--  [AC_CHECK_FUNCS([uuid_create uuid_enc_be],
--    [have_uuid=yes
-+AC_CHECK_HEADERS([uuid.h], [
-+  AC_CHECK_FUNCS([uuid_create uuid_enc_be], [
-+    have_uuid=yes
-+    ac_cv_have_uuid_h=yes
-     LIBUUID_CFLAGS=${LIBUUID_CFLAGS-""}
-     LIBUUID_LIBS=${LIBUUID_LIBS-""}
-   ])
-@@ -3758,19 +3760,29 @@ AS_VAR_IF([have_uuid], [missing], [
-   PKG_CHECK_MODULES(
-     [LIBUUID], [uuid >= 2.20],
-       [dnl linux-util's libuuid has uuid_generate_time_safe() since v2.20 (2011)
--      dnl and provides <uuid.h>.
-+      dnl and provides <uuid.h> assuming specific include paths are given
-       have_uuid=yes
--      AC_DEFINE([HAVE_UUID_H], [1])
--      AC_DEFINE([HAVE_UUID_GENERATE_TIME_SAFE], [1])
-+      ac_cv_have_uuid_generate_time_safe=yes
-+      # The uuid.h file to include may be <uuid.h> *or* <uuid/uuid.h>.
-+      # Since pkg-config --cflags uuid may return -I/usr/include/uuid,
-+      # it's possible to write '#include <uuid.h>' in _uuidmodule.c,
-+      # assuming that the compiler flags are properly updated.
-+      #
-+      # Ideally, we should have defined HAVE_UUID_H if and only if
-+      # #include <uuid.h> can be written, *without* assuming extra
-+      # include path.
-+      ac_cv_have_uuid_h=yes
-     ], [
-       WITH_SAVE_ENV([
-         CPPFLAGS="$CPPFLAGS $LIBUUID_CFLAGS"
-         LIBS="$LIBS $LIBUUID_LIBS"
-         AC_CHECK_HEADERS([uuid/uuid.h], [
-+          ac_cv_have_uuid_uuid_h=yes
-           PY_CHECK_LIB([uuid], [uuid_generate_time], [have_uuid=yes])
--          PY_CHECK_LIB([uuid], [uuid_generate_time_safe],
--            [have_uuid=yes
--            AC_DEFINE([HAVE_UUID_GENERATE_TIME_SAFE], [1]) ]) ])
-+          PY_CHECK_LIB([uuid], [uuid_generate_time_safe], [
-+            have_uuid=yes
-+            ac_cv_have_uuid_generate_time_safe=yes
-+          ])])
-         AS_VAR_IF([have_uuid], [yes], [
-           LIBUUID_CFLAGS=${LIBUUID_CFLAGS-""}
-           LIBUUID_LIBS=${LIBUUID_LIBS-"-luuid"}
-@@ -3785,14 +3797,90 @@ AS_VAR_IF([have_uuid], [missing], [
-   AC_CHECK_HEADERS([uuid/uuid.h], [
-     AC_CHECK_FUNC([uuid_generate_time], [
-       have_uuid=yes
-+      ac_cv_have_uuid_uuid_h=yes
-       LIBUUID_CFLAGS=${LIBUUID_CFLAGS-""}
-       LIBUUID_LIBS=${LIBUUID_LIBS-""}
-     ])
-   ])
- ])
- 
-+AS_VAR_IF([ac_cv_have_uuid_h], [yes], [AC_DEFINE([HAVE_UUID_H], [1])])
-+AS_VAR_IF([ac_cv_have_uuid_uuid_h], [yes], [AC_DEFINE([HAVE_UUID_UUID_H], [1])])
-+AS_VAR_IF([ac_cv_have_uuid_generate_time_safe], [yes], [
-+  AC_DEFINE([HAVE_UUID_GENERATE_TIME_SAFE], [1])
-+])
-+
-+# gh-124228: While the libuuid library is available on NetBSD, it supports only UUID version 4.
-+# This restriction inhibits the proper generation of time-based UUIDs.
-+if test "$ac_sys_system" = "NetBSD"; then
-+  have_uuid=missing
-+  AC_DEFINE([HAVE_UUID_H], [0])
-+fi
-+
- AS_VAR_IF([have_uuid], [missing], [have_uuid=no])
- 
-+# gh-132710: The UUID node is fetched by using libuuid when possible
-+# and cached. While the node is constant within the same process,
-+# different interpreters may have different values as libuuid may
-+# randomize the node value if the latter cannot be deduced.
-+#
-+# Consumers may define HAVE_UUID_GENERATE_TIME_SAFE_STABLE_MAC
-+# to indicate that libuuid is unstable and should not be relied
-+# upon to deduce the MAC address.
-+AC_DEFUN([PY_EXTRACT_UUID_GENERATE_TIME_SAFE_MAC], [WITH_SAVE_ENV([
-+  # Be sure to add the extra include path if we used pkg-config
-+  # as HAVE_UUID_H may be set even though <uuid.h> is only reachable
-+  # by adding extra -I flags.
-+  #
-+  # If the following script does not compile, we simply assume that
-+  # libuuid is missing.
-+  CFLAGS="$CFLAGS $LIBUUID_CFLAGS"
-+  LIBS="$LIBS $LIBUUID_LIBS"
-+  AC_RUN_IFELSE([AC_LANG_SOURCE([[
-+    #include <inttypes.h>   // PRIu64
-+    #include <stdint.h>     // uint64_t
-+    #include <stdio.h>      // fopen(), fclose()
-+
-+    #ifdef HAVE_UUID_H
-+    #include <uuid.h>
-+    #else
-+    #include <uuid/uuid.h>
-+    #endif
-+
-+    #define ERR 1
-+    int main(void) {
-+        uuid_t uuid;  // unsigned char[16]
-+        (void)uuid_generate_time_safe(uuid);
-+        uint64_t node = 0;
-+        for (size_t i = 0; i < 6; i++) {
-+            node |= (uint64_t)uuid[15 - i] << (8 * i);
-+        }
-+        FILE *fp = fopen("conftest.out", "w");
-+        if (fp == NULL) {
-+            return ERR;
-+        }
-+        int rc = fprintf(fp, "%" PRIu64 "\n", node) >= 0;
-+        rc |= fclose(fp);
-+        return rc == 0 ? 0 : ERR;
-+    }]])], [
-+      AS_VAR_SET([$1], [`cat conftest.out`])
-+    ], [], []
-+  )])])
-+
-+if test "$have_uuid" = "yes" -a "$HAVE_UUID_GENERATE_TIME_SAFE" = "1"
-+then
-+  AC_MSG_CHECKING([if uuid_generate_time_safe() node value is stable])
-+  PY_EXTRACT_UUID_GENERATE_TIME_SAFE_MAC([py_cv_uuid_node1])
-+  PY_EXTRACT_UUID_GENERATE_TIME_SAFE_MAC([py_cv_uuid_node2])
-+  if test -n "$py_cv_uuid_node1" -a "$py_cv_uuid_node1" = "$py_cv_uuid_node2"
-+  then
-+    AC_DEFINE([HAVE_UUID_GENERATE_TIME_SAFE_STABLE_MAC], [1])
-+    AC_MSG_RESULT([stable])
-+  else
-+    AC_MSG_RESULT([unstable])
-+  fi
-+fi
-+
- # 'Real Time' functions on Solaris
- # posix4 on Solaris 2.6
- # pthread (first!) on Linux
-diff --git a/pyconfig.h.in b/pyconfig.h.in
-index 3c16c694c84599..73358a0f35ae82 100644
---- a/pyconfig.h.in
-+++ b/pyconfig.h.in
-@@ -1548,6 +1548,9 @@
- /* Define if uuid_generate_time_safe() exists. */
- #undef HAVE_UUID_GENERATE_TIME_SAFE
- 
-+/* Define if uuid_generate_time_safe() is able to deduce a MAC address. */
-+#undef HAVE_UUID_GENERATE_TIME_SAFE_STABLE_MAC
-+
- /* Define to 1 if you have the <uuid.h> header file. */
- #undef HAVE_UUID_H
- 
-
-From cb0f32a7d64b6dc4a63c4a683bb52a97ebe1d78a Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?=
- <10796600+picnixz@users.noreply.github.com>
-Date: Mon, 26 May 2025 12:34:00 +0200
-Subject: [PATCH 2/2] rgen
-
----
- configure | 25 ++++++-------------------
- 1 file changed, 6 insertions(+), 19 deletions(-)
-
-diff --git a/configure b/configure
-index cc976aafc09b34..47e4f29e23a7ac 100755
---- a/configure
-+++ b/configure
-@@ -13735,14 +13735,7 @@ else
- 	LIBUUID_LIBS=$pkg_cv_LIBUUID_LIBS
-         { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
- printf "%s\n" "yes" >&6; }
--<<<<<<< HEAD
- 	            have_uuid=yes
--      printf "%s\n" "#define HAVE_UUID_H 1" >>confdefs.h
--
--      printf "%s\n" "#define HAVE_UUID_GENERATE_TIME_SAFE 1" >>confdefs.h
--
--=======
--                    have_uuid=yes
-       ac_cv_have_uuid_generate_time_safe=yes
-       # The uuid.h file to include may be <uuid.h> *or* <uuid/uuid.h>.
-       # Since pkg-config --cflags uuid may return -I/usr/include/uuid,
-@@ -13753,7 +13746,6 @@ printf "%s\n" "yes" >&6; }
-       # #include <uuid.h> can be written, *without* assuming extra
-       # include path.
-       ac_cv_have_uuid_h=yes
-->>>>>>> 3bffada4672 (gh-132710: only use stable `_uuid.generate_time_safe()` to deduce MAC address (#132901))
- 
- fi
- 
-@@ -13787,8 +13779,6 @@ done
- 
- fi
- 
--<<<<<<< HEAD
--=======
- if test "x$ac_cv_have_uuid_h" = xyes
- then :
-   printf "%s\n" "#define HAVE_UUID_H 1" >>confdefs.h
-@@ -13815,7 +13805,6 @@ if test "$ac_sys_system" = "NetBSD"; then
- 
- fi
- 
-->>>>>>> 3bffada4672 (gh-132710: only use stable `_uuid.generate_time_safe()` to deduce MAC address (#132901))
- if test "x$have_uuid" = xmissing
- then :
-   have_uuid=no
-@@ -13853,8 +13842,8 @@ save_LIBS=$LIBS
- then :
- 
- 
--else case e in #(
--  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-+else $as_nop
-+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
- /* end confdefs.h.  */
- 
-     #include <inttypes.h>   // PRIu64
-@@ -13891,8 +13880,7 @@ then :
- 
- fi
- rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
--  conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
--esac
-+  conftest.$ac_objext conftest.beam conftest.$ac_ext
- fi
- 
- CFLAGS=$save_CFLAGS
-@@ -13919,8 +13907,8 @@ save_LIBS=$LIBS
- then :
- 
- 
--else case e in #(
--  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-+else $as_nop
-+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
- /* end confdefs.h.  */
- 
-     #include <inttypes.h>   // PRIu64
-@@ -13957,8 +13945,7 @@ then :
- 
- fi
- rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
--  conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
--esac
-+  conftest.$ac_objext conftest.beam conftest.$ac_ext
- fi
- 
- CFLAGS=$save_CFLAGS
diff --git a/pythonbuild/downloads.py b/pythonbuild/downloads.py
index 78a24011..7d80e348 100644
--- a/pythonbuild/downloads.py
+++ b/pythonbuild/downloads.py
@@ -73,10 +73,10 @@
         "python_tag": "cp312",
     },
     "cpython-3.13": {
-        "url": "https://www.python.org/ftp/python/3.13.5/Python-3.13.5.tar.xz",
-        "size": 22856016,
-        "sha256": "93e583f243454e6e9e4588ca2c2662206ad961659863277afcdb96801647d640",
-        "version": "3.13.5",
+        "url": "https://www.python.org/ftp/python/3.13.6/Python-3.13.6.tar.xz",
+        "size": 22761268,
+        "sha256": "17ba5508819d8736a14fbfc47d36e184946a877851b2e9c4b6c43acb44a3b104",
+        "version": "3.13.6",
         "licenses": ["Python-2.0", "CNRI-Python"],
         "license_file": "LICENSE.cpython.txt",
         "python_tag": "cp313",

From 4cfefb552ebbe0f935cecc9669714f02568347d4 Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Thu, 7 Aug 2025 08:03:34 -0500
Subject: [PATCH 154/157] Fix label subsetting (#731)

Regressed in #716
---
 .github/workflows/linux.yml   | 2 +-
 .github/workflows/macos.yml   | 2 +-
 .github/workflows/windows.yml | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml
index 2d8c8a15..edd5acbd 100644
--- a/.github/workflows/linux.yml
+++ b/.github/workflows/linux.yml
@@ -173,7 +173,7 @@ jobs:
         run: |
           uv run ci-matrix.py \
             --platform linux \
-            --labels '${STEPS_GET_LABELS_OUTPUTS_LABELS}' \
+            --labels "${STEPS_GET_LABELS_OUTPUTS_LABELS}" \
             --max-shards 2 \
             ${{ (steps.check-pythonbuild.outputs.changed == 'true' || github.ref == 'refs/heads/main') && '--force-crate-build' || '' }} \
             > matrix.json
diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml
index 0bc73b13..02ce471d 100644
--- a/.github/workflows/macos.yml
+++ b/.github/workflows/macos.yml
@@ -90,7 +90,7 @@ jobs:
       - name: Generate build matrix
         id: set-matrix
         run: |
-          uv run ci-matrix.py --platform darwin --labels '${STEPS_GET_LABELS_OUTPUTS_LABELS}' ${{ (steps.check-pythonbuild.outputs.changed == 'true' || github.ref == 'refs/heads/main') && '--force-crate-build' || '' }} > matrix.json
+          uv run ci-matrix.py --platform darwin --labels "${STEPS_GET_LABELS_OUTPUTS_LABELS}" ${{ (steps.check-pythonbuild.outputs.changed == 'true' || github.ref == 'refs/heads/main') && '--force-crate-build' || '' }} > matrix.json
 
           # Extract python-build matrix
           echo "matrix=$(jq -c '."python-build"' matrix.json)" >> $GITHUB_OUTPUT
diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml
index 14840f46..847a82e8 100644
--- a/.github/workflows/windows.yml
+++ b/.github/workflows/windows.yml
@@ -90,7 +90,7 @@ jobs:
       - name: Generate build matrix
         id: set-matrix
         run: |
-          uv run ci-matrix.py --platform windows --labels '${STEPS_GET_LABELS_OUTPUTS_LABELS}' ${{ (steps.check-pythonbuild.outputs.changed == 'true' || github.ref == 'refs/heads/main') && '--force-crate-build' || '' }} > matrix.json
+          uv run ci-matrix.py --platform windows --labels "${STEPS_GET_LABELS_OUTPUTS_LABELS}" ${{ (steps.check-pythonbuild.outputs.changed == 'true' || github.ref == 'refs/heads/main') && '--force-crate-build' || '' }} > matrix.json
 
           # Extract python-build matrix
           echo "matrix=$(jq -c '."python-build"' matrix.json)" >> $GITHUB_OUTPUT

From 281d11620539c54ad3dd9d35b727109d36c644f6 Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Thu, 7 Aug 2025 13:41:48 -0500
Subject: [PATCH 155/157] Persist credentials in the release workflow (#729)

Co-authored-by: William Woodruff <william@astral.sh>
---
 .github/workflows/release.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index f4036a02..37edc1ba 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -38,7 +38,7 @@ jobs:
       - uses: actions/checkout@v4
         with:
           submodules: recursive
-          persist-credentials: false
+          persist-credentials: true # needed for git operations below
 
       - uses: extractions/setup-just@e33e0265a09d6d736e2ee1e0eb685ef1de4669ff # v2
 

From cb554c8f75d2cd9e4828c753c1977b7c4d3a72e6 Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Thu, 7 Aug 2025 13:47:53 -0500
Subject: [PATCH 156/157] Use a larger runner again for the release (#733)

We need more disk space.

Partially reverts
https://github.com/astral-sh/python-build-standalone/commit/a376f32981a4e690963fe29a6ae31203afb440ae
though I'm using an 8-core instead of 16-core runner and Depot instead
of GitHub.
---
 .github/workflows/release.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 37edc1ba..9c256ee7 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -25,7 +25,7 @@ jobs:
     name: Release
     env:
       GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-    runs-on: ubuntu-latest
+    runs-on: depot-ubuntu-24.04-8
 
     permissions:
       contents: write

From 7c96f41400198c589039c6e08b12af2340f7a13c Mon Sep 17 00:00:00 2001
From: Zanie Blue <contact@zanie.dev>
Date: Thu, 7 Aug 2025 13:48:03 -0500
Subject: [PATCH 157/157] Add more artifacts to the skip list (#732)

I noticed we were fetching these but... we shouldn't be :)
---
 src/github.rs | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/src/github.rs b/src/github.rs
index 676104f9..5db22472 100644
--- a/src/github.rs
+++ b/src/github.rs
@@ -259,6 +259,9 @@ pub async fn command_fetch_release_distributions(args: &ArgMatches) -> Result<()
         for artifact in artifacts {
             if matches!(artifact.name.as_str(), "pythonbuild" | "toolchain")
                 || artifact.name.contains("install-only")
+                || artifact.name.contains("dockerbuild")
+                || artifact.name.contains("crate-")
+                || artifact.name.contains("image-")
             {
                 continue;
             }
